記開發過的一款無線音箱解決方案


從2017年開始國外智能音箱的熱潮席卷到國內,各大小廠商都推出了智能音箱,主要有阿里的天貓精靈京東的叮咚和小米的小愛同學等。我也在去年雙11入手了一款智能音箱(天貓精靈),體驗下來總體感覺還是不錯的,我相信這股熱潮在今年(2018)會愈演愈熱。有報道說美國的青年有了智能音箱后對手機的依賴度有所下降,即有些事情可以通過智能音箱解決了,這種現象在國內也會出現。智能音箱是在無線音箱的基礎上加上人工智能(AI)發展起來的。幾年前無線音箱也火過,推出了好多產品,有基於bluetooth的,也有基於WiFi的。基於bluetooth的是主流,基於WiFi的不多,但是現在智能音箱都是基於WiFi的。那時我還在芯片公司,我們team的語音解決方案已經做得很成熟,老板就讓我們用自己公司的芯片做主芯片,開發一個基於WiFi的無線音箱解決方案。

 

無線音箱先由手機去配置連到某個無線路由器上,手機也連到這個無線路由器上, 這樣手機上的音樂播放器就可以把音樂在無線音箱上播放了。既可以把手機本機上的歌曲推送到音箱上播放,也可以把雲端的歌曲推送到音箱上播放。支持的協議有DLNA和Airplay,主流的音樂播放器(QQ音樂/酷狗音樂/網易雲音樂等)均支持,也支持蘋果的音樂播放器(Airplay)。支持的音樂格式很多,有MP3/AAC/OGG/APE/WMA/ALAC/FLAC等,支持音樂雙聲道立體聲播放,但是在一個音箱上效果不明顯。如果有兩個這樣的音箱,又用上公司開發的相應的音樂播放APP,可以把左聲道的數據推送到一個音箱上,右聲道的數據推送到另一個音箱上,產生較強的立體聲效果。

 

無線音箱的軟件實現是在openWrt上開發的,這樣無線相關的軟件全都好了,我們只要開發音頻相關的軟件。音頻相關的絕大多數是基於開源的開發,協議的DLNA用的是sharepoint,AirPlay用的是gmediarender,音樂格式解析及解碼等用的是FFMPEG,音頻的播放用的是ALSA。Sharepoint和gmediarender基本上是拿來用,在接口上改了一點點,調用我們做好的API實現與我們自己軟件的通信。FFMPEG主要是增加decoder,同時還要對decoder優化使其能流暢的運行。我們自己的軟件就是搭一個框架(實現一個process)把這些開源實現給串起來,形成一個無線音箱音樂播放方案。解決方案的軟件框圖如下:

                                       

 

我們實現的process叫mediaplay, 它與協議(DLNA/AirPlay)之間通過share memory通信,從而實現音樂的播放暫停停止等。Mediaplay會調用FFMPEG提供的API去解析音樂格式,並一幀一幀的解碼得到PCM數據放進ring buffer中,然后用mutex block住mediaplay。Mediaplay向ALSA注冊了回調函數,每隔一幀時長就會被調用一次,取走ring buffer中一幀PCM數據,並解鎖mutex使mediaplay繼續循環運行去解碼下一幀。在一首歌開始解碼時一般會緩存若干幀在ring buffer中然后才使能播放,這樣做雖然增加了一兩百毫秒的delay,但是保證了播放時的連續流暢性,不會出現噪聲。再說音樂播放是非實時業務,一兩百毫秒的delay對用戶是不敏感的。

 

