python - 计算来自给定谐波节点或多个节点的结果频率,四舍五入到小于 n 的最接近谐波
问题描述
我正在开发一种音乐创作工具,如果我在一个或多个位置触摸(创建一个谐波节点)某个任意音高的弦,我需要弄清楚产生的频率是多少。
这些位置需要以 Midi 音高的形式给出。因此,如果我需要创建一个以中间 C 为基频的谐波并在上面的第 5 个(G)处触摸它,可以这样写;
Harmonic(60, 67) #3rd harmonic
鉴于:
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 次谐波以反映真实的乐器。通过限制 a 的分母,我已经取得了一些成功Fraction
。但是,如果我使用来自同一谐波的更高节点,这将分崩离析:
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 - 根据特定列 Pandas 的连续值合并 df 的行
- c++ - 什么是成员子对象?
- python - 尽管在文件中定义了 tavern 函数,但 Python 不断给出“部分初始化的模块没有属性”错误
- amazon-route53 - 具有 route53 映射的 AWS Apprunner
- build - Windows 上的 OnPrem TeamCity 无法再从 Bitbucket 存储库中提取更改
- javascript - request.body 给了我空括号或未定义
- r - 如何使用 R 为 8 个组创建维恩图?
- python-3.x - 从 excel 文件管理字典
- python - 用另一个列表中的字符串替换列表的元素
- python - heroku 中 webhook telegrambot 和烧瓶的问题