zoukankan      html  css  js  c++  java
  • 音频变速播放原理分析及实现方案

    [时间:2019-05] [状态:Open]
    [关键词:音频,audio,倍速,变速,变调,soundtouch,sonic]

    音频变调变速原理分析

    先来一段语音处理的理论:

    变速变调可分为:变速不变调和变调不变速。
    
    语音变速不变调是指保持音调和语义保持不变,语速变快或变慢。该过程表现为语谱图在时间轴上如手风琴般压缩或者扩展。那也就是说,基频值几乎不变,对应于音调不变;整个时间过程被压缩或者扩展,声门周期的数目减小或者增加,即声道运动速率发生改变,语速也随之变化。对应于语音产生模型,激励和系统经历与原始发音情况几乎相同的状态,但持续时间相比原来或长或短。
    
    严格地讲,基频和音调是两个不同的概念,基频是指声带振动的频率,音调是指人类对基频的主观感知,但是两者变化基本一致,即基频越高,音调越高,基频越低,音调越低,音调是由基频决定的。因此,语音变调不变速就是指改变说话人基频的大小,同时保持语速和语义不变,即保持短时频谱包络(共振峰的位置和带宽)和时间过程基本不变。对应于语音产生模型,变调改变了激励源;声道模型的共振峰参数几乎不变,保证了语义和语速不变。
    
    综上所述,变速改变声道运动速率,力求保持激励源不变;变调改变激励源,力求保持声道的共振峰信息不变。但是声源和声道不是相互独立的,在改变声源时,必然也会非线性的影响声道,同样地,改变声道时也会或多或少的影响声源,两者之间相互影响,相互作用。
    

    语音变调在变声软件中较常用。而语音变速在播放器中常用,比如倍速播放(快播、慢播)。本文重点关注变速。
    相对于视频基于帧的变速原理,跳帧或者插帧。音频的变速原理并不是如此简单,因为简单的抽采样点会引起声音的不连续、噪声或爆破音,主观体验较差。
    所以一下简单的音频处理策略通常是行不通的:(以x2倍速为例)

    1.播放设备实现,设置播放设备播放采样率加倍,这样单位时间播放的采样点数加倍,可以实现变二倍速不变调,但声音不连续。
    2.播放前PCM重采样为原采样率的一半,可以实现二倍速,但是会变调。
    3.丢帧,每隔一帧丢一帧,可以实现两倍速,但是也会有刺啦刺啦的噪音,而且声音会产生断续,体验十分差。

    可用方案

    所以为了实现较好的主观体验,只能采用相对复杂的语音处理策略。目前较为常用的音频变速解决方案有两个:soundtouch和Sonic。

    ijkplayer使用的是soundtouch,EXOPlayer使用的是Sonic。

    在Android上还有一种实现方式,基于AudioTrack的变速播放,代码如下:

    	PlaybackParams params = audioTrack.getPlaybackParams();
        //params.setSpeed(1.0f);  // available
        //params.setSpeed(0.5f);  // available
        params.setSpeed(1.5f);  // not available
        audioTrack.setPlaybackParams(params);
    

    详细用法建议参考PlaybackParams

    Sonic和Soundtouch用法类似,都是提供封装好的库,将原音频的PCM数据通过接口函数处理为目标格式,比如二倍速,可能PCM采样点就减半。
    这里以Soundtouch提供的接口为例,说明下如下使用:

    参数设置类接口:

    • setChannels(int) 设置声道,1 = mono单声道, 2 = stereo立体声
    • setSampleRate(uint) 设置采样率
    • setRate(double) 指定播放速率,原始值为1.0,大快小慢
    • setTempo(double) 指定节拍,原始值为1.0,大快小慢
    • setRateChange(double)、setTempoChange(double) 在原速1.0基础上,按百分比做增量,取值(-50 .. +100 %)
    • setPitch(double) 指定音调值,原始值为1.0
    • setPitchOctaves(double) 在原音调基础上以八度音为单位进行调整,取值为[-1.00,+1.00]
    • setPitchSemiTones(int) 在原音调基础上以半音为单位进行调整,取值为[-12,+12]

    PCM处理类接口:

    • putSamples(const SAMPLETYPE *samples, uint nSamples) 输入采样数据
    • receiveSamples(SAMPLETYPE *output, uint maxSamples) 输出处理后的数据,需要循环执行
    • flush() 冲出处理管道中的最后一组“残留”的数据,应在最后执行

    从上述接口来看,类似于常规的解码器或者解复用器的调用逻辑。

    小结

    本文简述了音频变速变调的原理,并对目前Android平台上可用的音频变速方案做了总结,包括Soundtouch、Sonic及AudioTrack三种方案,仅供后续参考。

    参考资料

    1. 音频倍速(变速不变调)的实现
    2. 变速变调原理与方法总结
    3. SoundTouch官网
    4. ijkplayer倍速变调问题解决方案
    5. SoundTouch实现音频变速变调
  • 相关阅读:
    剑指offer——最小的K个数和数组中第K大的元素
    Leetcode刷题指南链接整理
    160. Intersection of Two Linked Lists
    100. Same Tree
    92. Reverse Linked List II
    94. Binary Tree Inorder Traversal
    79. Word Search
    78,90,Subsets,46,47,Permutations,39,40 DFS 大合集
    0x16 Tire之最大的异或对
    0x16 Tire
  • 原文地址:https://www.cnblogs.com/tocy/p/audio-tune-speed-change.html
Copyright © 2011-2022 走看看