我們team共4人。一人負責ALSA(包括driver和ALSA-Lib的調用),一人負責軟件框架(即實現mediaplay process及里面的控制邏輯),一人負責DLNA/AirPlay協議的移植以及與mediaplay的通信,我負責FFMPEG、decoder優化以及把優化好的decoder lib集成到FFMPEG中,同時還負責后處理(主要是EQ)。用開源的好處是網上資料很多。我開始前先在網上搜怎么編譯FFMPEG生成動態庫,以及怎么使能一些decoder不使能一些decoder等。這些搞定后就調研我們需要的decoder(MP3/AAC/APE/OGG/WMA/FLAC/ALAC)FFMPEG是否都支持,哪些是定點實現的,哪些是浮點實現的(我們是在ARM上做軟件方案,且CPU只有500兆,一定要用定點實現,浮點實現CPU load扛不住)。調研下來這些decoder FFMPEG都支持,但是AAC/OGG/WMA是浮點實現的。做了個小應用程序(代碼中調用FFMPEG的API)在芯片上去播放這些格式的音樂,明顯播放速度變慢了,這就需要去找這些decoder的定點實現來替換浮點實現。又到網上搜這些decoder定點實現中哪個應用最廣泛(在網上快速搜到自己想要的東西也是一種能力,我就在那時候這方面的能力得到了提高,並且養成了要找開源首先去GitHub的習慣。給GitHub打廣告了,哈哈)。

 

對於AAC,搜下來定點方案中較好的是3GPP中AAC的參考實現。由於是3GPP的reference code,質量肯定沒問題,就決定用它了。剛開始未優化時在我們芯片上跑下來load是2000多MCPS,后來一步步優化到不到200MCPS,可以在芯片上高枕無憂的運行了,也就沒再繼續優化,還要去忙其他的decoder呢。至於怎么優化的可以看我前面寫過的一片文章(音頻的編解碼及其優化方法和經驗),這里就不具體描述了,通常優化都是有套路的。優化好后就要把靜態庫集成到FFMPEG中,並且加相應的適配代碼,使其能正常運行。那時(2013年)網上關於這方面的描述不多,我也是一邊搜索一邊嘗試,最終把AAC的定點實現庫成功集成到FFMPEG中了。這里也簡單說一下怎么加decoder的庫到FFMPEG 中,給有需要的做個參考。主要有以下幾個步驟:

1)把decoder調好,得到庫文件和頭文件

2)修改FFMPEG的configure

3)在allcodecs.c中加上REGISTER_DECODER(),注冊這個decoder

4)在libavcodec目錄中加上這個decoder的適配文件(*.c),同時修改libavcodec下的makefile,使這個適配文件能編進去

5)修改./configure 使這個decoder使能,同時告訴相應的庫路徑和頭文件路徑

 

OGG格式的解碼用的是Vorbis,其官網(www.xiph.org)上就有定點實現。本來load就不高,把他簡單優化一下就可以用了,然后做成靜態庫集成到FFMPEG中。從找定點實現到集成到FFMPEG中用了不到一星期時間,可以說是非常順利。WMA就沒有這么順利了,廢了一番波折,主要是因為微軟不提供定點實現。在網上花了一些時間搜索,某個國外論壇里有人說RockBox里有WMA的定點實現。把RockBox download下來在Ubuntu下生成一個帶界面的應用程序,播放一個WMA格式的音樂,可以正常播放。接下來就是把WMA的定點實現從RockBox中剝離出來,它與其他代碼耦合的比較深,剝離花了些時間,最終還是成功剝離了,又花了點時間簡單優化下並做成庫集成進FFMPEG中。這樣三個decoder的優化及集成就搞定了。

 

Decoder搞定后就開始做后處理,主要做均衡化(EQ),它是通過改變不同頻段上的gain值從而產生不同的音效,有搖滾、經典、古典、爵士舞曲等10種模式。從信號處理的角度看,EQ就是一個兩階IIR濾波器。用戶在手機APP上指定想要的模式后模式ID就會發到音箱上,軟件就會根據ID得到相應的參數做EQ后處理。依舊在網上找定點實現,找到后先做一個應用程序驗證效果。驗證好后就開始把它用到我們的產品中並和其他模塊聯調。調試好后看到我們的無線音箱也支持音效特別有成就感。

 

經過我們幾個月的努力,無線音箱解決方案完成了,也陸續得到客戶的認可,采用我們的方案。對我個人而言,從語音擴展到了音樂,音頻的知識面更廣了。


免責聲明!

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



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