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

Python 计算给定谐波节点或多个节点的结果频率,四舍五入到小于n的最近谐波,python,algorithm,math,signal-processing,physics,Python,Algorithm,Math,Signal Processing,Physics,我正在开发一个音乐作曲工具,我需要弄清楚,如果我在一个或多个位置触摸(创建了一个谐波节点)一些任意音调的弦,结果会是什么频率 这些位置需要作为Midi音高给出。因此,如果我需要创建一个基波为中间C的谐波,并在上面的第五个(G)处触摸它,它会这样写 谐波(60,67)#三次谐波 考虑到: def toFreq(m): return pow(2, (m-69)/12) def toMidi(f): return 12 * math.log2( f/440 ) + 69 到目前为止,我

我正在开发一个音乐作曲工具,我需要弄清楚,如果我在一个或多个位置触摸(创建了一个谐波节点)一些任意音调的弦,结果会是什么频率

这些位置需要作为Midi音高给出。因此,如果我需要创建一个基波为中间C的谐波,并在上面的第五个(G)处触摸它,它会这样写

谐波(60,67)#三次谐波
考虑到:

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次谐波来反映一个真实的仪器。通过限制
分数的分母
,我在这方面取得了一些成功。但是,如果我使用来自同一谐波的更高节点,则会出现这种情况:

Harmonic(60, 69) # also the 5th harmonic, just a different node
import math                                               
    
    
def freq_from_midi(m):    
    return 440 * 2 ** ((m - 69) / 12)    
    
    
def nearest_midi_from_freq(f):    
    return  round( 2 * (12 * math.log2(f / 440) + 69 )) / 2    
    
    
def midi_overtones(m):    
    f = freq_from_midi(m)    
    return { nearest_midi_from_freq(h * f) for h in range(1, 25)}    
    
    
def midi_overtones_flexible(m):    
    float_range = lambda start, stop, step: [start + step*r for r in range(0,int((stop - start)/step))]    
    
    freqs = (freq_from_midi(m + r) for r in float_range(-0.5, 0.5, 0.125) )    
    
    return { nearest_midi_from_freq(h * f) for f in freqs for h in range(1, 25)}    
    
    
def harmonic(base, *nodes):    
    overtones_of_base = midi_overtones(base)    
    overtones_of_nodes = [midi_overtones_flexible(m) for m in nodes]    
    r = set.intersection( overtones_of_base, *overtones_of_nodes )    
    return min(r)    
    
    
print(harmonic(60, 64, 66))  
print(harmonic(60, 65, 67))    
我遇到的第二个问题是,有多个这样的节点,但我没有成功地实现这一点

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))

提交自己问题的答案。 基于David Eisenstat的答案,考虑到仪器会稍微移动节点以找到最低谐波:

Harmonic(60, 69) # also the 5th harmonic, just a different node
import math                                               
    
    
def freq_from_midi(m):    
    return 440 * 2 ** ((m - 69) / 12)    
    
    
def nearest_midi_from_freq(f):    
    return  round( 2 * (12 * math.log2(f / 440) + 69 )) / 2    
    
    
def midi_overtones(m):    
    f = freq_from_midi(m)    
    return { nearest_midi_from_freq(h * f) for h in range(1, 25)}    
    
    
def midi_overtones_flexible(m):    
    float_range = lambda start, stop, step: [start + step*r for r in range(0,int((stop - start)/step))]    
    
    freqs = (freq_from_midi(m + r) for r in float_range(-0.5, 0.5, 0.125) )    
    
    return { nearest_midi_from_freq(h * f) for f in freqs for h in range(1, 25)}    
    
    
def harmonic(base, *nodes):    
    overtones_of_base = midi_overtones(base)    
    overtones_of_nodes = [midi_overtones_flexible(m) for m in nodes]    
    r = set.intersection( overtones_of_base, *overtones_of_nodes )    
    return min(r)    
    
    
print(harmonic(60, 64, 66))  
print(harmonic(60, 65, 67))    

谢谢你,大卫

谢谢大家!!我已经发布了一个稍微修改过的版本,以考虑到触摸到的节点并不精确,并且会四舍五入到最近的节点。那和手指是无限小的!