智慧手錶上的音訊(三):音訊檔播放

2023-11-08 09:00:39

上篇講了智慧手錶上音訊相關的驅動。本篇開始講具體的功能,先講音訊檔播放。

 

音訊檔格式眾多,目前我們僅支援了最常見的幾種:WAV/MP3/AAC/AMR(主要用於播放錄音檔案)。相對於播放WAV(即PCM),MP3/AAC/AMR多了個解碼過程。音訊檔播放時只有AP和ADSP在執行。音訊可以從speaker(即內建codec)放出來,也可以從藍芽耳機放出來。這兩種方式不管是AP/ADSP的互動過程還是audio data path都有差異。下面分開講。

 

1,音訊從speaker放出來

下圖是其audio data path的軟體框圖:

從上圖看出,AP把音樂流(當是WAV檔案時是PCM資料,當是其他支援的檔案型別時是位元流)送給ADSP。ADSP收到後做解碼(WAV檔案沒有這一步)、重取樣(系統把內建codec的取樣率固定在48K,不是48K的都要轉到48K)、音效處理(比如EQ)、混音後送給audio driver,通過speaker播放出來。

 

下圖是speaker播放音訊檔時AP 與ADSP的主要互動命令:

1)  AP給ADSP發命令STREAM_DEV_SELECT,告訴ADSP選擇哪個device(內建codec或者BT)播放

2)  AP給ADSP發命令ENABLE_STREAM,告訴ADSP使能哪一條stream。系統中定義了很多條stream(music / voice / record / ……),每一條都有相對應的ID。

3)  ADSP給AP發命令DATA_REQ,stream被使能後,ADMA中斷就會等間隔的來。前面文章說過,內建codec下系統就是靠ADMA中斷轉起來的。ADMA中斷觸發去取採集到的音訊資料送給ADSP的audio buffer,以及從ADSP的audio buffer裡取資料去播放。Stream使能後,ADSP沒資料播放(音訊檔在AP上),因此ADSP向AP發DATA_REQ來請求音訊資料。

4)  AP收到ADSP發來的DATA_REQ後就會給ADSP回DATA_REQ_ACK,帶上音訊資料(AP把音訊資料放在雙方都能存取的share memory裡,實際上在命令裡帶上的是這塊音訊資料在share memory裡的起始地址, ADSP收到命令後從這個起始地址處拿音訊資料)。ADSP收到音訊資料後會做解碼等,最終播放出來,來消耗從AP收到的音訊資料。當消耗到快沒有時,又會向AP發DATA_REQ。AP收到後又會通過DATA_REQ_ACK向ADSP傳送音訊資料。如此反覆完成整個音訊檔的播放。

5)  AP給ADSP發命令DISABLE_STREAM,告訴ADSP停止哪一條stream。ADSP收到後將停止這條stream相關的處理。

6)  ADSP給AP發命令DISABLE_STREAM_ACK,告訴AP這條stream已停止處理。AP收到後做相應處理。

 

2,音訊從BT放出來

下圖是其audio data path的軟體框圖:

從上圖看出,AP把音樂流送給ADSP。ADSP收到後做解碼、重取樣、音效處理、混音後送給BT SBC encoder做編碼處理,得到SBC碼流後將其傳送給AP,最終AP上的BT host將SBC碼流通過UART傳送給BT chip,BT chip再通過藍芽的空口將碼流送給藍芽耳機,音訊從藍芽耳機播放出來。這裡BT chip 做master,藍芽耳機做slave。ADSP在BT播放音訊的場景中起加速器的作用,音訊流從AP到ADSP,ADSP處理後又把音訊流(這時是SBC碼流)送給AP。這跟speaker播放音訊是有明顯差異的。

 

下圖是BT播放音訊檔時AP 與ADSP的主要互動命令:

1)  AP給ADSP發命令STREAM_DEV_SELECT,告訴ADSP選擇哪個device(內建codec或者BT)播放

2)  AP給ADSP發命令SET_BT_PARAM,告訴ADSP做SBC編碼時用的引數。這些引數包括bitpool(2--250) / subband(4 / 8) / blocks(4 / 8 / 12 / 16) / mode(MONO/DUAL/STEREO/JOINT STEREO) / allocation(LOUDNESS / SNR)。

3)  AP給ADSP發命令ENABLE_STREAM,告訴ADSP使能哪一條stream。

4)  AP給ADSP發命令A2DP_DATA_REQ,告訴ADSP A2DP模組需要多少位元組的SBC碼流資料。音訊播放中都是靠資料消耗者來驅動的。這裡A2DP是資料消耗者,因此由它來要播放的資料。

5)  ADSP給AP發命令DATA_REQ。 Stream使能後,ADSP沒資料播放(音訊檔在AP上),因此ADSP向AP發DATA_REQ來請求音訊資料。

6)  AP收到ADSP發來的DATA_REQ後就會給ADSP回DATA_REQ_ACK,帶上音訊資料(AP把音訊資料放在雙方都能存取的share memory裡,實際上在命令裡帶上的是這塊音訊資料在share memory裡的起始地址, ADSP收到命令後從這個起始地址處拿音訊資料)。

7)  ADSP給AP發命令A2DP_DATA_REQ_ACK。ADSP上音訊資料後就做相關處理,直到得到SBC碼流。當SBC碼流的位元組數達到A2DP_DATA_REQ請求的個數時就會給AP發A2DP_DATA_REQ_ACK。SBC碼流也是放在雙方都能存取的share memory裡,在命令裡帶上的是這塊SBC碼流在share memory裡的起始地址, AP收到命令後從這個起始地址處拿SBC碼流。這SBC碼流會被BT host通過UART發給BT chip。當SBC碼流消耗到快沒有時,又會向ADSP發A2DP_DATA_REQ。ADSP沒有音訊資料時又會通過DATA_REQ向AP要音訊資料,AP收到後會向ADSP傳送音訊資料,當SBC碼流的位元組數達到A2DP_DATA_REQ請求的個數時又會給AP發A2DP_DATA_REQ_ACK。如此反覆完成整個音訊檔的播放。

8)  AP給ADSP發命令DISABLE_STREAM,告訴ADSP停止哪一條stream。ADSP收到後將停止這條stream相關的處理。

9)  ADSP給AP發命令DISABLE_STREAM_ACK,告訴AP這條stream已停止處理。AP收到後做相應處理。

 

至此兩種場景下的音訊檔播放就講完了。最後再上一張ADSP上的音訊資料流向圖,它把不同stream(PCM stream / bit stream)以及不同的播放方式(speaker / BT)都呈現出來。圖中有多個FIFO(也就是ring buffer),主要是保證播放的流暢性。