你要的功能叫做「变速不变调」。知乎上有人写过一些综述,比如:
我想稍微介绍一下其中的 PSOLA (pitch-synchronous overlap-and-add) 算法。它的大概步骤是:
PSOLA 算法不仅可以「变速不变调」,它可以独立地改变语音的速度和音调:
PSOLA 算法还有一个优点是,在整个算法中不需要对波形进行重采样。这有两个好处:
当然 PSOLA 算法也有一些局限和挑战:
很简单,这是通过傅里叶变换玩的一个小把戏。
我们知道,wav格式的音频数据是按一定间隔从平面坐标系的波形曲线上采样的一组坐标点;而傅里叶变换说白了就是把一小段音频数据(比如0.01秒或更短)从一组坐标点转换为一组频率——而mp3等有损压缩算法其实就是剔除那些人耳不太能注意到的、过高或过低的频率。
频率信息是不能直接播放的。重放时,我们就不得不把频率信息转换回波形采样数据,这样才能驱动声卡发声。
容易想到,只要在把频率信息转换回波形数据之前,先均匀抛弃一定比例的傅里叶变换后的数据,这就相当于保持声音数据频率的同时、缩短了声波波形的总长度(删除了一定比例的波形曲线),自然就达成了“播放语速加倍再加倍,但声音频率不变”的设计目标。
当然,抛弃一些波形曲线段之后,剩余的曲线拼接起来会“接不上茬”。这种周期性的跳变最终会以噪音的形式体现。要消除这种噪声,那可就麻烦了。