这有点复杂,但请耐心等待。我正在尝试创建一个地图,将音符的名称与相应的频率相关联。然后我想编写一个函数,当提供随机频率时,将返回最接近该频率的音符。
这个问题是音符的频率不是用线性公式生成的,因此每个音符之间的确切中间频率也不是线性的。 (这基本上意味着音符之间的中点不完全在中间,因此通过常规方法找到中点不起作用。)
用于生成笔记地图的一些示例代码:
// 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;
}
}
我想编写一个给定随机频率的函数,它会返回最接近该频率的音符。
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.
}
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_;
};
用于计算音符频率的公式来自https://pages.mtu.edu/~suits/NoteFreqCalcs.html。
如何以随机频率找到最近的音符?
答案 0 :(得分:6)
半音频率的对数均匀分布。要找到与给定频率最接近的音符,只需记录频率记录并找到音符频率的最接近日志。
这是一个简单的函数,它采用以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);
}