如何计算最小周期的正弦波有整数N个周期的缓冲



我发现了一个类似的问题,但没有合适的答案。

我想要有正弦波缓冲器,做音频合成,并希望找出缓冲器的最佳大小,以避免在样本中测量的正弦波周期为非整数的工件。

例如,A4, 440.0 Hz的正弦,采样率为44100,每1/440 * 44100个样本重复一次,或每100.227272727272个样本重复一次。如果您简单地创建一个包含100(或101)个样本的循环缓冲区来包含一个正弦周期,则回放会对不相交产生明显的伪影。

根据对前一个海报版本的回应,建议的解决方案是将周期表示为整数分数,并找到最大公约数,以找到所需的周期数和样本数。然而,在实践中,我一直在寻找最大公约数为1的比率,这在我看来似乎不太可能。

使用上面的例子,在Python中:
freq = 440.0
rate = 44100
period = 1.0 / freq * rate 
ratio = period.as_integer_ratio()
from fractions import gcd
divisor = gcd(*ratio)

除数等于1,显然意味着没有公约数,意味着它需要无限的频率循环才能找到一个整数的样本来完美地存储正弦。

我做错了吗?还有别的解决办法吗?

注意,在实践中,我发现将缓冲区大小设置在实际正弦周期的1000倍左右可以消除对裸耳的伪影,但我想降低我的内存使用,因此想在数学上确定基于任意频率的更小的允许缓冲区大小。

gcd(*ratio)返回1告诉你的是你用period.as_integer_ratio()得到的分数已经被简化了,而不是"它需要频率的无限循环才能找到一个整数的样本来完美地存储正弦"。

然而,考虑到计算period = 1.0 / freq * rate时的舍入误差,这种简化可能不是那么大。您最好使用:

divisor = fractions.gcd(rate, freq)
ratio = (rate/divisor, freq/divisor)

在这一点上,因为ratio是一个简化的分数(在您的具体情况下(2205, 22)), ratio[1]循环将适合一个整数的样本(更具体地说,ratio[0]*ratio[1]或在您的具体情况下48510样本)。

最新更新