在 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 音高表示 )

C Pitchshifter 使用 libsamplerate

在 Windows 中更改原始波形数据的音高