音頻處理之語音加速播放


本文系作者原創。如轉載,請注明出處。 謝謝!

在做語音類APP時,語音留言(以碼流形式)會被保存下來。當聽時想快點聽完,於是就有了語音加速播放功能。同時還有個需求,能實時切換播放速率,即當1.5倍
速播放時切兩倍速,就要立刻兩倍速播放。

首先做了一番調研,看幾倍速后就基本上聽不清說什么了。找來了一款能在PC上運行的有加速播放功能的軟件,試驗下來兩倍速以上就基本上聽不清說什么了。於是除
了正常速率外,只有兩個速率可調:1.5倍速和兩倍速。同時搜了一下變速相關的開源算法(算法原理請看其他相關文章),發現主打變聲功能的sound touch使用率較高。它可以改變音調(pitch)和語速(rate)等,好多軟件拿它做一些趣味音頻。基於sound touch做了一個應用程序看加速效果,同時要兼顧男聲和女聲。試驗下來發現語速加快了后音調就變了,也就是還要同時調音調。改了音調做了一番調試后只能接近原聲,能兼顧男女聲。再試試在PC上運行的軟件,加速后也是只能接近原聲。做了這些后就決定用sound touch來做了,在不同的速率下音調(pitch)和語速(rate)參數值也確定了下來(男女聲在一個速率下用一組參數值)。

再看我們的相關代碼,系統支持ILBC和OPUS兩種codec,ILBC每幀30ms, OPUS每幀20ms, 播放線程每20ms運行一次,即每次取20ms PCM數據播放。要想播放語音留言,首先要解碼碼流成PCM 數據放在buffer1中,再看是否要加速播放,要加速的話就把buffer1中的語音數據調加速函數處理后放在buffer2中,不加速就把buffer1中的語音數據直接拷進buffer2中,等待buffer2中的數據被取走播放。根據這些經過一番嘗試后用了分段循環處理的實現方法。一個循環內取固定時間長度的原始音頻幀,取出的這段音頻幀不管是否加速在這個循環內都要正好播放完,同時兼顧ILBC和OPUS兩種不同的幀長和1.5倍速兩倍速兩種不同的速率。ILBC時,每幀30ms,每次取20ms播放,有1.5倍速兩倍速兩種速率,最小的原始PCM數據長度(即最小固定長度)是120ms(原始ILBC幀數是4幀,1.5倍速后是80ms,4次可取完播放,2倍速后是60ms,3次可取完播放)。OPUS時,每幀20ms,每次取20ms播放,有1.5倍速兩倍速兩種速率,最小的原始PCM數據長度也是120ms(原始OPUS幀數是6幀,1.5倍速后是80ms,4次可取完播放,2倍速后是60ms,3次可取完播放)。所以一個循環內取的最小原始音頻的固定長度是120ms. 一個循環結束后正好播放完,清空buffer2,然后取下一段原始音頻幀解碼加速后播放。為了在循環內播放時聲音不斷斷續續,buffer2里要有足夠的數據供取走播放。這樣在每個循環剛開始的時候,要盡可能多的解碼幀數加速后放在buffer2中等取走播放。至於幾次解碼完所需的碼流幀數,這要根據cpu來定。一般一個循環的前一兩次就把碼流解碼加速做完了,后面的次數里只需要從加速后的buffer2里取數據播放就可以了。這樣循環內每次播放線程運行時都能取到數據播放,下一循環開始時也能取到數據播放,不存在斷斷續續的情況。

當要求實時切換語速時,要把這120ms原始語音數據播放完在下一個循環里才能改變語速。由於120ms很短,用戶基本無感知,可以認為是實時的,不影響用戶體驗。
當到語音結尾時,有多少幀就解碼加速多少幀供播放,當從加速后的buffer里不能取到20ms數據就可認為播放結束了。這時用零補足20ms數據,把這些數據播放出去,從而結束播放。

跟上層的UI聯調后效果不錯。這樣APP內的語音加速方案就搞定了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM