我正在开发一种音乐创作工具,我需要弄清楚如果我在一个或多个位置触摸(创建和声节点)某个任意音高的弦,所产生的频率会是多少。
这些位置需要以 Midi 音调给出。因此,如果我需要创建一个以中音 C 为基音的和声,并在上面的第 5 音 (G) 上触摸它,就会这样写;
Harmonic(60, 67) #3rd harmonic
我期望返回 79,因为:
def toFreq(m):
return pow(2, (m-69)/12)
def toMidi(f):
return 12 * math.log2( f/440 ) + 69
到目前为止我已经能够实现这一点。
但是,如果我这样做:
Harmonic(60, 64) #5th harmonic
我得到了错误的答案,这是因为我想“四舍五入”下面的谐波 - 比方说 - 20 次谐波以反射(reflect)真实的乐器。通过限制分数的分母,我已经取得了一些成功。然而,如果我使用同一谐波的更高节点,这就会崩溃:
Harmonic(60, 69) # also the 5th harmonic, just a different node
我遇到的第二个问题是拥有多个这样的节点,但我没有成功地让它发挥作用。
Harmonic(60, [67, 65]) # where a 'C' string is touched at the 5th and 4th
# this is the 9th harmonic ( a compound major 2nd )
我想知道是否有人可以帮助这里的算法?实际上类和 python 的东西不是问题 - 这个算法将进入 initaliser 并设置一个成员 self.sounding - 我很高兴得到一个伪代码的答案!返回的是 MIDI 音高还是频率也并不重要,它只需要采用根音和一个或多个节点(如果更容易的话,限制为两个)。
另外,我希望我没有过度标记这个问题!
最佳答案
这个有用吗?我对所涉及的物理原理的内存相当模糊,但基本上,我们发现最低音高是所有给定 MIDI 音高的共同泛音。
import math
def freq_from_midi(m):
return 440 * 2 ** ((m - 69) / 12)
def nearest_midi_from_freq(f):
return round(12 * math.log2(f / 440) + 69)
def midi_overtones(m):
f = freq_from_midi(m)
return {nearest_midi_from_freq(h * f) for h in range(1, 21)}
def harmonic(*ms):
return min(set.intersection(*(midi_overtones(m) for m in ms)))
print(harmonic(60, 67))
print(harmonic(60, 64))
print(harmonic(60, 69))
print(harmonic(60, 67, 65))
关于python - 计算给定谐波节点或多个节点的结果频率,四舍五入到小于 n 的最接近的谐波,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65226396/