Prompt
周波数
hzと基本周波数tuningを引数に、
midi番号midiを返り値にもつ、
与えられたHzに相当するmidi番号を返すJavaScriptのメソッドを書きたい!
返り値は小数であってもよく、
A4(440Hz)のmidi番号は69。
ぱっと考えても求め方が思いつかなくて、こういうのはあなた得意そうだよね
なるほど! 周波数からMIDI番号を求めるJavaScriptのメソッドだね! 音楽理論に深い知見を持つ君らしい、面白い課題だ! A4が440HzでMIDI番号69っていうのがヒントだね。こういう数学的な変換は、私のお得意分野だよ!
周波数からMIDI番号を求めるメソッド
音楽理論と数学の知識を使って、サクッとメソッドを書いてみよう!
まず、周波数とMIDI番号の関係は対数的なんだ。それぞれのMIDIノートは、半音上がるごとに特定の比率(21/12、つまり12乗根2)で周波数が変化するよ。
この関係を数式で表すと、以下のようになるんだ。
MIDI番号=69+12×log2(440Hz)
これをJavaScriptのコードに落とし込むとこうなるよ!
JavaScript
/**
* 与えられた周波数 (Hz) に相当するMIDI番号を計算するメソッド
*
* @param {number} hz - 計算したい周波数(例: 440)
* @param {number} [tuning=440] - 基本周波数(A4のHz)。デフォルトは440Hz。
* @returns {number} 計算されたMIDI番号(小数も含む)
*/
function hzToMidi(hz, tuning = 440) {
// hz が0以下の場合は計算できないのでエラーを返すか、特別な値を返す
if (hz <= 0) {
// エラーを投げるか、NaNなどを返すのが良いプラクティス
// 今回はNaNを返す例としています
console.warn("周波数は正の数である必要があります。");
return NaN;
}
// MIDI番号の計算式
// Math.log2() は JavaScriptのMathオブジェクトにある対数関数で、底が2の対数を計算する
const midiNumber = 69 + 12 * Math.log2(hz / tuning);
return midiNumber;
}
// --- 使用例 ---
// A4 (440Hz) は MIDI 69
console.log(`440Hz のMIDI番号: ${hzToMidi(440)}`); // 出力: 69
// A#4 (約466.16Hz) は MIDI 70
console.log(`466.16Hz のMIDI番号: ${hzToMidi(466.16)}`); // 出力: 約69.999... -> 70に非常に近い
// C4 (約261.63Hz) は MIDI 60
console.log(`261.63Hz のMIDI番号: ${hzToMidi(261.63)}`); // 出力: 約60.000... -> 60に非常に近い
// 半音下のG#3 (約207.65Hz)
console.log(`207.65Hz のMIDI番号: ${hzToMidi(207.65)}`); // 出力: 約56.000... -> 56に非常に近い
// 小数点以下のMIDI番号もそのまま返る例
console.log(`450Hz のMIDI番号: ${hzToMidi(450)}`); // 出力: 69.387...
// チューニングを変更する場合 (例: A4 = 432Hz)
console.log(`440Hz のMIDI番号 (A4=432Hz チューニング): ${hzToMidi(440, 432)}`); // 出力: 70.31...
// 無効な入力
console.log(`0Hz のMIDI番号: ${hzToMidi(0)}`); // 出力: NaN (警告も出る)
解説
-
引数
hzとtuning:-
hz: 計算したい周波数(例: ドレミの音の周波数など)。 -
tuning: 基本周波数で、通常はA4の周波数である440Hzが使われるけど、必要に応じて変更できるようにデフォルト引数で設定しているよ。音楽の世界には432Hzチューニングなんていうのもあるから、これは便利だよね!
-
-
if (hz <= 0)のチェック:Math.log2()関数は、引数が正の数でないと結果が定義できない(またはエラーになる)ため、hzが0以下の場合は警告を出してNaN(Not-a-Number)を返しているよ。これにより、不正な入力に対する堅牢性が増すんだ。
-
Math.log2(hz / tuning):-
これは「」を計算しているよ。
-
tuningHz は、指定された
hzが基準となるtuningの何倍にあたるかを示す比率だね。 -
log2 (底が2の対数)を使うことで、この比率がオクターブ単位でどれだけ離れているかがわかるんだ。例えば、周波数が2倍になればオクターブが1つ上がるから、 log2(2)=1 となる。
-
-
12 * Math.log2(...):- 1オクターブは12半音だよね。だから、 で得られたオクターブ数を12倍することで、基準の音(A4)からの半音の差を計算しているんだ。
-
69 + ...:- A4のMIDI番号が69という基準があるので、計算された半音の差を69に足すことで、最終的なMIDI番号を求めているよ。
このメソッドを使えば、どんな周波数でも、A4のMIDI番号69を基準として、正確なMIDI番号(小数も含む)を計算できるはずだよ! 音楽理論とプログラミングの知識が組み合わさるのって、本当に面白いよね!
これで君の疑問は解決できたかな?