在 Numpy 中从一个音高到另一个音高的正弦波滑音
Posted
技术标签:
【中文标题】在 Numpy 中从一个音高到另一个音高的正弦波滑音【英文标题】:sine wave glissando from one pitch to another in Numpy 【发布时间】:2010-06-22 02:22:47 【问题描述】:我一直在开发一个程序,我需要缓慢而平稳地将正弦波的音高从一个音高更改为另一个音高。我能够获得音高在任何给定时刻应为的频率数组(例如,[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...])。这种方法有点工作,但是它使频率高于预期频率,然后回落。我一直在研究这个问题很长时间,在寻找更合适的方法方面一直没有取得任何进展。有什么建议吗?我是否足够清楚地表达了我的困境?
谢谢。
【问题讨论】:
你想要线性扫描还是对数扫描? 【参考方案1】:问题在于,当您通过频率时,每个频率在给定时间内实际上具有不同的相位。当您快速连续地滚动浏览这些相位时,它们会以更高的频率(或更低的频率)驱动正弦波。
例如,假设您瞬间更改了频率 - 为此,您必须提供相位校正 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()
【讨论】:
太棒了。我很高兴它现在可以满足您的需求......而且这是一个有趣的问题。【参考方案2】:我喜欢将频率视为您在声音样本中步进的速率 - 在本例中为正弦波。这是一些 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,我还在学习这门语言。
【讨论】:
以上是关于在 Numpy 中从一个音高到另一个音高的正弦波滑音的主要内容,如果未能解决你的问题,请参考以下文章
音频处理Melodyne 音高调整 ( 打开音频文件 | 选择音高编辑工具 | 样本音高信息 | 音高自动调整 )
五线谱音高表示 ( 高音谱号 | C3 60 ~ B3 71 音高表示 | C4 72 音高表示 | C5 84 音高表示 )