python - 产生颤音正弦波

标签 python audio python-3.x trigonometry

我试图通过在两个430Hz和450Hz之间振荡来创建颤音,并将16位样本存储在列表wav中。但是,可听频率似乎增加了整个剪辑的振荡范围。有人知道为什么吗?

编辑:重写代码以使其更清晰/简洁

# vibrato.py

maxamp = 2**15 - 1 # max signed short
wav = []
(t, dt) = (0, 1 / 44100)
while t < 6.0:
  f = 440 + 10 * math.sin(2 * math.pi * 6 * t)
  samp = maxamp * math.sin(2 * math.pi * f * t)
  wav.append(samp)
  t += dt

-

更新:因为响应使用numpy,所以我将更新纯Python3的代码
# vibrato.py

maxamp = 2**15 - 1 # max signed short
wav = []
(t, dt) = (0, 1 / 44100)
phase = 0
while t < 6.0:
  f = 440 + 10 * math.sin(2 * math.pi * 6 * t)
  phase += 2 * math.pi * f * t
  samp = maxamp * math.sin(phase)
  wav.append(samp)
  t += dt

最佳答案

这个问题与隐含的相位变化以及频率变化有关。简而言之,当您计算相对于时间线中每个点的响应时,请务必注意,振荡的相位对于每个频率在每个时间都会有所不同(除了起点都相同)。因此,在频率之间移动就像在不同相位之间移动一样。对于在两个不同频率之间移动的情况,可以通过基于频率变化来调整整个信号相位来进行事后校正。我已经解释了此in another answer,因此在这里不再赘述,而在这里仅显示突出显示问题的初始图解以及如何解决问题。在这里,主要要添加的是一个好的诊断图的重要性,而正确的图就是一个频谱图。

这是一个例子:

import numpy as np

dt = 1./44100
time = np.arange(0., 6., dt)
frequency = 440. - 10*np.sin(2*math.pi*time*1.)  # a 1Hz oscillation
waveform = np.sin(2*math.pi*time*frequency)

Pxx, freqs, bins, im = plt.specgram(waveform, NFFT=4*1024, Fs=44100, noverlap=90, cmap=plt.cm.gist_heat) 
plt.show()

请注意,频率振荡的跨度正在增加(如您最初听到的)。应用上面链接的更正将得出:
dt = 1./defaults['framerate']
time = np.arange(0., 6., dt)
frequency = 440. - 10*np.sin(2*math.pi*time*1.)  # a 1Hz oscillation
phase_correction = np.add.accumulate(time*np.concatenate((np.zeros(1), 2*np.pi*(frequency[:-1]-frequency[1:]))))
waveform = np.sin(2*math.pi*time*frequency + phase_correction)

我希望这更接近预期的目标。

对此进行概念化的另一种方法,可能是在遍历每个时间步长的上下文中(如OP所做的那样),并且与物理模型更接近,这可能是在每个步长跟踪相位并确定新的幅度考虑上一步的幅度和相位,并将其与新频率组合。我没有耐心让它在纯Python中运行,但是在numpy中,解决方案看起来像这样,并给出了类似的结果:
dt = 1./44100
time = np.arange(0., 6., dt)
f = 440. - 10*np.sin(2*math.pi*time*1.)  # a 1Hz oscillation
delta_phase = 2 * math.pi * f * dt
phase = np.cumsum(delta_phase)  # add up the phase differences along timeline (same as np.add.accumulate)
wav = np.sin(phase)

关于python - 产生颤音正弦波,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28185219/

相关文章:

python - 除了被零除之外,double_scalars 遇到溢出的原因是什么?

silverlight - 使用Silverlight 2进行短时音频缓存

java - Android AudioRecord.stop()导致崩溃

python - iter_content() 函数到底做了什么?

python - 如何使用 python 中的公共(public)字段组合来自不同行的值?更新

python - 跨行对 Pandas 数据框进行分组

python - PyQt 和 py2exe : no sound from QSound after compiling to . exe

Python:我是否必须使用 else 语句(除非代码强制)?

python - 在 Python 中加载大型 JCON 文件 - 错误 = JSONDecodeError : Extra data

c++ - 在 C/C+ 中将 16 位线性 PCM 音频转换为 32 位 float 的最佳方式?