python - 计算给定谐波节点或多个节点的结果频率,四舍五入到小于 n 的最接近的谐波

标签 python algorithm math signal-processing physics

我正在开发一种音乐创作工具,我需要弄清楚如果我在一个或多个位置触摸(创建和声节点)某个任意音高的弦,所产生的频率会是多少。

这些位置需要以 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/

相关文章:

python - 有效地模糊搜索大量数据?

Javascript计算公式

c++ - 使用C++查找直线中的第三个点

python - Pandas :如何索引行?

python - 如何绘制非数字列的直方图 w.r.t pandas 数据框中的另一个计算列?

python - tkinter TreeView : get selected item values

arrays - 混淆 "Find a pair with the given difference"中的时间复杂度

json - 如何从文本中提取需要的信息?

java - 关于动态规划我需要了解什么?

c - 在 C 中保留输入值?