在Numpy中实现正弦波滑音从一个音高到另一个音高
我正在做一个程序,需要让一个正弦波的音调从一个音调慢慢平滑地变化到另一个音调。我已经能得到一个数组,里面是每个时刻应该达到的频率(比如说,[440, 526.5, 634.2, 794.8, 880],不过这个数组要长得多),但我似乎无法把这些频率真正应用到波形上。我尝试的方法是:
numpy.sin(2*math.pi*x*freq/self.sample_rate)
这里的“freq”就是频率数组,而x是一个枚举数组([0, 1, 2, 3, 4...])。这个方法有点效果,但它会让频率超过预期的值,然后再回落。我在这个问题上已经努力了很久,但一直找不到更合适的方法。有没有什么建议?我表达我的困惑是否清楚呢?
谢谢。
2 个回答
0
我喜欢把频率想象成你在声音样本中移动的速度——在这个例子中是正弦波。这里有一段Python代码,试图实现你想要的功能。我们假设freq()
这个方法是根据时间来给出频率的。为了你的需求,它会是某种指数函数。我们正在尝试填充一个叫wave
的预先分配好的列表。
index = 0
t = 0
while t < len(wave):
wave[t] = math.sin(2*math.pi*index/sample_rate)
t = t+1
index = index + freq(t/sample_rate)
请原谅我的Python代码,我还在学习这门语言。
11
问题在于,当你逐渐改变频率时,每个频率在特定时间点的相位都是不同的。当你快速而连续地切换这些相位时,会让正弦波的频率变得更高(当然也可以变得更低)。
比如说,如果你想瞬间改变频率,你需要进行相位修正,公式是 p_1 = p_0 + 2*pi*t*(f_0-f_1)
,这样才能确保在时间 t
时相位是对齐的。当你一步一步地进行这个操作时,每次都需要进行类似的相位修正,每次的修正都会在之前的基础上增加。
下面是结果图,代码在下方。最上面的图是频率,中间的是没有相位修正的情况,底部的是经过连续相位修正的情况。
from pylab import *
sample_rate = .001
f0, f1 = 10, 20
t_change = 2
times = arange(0, 4, sample_rate)
ramp = 1./(1+exp(-6.*(times-t_change)))
freq = f0*(1-ramp)+f1*ramp
phase_correction = add.accumulate(times*concatenate((zeros(1), 2*pi*(freq[:-1]-freq[1:]))))
figure()
subplot(311)
plot(times, freq)
subplot(312)
plot(times, sin(2*pi*freq*times))
subplot(313)
plot(times, sin(2*pi*freq*times+phase_correction))
show()