简体   繁体   English

找到具有非线性进展的最近值

[英]Find the nearest value with a non-linear progression

This is a little complicated, but bear with me. 这有点复杂,但请耐心等待。 I am trying to create a map that links the names of musical notes with their corresponding frequencies. 我正在尝试创建一个地图,将音符的名称与相应的频率相关联。 Then I want to write a function that when provided a random frequency will return the note that is closest to that frequency. 然后我想编写一个函数,当提供随机频率时,将返回最接近该频率的音符。

The problem with this is that the frequencies of the notes are not generated with a linear formula, and therefore the frequency that is the exact middle between each note is not linear as well. 这个问题是音符的频率不是用线性公式生成的,因此每个音符之间的确切中间频率也不是线性的。 (This basically means that the midpoint between notes is not perfectly in the middle so finding the midpoint by normal methods does not work.) (这基本上意味着音符之间的中点不完全在中间,因此通过常规方法找到中点不起作用。)

Some sample code used to generate the map of notes: 一些示例代码用于生成注释地图:

// Ordered starting with "B" so notes line up with frequencies
vector<string> names = {
    "B", "C", "C#/Db", "D", "D#/Eb", "E", "F", "F#/Gb", "G", "G#/Ab", "A", "A#/Bb"
};

double f0 = 440;
map<string, map<int, double> > notes;

// Map notes to their corresponding frequencies
for (int octave = 0; octave < 10; ++octave) {
    for (int index = 0; index < names.size(); ++index) {

        // Get the exact frequency of the musical note
        double frequency               = f0*pow(pow(2, 1.0/12), index       - 10)*pow(pow(2, 1.0/12), 12*(octave + 1 - 5));

        // Get the exact frequency between this note and the next (I'm not doing anything with this yet, but I feel like this is on the right track.)
        double frequency_between_notes = f0*pow(pow(2, 1.0/12), index + 0.5 - 10)*pow(pow(2, 1.0/12), 12*(octave + 1 - 5));

        notes[names[index]][octave] = frequency;
    }
}

I want to write a function that given a random frequency it will return the note that is closest to that frequency. 我想编写一个给定随机频率的函数,它将返回最接近该频率的音符。

Note& find_note(double frequency) {
    // Provided a random frequency find the ACTUAL nearest note using the non-linear formula that notes are calculated from.
    // Create the note object and return it.
}

The Note class looks something like this: Note类看起来像这样:

class Note {
public:
    Note(string name, int octave, double frequency) {
        name_      = name;
        octave_    = octave;
        frequency_ = frequency;
    }

    const string& get_name() const {
        return name_;
    }

    const int& get_octave() const {
        return octave_;
    }

    const double& get_frequency() const {
        return frequency_;
    }
private:
    string name_;
    int    octave_;
    double frequency_;
};

The equation used to calculate the frequencies of the notes came from https://pages.mtu.edu/~suits/NoteFreqCalcs.html . 用于计算票据频率的公式来自https://pages.mtu.edu/~suits/NoteFreqCalcs.html

How can I find the nearest note given a random frequency? 如何以随机频率找到最近的音符?

The logarithm of the frequencies of the semitones are evenly spaced. 半音频率的对数均匀分布。 To find the closest note to a given frequency, just take the log of the frequency and find closest log of a note frequency. 要找到与给定频率最接近的音符,只需记录频率的对数并找到音符频率的最接近的对数。

Here is a simple function that takes a frequency in Hz and returns the closest semitone, as a number of semitones above (positive) or below (negative) A4 (440Hz) 这是一个简单的函数,它采用以Hz为单位的频率并返回最接近的半音,作为高于(正)或低于(负)A4(440Hz)的半音数

const double LOG_SEMITONE = log(2.0)/12.0;

int getNote(double f)
{
    double note = log(f/440.0) / LOG_SEMITONE;
    return (int)round(note);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM