【发布时间】:2012-01-29 02:52:05
【问题描述】:
我正在尝试对音频信号进行频率调制。我可以使用以下等式 y=cos(Fc + sin(Fm)) 成功地用另一个正弦波(调制器)调频一个正弦波(载波),但是我不确定如何调频音频信号因为显然我不能使用上述公式。我的问题是:如何将输入数据与调制信号结合起来得到调频信号?
【问题讨论】:
我正在尝试对音频信号进行频率调制。我可以使用以下等式 y=cos(Fc + sin(Fm)) 成功地用另一个正弦波(调制器)调频一个正弦波(载波),但是我不确定如何调频音频信号因为显然我不能使用上述公式。我的问题是:如何将输入数据与调制信号结合起来得到调频信号?
【问题讨论】:
不幸的是,我无法让 Paul 的方法发挥作用,但我有一个可行的解决方案,用于音频信号的 FM 合成。我在 Excel 中做了很多测试,并意识到如何去做。这是算法
for (i = 0; i < N; i++) {
// increase the frequency with increasing amlitudes (fc + fm)
if (input[i] < input[i+1])
out[i] = cos(acos(input[i]) + A * sin(2 * pi * mf * i));
else //decrease the frequency with decreasing amplitudes (fc - fm)
out[i] = cos(acos(input[i]) - A * sin(2 * pi * mf * i));
}
它运行良好,但确实会产生一些不需要的谐波(可能是由于舍入误差),因此您可能必须使用某种过滤器(移动平均值可能会很好地减少那些不需要的谐波)。当应用于音频信号时,您可能需要获取音频的包络并将其与调制信号相乘,以免将 FM 应用于音频的安静部分等。
【讨论】:
您可以将 FM 视为只是动态改变播放速率,其中播放速率的变化与您的调制信号成正比。因此,对于正常播放,您的播放速率与采样率相同,Fs。对于 FM 版本的音频信号,您的播放速率将为 Fs * (1 + A * f(t)),其中 A 是调制幅度,f(t) 是调制信号。要实现这一点,您需要维护一个具有实部和小数部分的 相位累加器,然后根据当前(调制)采样率更新相位累加器。使用相位累加器的整数部分来确定样本索引n,并使用小数部分来进行插值,例如在样本n 和n + 1 之间。
这并不是与wavetable synthesis 非常相似,只是您的波形表是采样声音而不是周期性波形。参见例如this question on dsp.stackexchange.com 了解更多信息。
【讨论】:
for (i = 0; i < 7999; i++) { phi_delta = 8000 - 8000 * (1 + 0.25 * sin(2* pi * mf * i)); f_phi_accum += phi_delta; i_phi_accum = f_phi_accum; r_phi_accum = fabs(f_phi_accum - i_phi_accum); //i_phi_accum = abs(i_phi_accum); if (i_phi_accum <= 7999) output[i] = ((input[i_phi_accum] + input[i_phi_accum + 1])/2) * r_phi_accum; } 我得到了 phi_accum 的负值。即使我做了 abs(i_phi_accum),i_phi_accum 的值也经常超过我输入数组的大小。 (越界)
只需将您的载波方程 cos(t) 替换为输入信号的 f(t),其中 t 可能会根据采样数据的采样率进行缩放。然后像以前一样调制 dt。
请注意,对于采样数据并取决于输入信号的带宽,要使 f(t) 听起来“好”,您可能需要使用结合低通滤波器的高阶插值方法(例如加窗 Sinc 卷积),而不是仅使用最近的样本或两个样本之间的线性插值,这可能会在频域中产生相当严重的混叠。
【讨论】: