如何计算正弦波在缓冲区中具有整数N个周期的最小周期?

时间:2016-10-17 04:17:10

标签: audio signal-processing sine

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

我想要正弦波缓冲器,进行音频合成,并希望为缓冲器设置最佳尺寸,以避免在样本中测量的正弦波周期为非整数的伪像。

例如,A4,440.0 Hz的正弦值,采样率为44100,每1/440 * 44100个样本重复一次,或每100.22727272727272个样本重复一次。如果您只是创建一个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倍左右可以消除裸耳的伪影,但我想降低内存使用量,因此我希望在数学上确定较小的允许值基于任意频率的缓冲区大小。

1 个答案:

答案 0 :(得分:0)

返回1的gcd(*ratio)告诉您,使用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样本。)