连接不同频率的正弦波

concatenate sinusoids of varying frequency

这是我第一次处理音频,我正在尝试连接任意(数据驱动)频率的正弦波,并且无法消除由罪恶之间的不连续性引起的咔嗒声。

我正在阅读 this thread 关于使频率成为相位的函数以线性增加波的频率,但无法弄清楚如何适应任意移动频率。

我一直在研究计算前一个正弦波的相移,然后尝试相应地移动下一个,但这似乎只是让声音变得更高调,并没有消除咔哒声。

def audio_map(data):
p=[]
phase = 0 
for point in data: 
    if point[0]<0: 
        f=100*np.abs(point[0])
    else:
        f=100*point[0]
#Do something with the phase to shift the sinusoid below??? 
p=np.concatenate((p,np.sin((4*np.pi*f/sampling_rate)*np.arange(sampling_rate*np.pi/(16)))))
    phase=f*np.pi/16

return p

感谢您的帮助!!

编辑

我对你选择的正弦函数也有点困惑,它看起来不像系数或持续时间与真实世界的值相关联,我希望看到这样的东西:

p = np.concatenate((p, np.sin((2 * np.pi * f / sampling_rate) * np.arange(total_tone_time * sampling_rate) + phase)))
phase += 2 * np.pi * f * total_tone_time
phase %= 2 * np.pi  # strip off full cycles to avoid overflow

在哪里

  • total_tone_time是当前播放的音调的持续时间
  • sampling_rate 以 hz(每秒采样数)为单位

在每一项之间添加相位的目的是使合成的复合曲线保持连续,这可能有助于避免波形中出现任何爆裂声。如果您听不到任何声音,请确保输出的频率在可听范围内:http://en.wikipedia.org/wiki/Audio_frequency

我会先尝试上面的建议,然后再尝试我在下面谈论的内容,这更深入兔子洞。

/编辑

不是专家,但我认为您所说的导致点击的不连续性可能是正确的。如果是,您可以在交界处快速衰减 out/fade 幅度以避免点击。

这是我能想到的其他一些可能性。

模型与拟合

您如何对频率进行采样?它们是否在特定时间采样,因此您可以获得作为时间函数的频率?如果是这样,您可以尝试将曲线拟合到点(这是一个非常重要的问题),然后取计算曲线积分的正弦:

Sin[2 * PI * Integral[频率(时间),时间,0,current_time]]

数值积分

作为拟合曲线的替代方法,如果您的频率采样率足够快以近似于平滑曲线,您可以直接在数值积分中使用这些值。对于下面的示例,我假设您的数据采用 [[freq0, time0], [freq1, time1], ...] 的格式,并且频率样本以您想要的相同速率随时间均匀分布对输出波形进行采样。

PI = 3.14159
waveform = [0] * len(data)
phase = 0
time_delta = data[1][1] - data[0][1]
for i, (f, t) in enumerate(data):
    if i != 0:
        phase += 0.5 * (f + last_f) * time_delta
        waveform[i] = sin(2 * PI * phase)
    last_f = f
    phase %= 2 * PI

请注意,对于以上内容,我使用的是梯形方法,如下所述:http://www.mathworks.com/help/matlab/ref/trapz.html#bua4lsr

关于此方法,让我担心的一件事是您采用的是频率的绝对值,这对我来说表明您的频率可能不是从数据源中采样的,从而产生行为良好的连续函数。

添加坡道

最后,如果您要连接一个没有直接时间依赖性的随机样本的频率,您可以添加一个频率斜坡来弥补差距。

你可以尝试线性:

sin(PI * [(f2 - f1) / time_frame * t ** 2 + 2 * f1 * t])

或指数:

sin(2 * PI * time_frame * f1 * exp(log(f2 / f1) * t / time_frame) / log(f2 / f1))

哪里

  • time_frame 是您希望斜坡持续的持续时间
  • t 选择从零开始到 time_frame
  • 结束
  • f1是剩余的频率
  • f2 是输入的频率