原文:http://www.znmcu.cn/znx_51_alltest_shell_fj_adpcm1.html
ADPCM音頻解碼,其實放在這里有些不太合適。
在編寫ZN-X開發板整板測試程序的后期,振南開始轉向專注於ADPCM音頻的解碼算法。對於音視頻的編解碼,振南一直是很感興趣的。
VS1003錄音向外輸出的數據是經過ADPCM編碼的,所謂ADPCM編碼是一種自適應差分脈碼調制技術。它可以對音頻數據在毫無損失的前提下,將數據量壓縮為原來的1/4,這對於音頻來說,意義是重大的。我很想深入去研究一下ADPCM,但因為沒有時間,一直被擱置。
ADPCM源於微軟的Windows,一般的WAV文件就是使用它來編碼的,WAV是Windows上的標准音頻格式。ADPCM算法已經被標准化了,現行使用的是IMA-ADPCM,即IMA組織制訂的ADPCM算法。這種算法比較簡單,但卻有較高的壓縮比。


ADPCM編碼的原理(我會盡量說的通俗的):
如果我們對一個聲音信號進行采樣,采用16位量化,比如采集53個點,如下圖:

如果我們直接存儲每一個點的16位的采樣值,這樣就需要53X16=848個位,大約是106字節。但我們換個思路,我們不存儲采樣值,而存儲采樣點兩兩之間的差值(采樣值可能會很大,需要更多的位數來表達,比如16個位,但是兩點之間一般來說是比較連續的,差值不會太大,所以這個差值只需要很少的幾個位即可表達,比如4個位)。這樣,我們只需要知道前一個點的值,又知道它與下一個點的差值,就可以計算得到下一個點了。這個差值就是所謂的“差分”!
這就是DPCM的主要思想精髓!!
“什么?DPCM?我們不是說ADPCM嗎?”是的,DPCM是差分脈碼調制,多一個A,就是自適應!為什么要自適應?
你有沒有考慮到一個問題?如果取兩點之差,這個差值超過了4個位可以表達的范圍,該如何處理?音頻信號雖然具有很高的連續性,但是我們並不能保證兩點之間產生突變的可能!

前面的差值可能是3、5、8、12,后面突然變成20、40,甚至更大,這時4個位還夠用嗎?數據量的減少,不能以數據丟失和失真作為代價!!
如果有一種方法,可以把兩點之間的差值變換到固定的幾個位即可表達的范圍內,那就好了!而且這種變換是實時的,並且具有自適應性和預測能力的。這就是ADPCM的基本思想。它定義了一些因子,這種算法如果發現兩點之間差值變大之后,就會用差值去和相應的因子作除法,從而減小了差值,讓它可以減少到幾個位可表達的數值范圍內。而選擇哪一個因子來除它,這就是ADPCM編碼要作的事情了。
ADPCM算法巧妙的利用了音頻信號的特點,也就是音頻信號上的點與它前面的若干個點是有一定的相關性的,從而可以對下一個點進行預測,從而預先估計這個差值,從而選取相應的除數因子,去把差值歸化到數值范圍內!!
以上就是ADPCM對音頻信號進行編碼大體思想和過程!!
我們從VS1003中讀取到的,就是經過ADPCM編碼后的數據,也就是音頻信號采樣點之間的差值!(只是這些差值並不能直接用來去計算下一個采樣點,而需要與因子相乘,計算得到真正的差值,這與編碼是一個相逆的過程。乘數因子就是編碼時用的那個除數因子,解碼時要根據當前的音頻信號去預判,以便取合適的因子!!)
以上是對ADPCM編碼音頻的解碼的方法,它適用於VS1003輸出的音頻數據,同樣適用於使用ADPCM編碼的WAV文件,以及所有使用ADPCM編碼的聲音數據!!!
【比如一些語音產品,像數字對講機、數字廣播等等,也都可以使用ADPCM編碼,這樣可以很好的降低數據帶寬要求!!】
