作为学习练习,我试图实现一个Java类,该类能够根据另一个音频效果文件应用某些语音更改。
例如。假设我有一个语音样本,说“hello world”,另一个语音样本有“呼吸噪音”,我想用噪音调制语音,以达到“Darth Vader”效果。
仔细搜索一下,我发现这可以通过使用频率调制来实现,因此我的第一个疑问:频率调制是否可以正确解决我的问题? (我不想实现darth vader语音效果,我想使声音听起来像普通的杂音效果一样)。
假定频率调制是正确的答案,我试图弄清楚如何在Java中实现它,并最终得到如下结果:
public void modulate(File voice, File effect, File output) {
AmplitudeData ampVoice = readAudioFile(voice);
AmplitudeData ampEffect = readAudioFile(effect);
FFT fftVoice = FFT(ampVoice);
FFT fftEffect = FFT(ampVoice);
FFT fftModulated = FM(fftVoice,fftEffect);
AmplitudeData ampModulated = IFFT(fftModulated);
writeAmplitudeToFile(ampModulated, "WAV");
}
我基本上知道如何应用FFT和IFFT,但是我仍在寻找任何稳定,高效的开源代码,这些代码可能比我的要好,所以假设我能够将音频文件(例如MP3)读取为幅度表示形式然后产生音频文件的FFT表示。还可以计算逆FFT。
关于FM(我不是信号处理专家),我发现使用正弦函数的采样非常基本,但没有使用其他载波的示例(即我的噪声效应)。
通过阅读一些论文,我了解到信号屏蔽并不是我想要的。例如,要将声音更改为机器人声音或darth vader效果,我可以对FFT进行一些偏移或音调更改,但是在这种情况下,我想让声音看起来像是与另一声音一样声音(例如,想象一下电锯或熊熊燃烧的烈火在讲类似世界的东西)。
所以我的问题是,在我的代码中实现FM功能的最佳和最有效的方法是什么?它对我有用吗?
最佳答案
解决方案的简化版本似乎是通过使用调制器信号对载波进行简单的环形调制。
主要思想类似于“颤音”效果,即通过简单地将信号数字阵列与颤音变化相乘:
h [i] = inner_product(c [i],m [i])
对于每个i,H为最终结果,C为载波,M为调制器,其中i是每个信号的每个数字样本的索引。
在此版本中,信号必须具有相同的长度。
结果可能会受到失真的影响,但出于我的目的应该可以。如果没有其他人知道更好的解决方案,我认为这将是正确的答案。