劉曉暉 秦子實
摘要:近年來,5G技術的發(fā)展帶動物聯網設備快速普及,以樹莓派為代表的卡片計算機大量出現在工程應用的各個方面。而在音頻采集處理方面,基于樹莓派的麥陣列聲源采集具有高算力、高精度、低功率的特點。本文介紹基于sounddevice的采集、分發(fā)、播放音頻流的方法,該方法可以對音頻數字信號進行自定義預處理,支持多種數據分發(fā)方式,系統(tǒng)依賴少,代碼簡單且方便部署。
關鍵詞:物聯網設備;樹莓派;音頻采集
中圖分類號:TP393? ? ? 文獻標識碼:A
文章編號:1009-3044(2021)17-0036-02
開放科學(資源服務)標識碼(OSID):
1 概述
樹莓派是一種尺寸極小的計算設備,具有包括處理器、內存、外村在內完整的計算機硬件要素,通常運行基于Debian的Linux系統(tǒng),功率約5W,具有豐富的外部接口。由于通用性強且已被市場廣泛應用,目前具有大量適配的高質量、低成本傳感器。
本文介紹基于樹莓派3B+平臺及SeeedReSpeaker6麥陣列,運行Raspbian buster系統(tǒng),使用sounddevice庫(以下簡稱sd)的聲源采集方案的設計與實現。該環(huán)形麥陣列精度較高、價格較低,適合在聲源定位、音頻采集項目中低成本部署。
2音頻采集
2.1 硬件識別
通過sounddevice庫進行音頻數據相關操作,首先需要識別聲卡并確定麥陣列聲卡的系統(tǒng)ID??梢酝ㄟ^sd.query_devices()函數確認系統(tǒng)識別的音頻設備列表,返回示例如下:
“seeed-8mic-voicecard”即為麥陣列聲源采集設備(序號為2),具有8路輸入,即2顆AC108 ADC芯片,每芯4路輸入其中1路為playback,則實際采集為6路。麥陣列自帶聲卡輸出,即AC101 DAC芯片(序號為6),2路輸入2路輸出,占用樹莓派3.5mm耳機監(jiān)聽接口。因此,sounddevice庫主要使用序號2及序號6設備進行音頻數據的輸入輸出。通過以下代碼獲取輸入輸出設備ID:
2.2 音頻采集及監(jiān)聽
sounddevice庫支持兩種數據封裝格式,RawStream將數字信號轉為buffer對象進行傳輸,而Stream將RawStream再次封裝為numpy數組進行傳輸,需要numpy支持,更方便數據操作,本文選用Stream方式,發(fā)送numpy數組。
數據流發(fā)送有兩種方式:阻塞方式的和非阻塞回調方式,為方便調試,本文選用非阻塞回調方式,即音頻數據流發(fā)送開始后立即返回,這樣可以繼續(xù)在解釋器中繼續(xù)執(zhí)行其他作業(yè)。啟動音頻流的方法如下:
[rs = sd.Stream(samplerate=48000, device=iodevs, channels=[8, 2], callback=cb, finished_callback=fcb) ]
其中最主要的參數為回調callback,該函數將輸入輸出聯系起來,這個回調所要求的函數簽名為:
[callback(indata: ndarray, outdata: ndarray, frames: int, time, CData, status: CallbackFlags) -> None ]
其中indata參數時輸入設備傳入的數據,即序號2的麥陣列,通常采用48Khz采樣率,每次回調傳入的numpy數組維度均為(512, 8),約為10ms的音頻數據,延遲較低。outdata是傳給輸出設備的數據,傳給輸出設備的數據,在sd.Stream的聲道配置為[8, 2]即8路輸入2路輸出,因此需要將indata的8列數據轉為2列賦給outdata(如每4路求平均),此時3.5mm監(jiān)聽接口由于channels參數輸出設備的選擇,將有麥陣列采集的音頻信號輸出?;卣{函數示例,本文使用簡單的求平均法,將每4聲道數據求平均,使得原8列數據轉為2列數據:
剩余的參數中,frames為幀數,本文中即512;time是一個CFFI的C結構體,包括輸入開始時間inputBufferAdcTime、輸出開始時間outputBufferDacTime、本次callback被調用的時間currentTime三個成員;status為本次回調狀態(tài),可以在此發(fā)送終止指令。
使用sounddevice將輸入處理后直接賦給輸出,經實測延時極低,采集效率較高。
3 音頻數據分發(fā)
3.1 數據收發(fā)
由于在48000kHz采用率下,未經壓縮是數據量較大(理論值約1.465MB/s),因此本文選用ZeroMQ分發(fā)numpy數組。ZeroMQ支持包括推送模式、拉取模式、MapReduce模式等多種分發(fā)方式,高效靈活,可以按照實際應用場景靈活選擇。
ZeroMQ在Python下的支持庫名為pyzmq,在發(fā)送numpy數組時需要注意,pyzmq直接發(fā)送numpy數組時,ZeroMQ會使用Python的memoryview直接將數組轉換為字節(jié)發(fā)送,由于轉換過程僅保留數據,數組的dtype類型信息和shape維度信息將丟失。因此,在發(fā)送數組時,需要使用ZeroMQ的SNDMORE標識,先發(fā)送數組屬性,再發(fā)送數組內容,如此即可在接收端重建完整數組。發(fā)送端的函數示例:
可以在分發(fā)時在md字典中添加其他屬性,如幀序列等信息,以輔助分發(fā)、重建及顯示,并不影響numpy數組重建。
3.2 數據重建及播放
在數據接收設備上,同樣按照2.1節(jié)的方法找出本地音頻輸入輸出設備(若是對數據進行重建并播放,則主要使用輸出設備)。鑒于發(fā)送端采用48000KHz采樣率,接收設備若希望能夠正常還原并播放音頻數據,同樣需要調整設備聲卡采樣率至48000KHz,否則重組數據播放將有明顯的滯后。
接收設備收到的numpy數組每幀同樣為(512, 8)的維度,若接收設備播放為雙聲道,同樣需要進行調整輸出維度,安裝2.2節(jié)的回調函數進行按列求平均合并。
3.3 未來的改進
本文實例為最簡單的原理展示,若進行工程應用需要注意,ZeroMQ與目前流行的其他消息隊列相比,具有極小極快可嵌入的優(yōu)點,但缺點也較為明顯——未配備持久化模塊。本文經測試,在網絡狀況一般的環(huán)境中(如某些無線網絡),若網絡承受不住過大的數據流量,ZeroMQ發(fā)送端將出現消息堆積現象,并在緩存滿后直接丟棄數據,在接收端的現象為數據滯后越來越大,在一定時間后重新同步至最新數據,滯后未收到的數據將丟失。ZeroMQ因庫應用場景及大小考慮,雖不提供官方持久化方案,但支持用戶自定義持久化,在工程應用中,應自行定義持久化模塊,以防數據丟失。
4 結束語
本文介紹了基于樹莓派的物聯網設備進行音頻數據采集,并使用ZeroMQ進行實時數據分發(fā)的方法,系統(tǒng)依賴少且部署簡便。該方法基于物聯網設備,在保證一定的數據處理能力的情況下維持低功耗。數據分發(fā)僅基于TCP socket,對網絡拓撲及協(xié)議沒有特殊要求,兼容性良好且分發(fā)效率高,同時兼顧了多種的數據分發(fā)模式,可以在不同的場景中進行靈活應用。
【通聯編輯:梁書】