3 回答

TA貢獻1946條經驗 獲得超4個贊
基于維基百科上找到的轉換函數:
import math
def freq_to_note(freq):
? ? notes = ['A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#']
? ? note_number = 12 * math.log2(freq / 440) + 49??
? ? note_number = round(note_number)
? ? ? ??
? ? note = (note_number - 1 ) % len(notes)
? ? note = notes[note]
? ??
? ? octave = (note_number + 8 ) // len(notes)
? ??
? ? return note, octave
示例:freq_to_note(440)返回('A', 4)
另一種方法是使用可用的包。
您可以使用 librosa 包:
import librosa
librosa.hz_to_note(440.0)
# will return ['A5']
或者我寫的一個小包,名為 freq_note_converter:
import freq_note_converter
freq_note_converter.from_freq(440).note
# will return 'A'
順便說一句,它們都支持舍入,例如 430 或 450 仍然會返回“A”。

TA貢獻1963條經驗 獲得超6個贊
這是您需要的所有音樂信息,以便能夠導出一個公式,告訴您給定頻率距 A4 有多少個半色調:
A4 為 440 Hz(不是 400)。
任何兩個相鄰半色調的頻率之間的比率是恒定的(例如A/Ab和Bb/A給出相同的數字)。
相距一個八度的兩個音調的頻率之比為 2。
一個八度中有十二個半音。
(最后兩點將讓您弄清楚第二點中的常數比率是多少。)
或者,您可以使用它來編寫一個程序,該程序只需從 A4 向上或向下“步進”,直到達到(或通過)給定頻率。

TA貢獻1852條經驗 獲得超7個贊
在音樂理論中,通常的定義是每個八度有12個音符,上升一個八度會使頻率加倍,A4被定義為440 Hz。同樣重要的是要注意音符均勻分布在八度內。
使用這個定義,我們可以編寫一個函數,當給定頻率時,該函數返回音符和八度音程。
由于從 A4 到 A5 會乘以 2,并且我們需要均勻分布音符,這意味著向上移動音符必須恰好是加倍的 12 倍,因此從 A4 到 B4 必須乘以頻率2 的 12 次方根 ( 2**(1/12))。
編寫這樣的函數并不簡單,但也不難。我認為,雖然有時不給出解決方案本身更有利于學習,但在這種情況下,我最好展示解決方案并解釋每個部分。
import math
def frequency_to_note(frequency):
# define constants that control the algorithm
NOTES = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'] # these are the 12 notes in each octave
OCTAVE_MULTIPLIER = 2 # going up an octave multiplies by 2
KNOWN_NOTE_NAME, KNOWN_NOTE_OCTAVE, KNOWN_NOTE_FREQUENCY = ('A', 4, 440) # A4 = 440 Hz
# calculate the distance to the known note
# since notes are spread evenly, going up a note will multiply by a constant
# so we can use log to know how many times a frequency was multiplied to get from the known note to our note
# this will give a positive integer value for notes higher than the known note, and a negative value for notes lower than it (and zero for the same note)
note_multiplier = OCTAVE_MULTIPLIER**(1/len(NOTES))
frequency_relative_to_known_note = frequency / KNOWN_NOTE_FREQUENCY
distance_from_known_note = math.log(frequency_relative_to_known_note, note_multiplier)
# round to make up for floating point inaccuracies
distance_from_known_note = round(distance_from_known_note)
# using the distance in notes and the octave and name of the known note,
# we can calculate the octave and name of our note
# NOTE: the "absolute index" doesn't have any actual meaning, since it doesn't care what its zero point is. it is just useful for calculation
known_note_index_in_octave = NOTES.index(KNOWN_NOTE_NAME)
known_note_absolute_index = KNOWN_NOTE_OCTAVE * len(NOTES) + known_note_index_in_octave
note_absolute_index = known_note_absolute_index + distance_from_known_note
note_octave, note_index_in_octave = note_absolute_index // len(NOTES), note_absolute_index % len(NOTES)
note_name = NOTES[note_index_in_octave]
return (note_name, note_octave)
所以現在frequency_to_note(440)返回('A', 4),并frequency_to_note(740)返回('F#', 5),這似乎是正確的。
值得注意的是,這個函數并不關心哪個八度音階有意義,所以像frequency_to_note(1)returns之類的東西('C', -4),因為如果我們確實有一架鋼琴,通常使用八度音階 1-7,并向左側添加 5 個八度音階,則 C請注意,最左邊的八度確實是 1 Hz。因此,根據您的用例,如果八度不在 1 到 7 之間,您可能希望在最后引發異常。
添加回答
舉報