Android音訊知識介紹-從AndroidRecord看起

Anderson大碼渣發表於2017-08-09

前言

音訊的相關知識我們從AudioRecord的構造傳參看起:

        RecorderHelper.getInstance().initRecoder(
                this,
                MediaRecorder.AudioSource.MIC,  //麥克風資料
                16000,                          //取樣率16k
                AudioFormat.CHANNEL_CONFIGURATION_MONO,  //單聲道
                AudioFormat.ENCODING_PCM_16BIT);// 16bit的取樣精度複製程式碼

上面一個初始化麥克風的呼叫,涉及到了很多知識,大概是大學時數字訊號處理課程或者是訊號與系統學的。相關覺得有必要科普一下,不然大家永遠是在複製程式碼,遇到相關問題的時候如果不瞭解會一頭霧水,優化效果更提不上了。

這篇文章不是用來介紹API的,介紹AndroidRecord API很簡單,無非初始化然後讀取。如果只是這麼簡單的需求,甚至這個類都用不到,直接用MediaRecorder即可錄音等。本文主要介紹相關的引數是什麼意思。比如什麼是16Bit取樣,什麼是44100取樣率。

簡介

Google API地址
developer.android.google.cn/reference/a…

從網頁的右上角我們可以看到,這是從API3等級開始就有的類。AndroidRecord是一個比MediaRecorder更加底層的類,根據谷歌介紹,有點相當於是直接從音訊裝置拉資料的意思,並且我們拿到的也直接是PCM流。

從API23開始 多了個AudioRecord.Builder類來幫助我們初始化AndroidRecord,可惜這個類還不如不用,用了我23以下的還得用老方法初始化,這不僅沒優化程式碼,還冗餘了程式碼。

構造方法

AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)複製程式碼
引數 介紹
audioSource MediaRecorder.AudioSource類裡面的各種型別,有MICVOICE_CALL
sampleRateInHz 取樣率,44100Hz是唯一可以工作於所有手機上的取樣率,22050, 16000, and 11025 可能只有部分機型能工作,我之前就因為設定的取樣率為16000導致在我的手機上工作正常,而在努比亞手機上Buffer滿的時間變短導致了些問題。
channelConfig CHANNEL_IN_MONO 和 CHANNEL_IN_STEREO.即單聲道和立體聲也叫雙聲道,雙聲道可以有保證的作於所有手機上
audioFormat ENCODING_PCM_8BIT, ENCODING_PCM_16BIT, and ENCODING_PCM_FLOAT. 有8bit,16bit,32bit的取樣精度
bufferSizeInBytes Record的內部記錄緩衝區大小,可以通過getMinBufferSize(int, int, int) 方法得到。

什麼是PCM

脈衝編碼調製(Pulse Code Modulation,PCM),這是在訊號與系統裡面接觸過的編碼格式,脈衝編碼調製是數字通訊的編碼方式之一。主要過程是將話音、影象等模擬訊號每隔一定時間進行取樣,使其離散化,同時將抽樣值按分層單位四捨五入取整量化,同時將抽樣值按一組二進位制碼來表示抽樣脈衝的幅值。

PCM通過抽樣、量化、編碼三個步驟將連續變化的模擬訊號轉換為數字編碼

什麼是取樣率?

取樣率又叫抽樣,由於聲音其實是一種能量波,因此也有頻率和振幅的特徵,頻率對應於時間軸線,振幅對應於電平軸線。波是無限光滑的,絃線可以看成由無數點組成,由於儲存空間是相對有限的,數字編碼過程中,必須對絃線的點進行取樣。取樣的過程就是抽取某點的頻率值,很顯然,在一秒中內抽取的點越多,獲取得頻率資訊更豐富,為了復原波形,一次振動中,必須有2個點的取樣,人耳能夠感覺到的最高頻率為20kHz,因此要滿足人耳的聽覺要求,則需要至少每秒進行40k次取樣,用40kHz表達,這個40kHz就是取樣率。我們常見的CD,取樣率為44.1kHz。

44.1kHz意味著什麼呢?假設我們有2段正弦波訊號,分別為20Hz和20KHz,長度均為一秒鐘,以對應我們能聽到的最低頻和最高頻,分別對這兩段訊號進行 40KHz的取樣,我們可以得到一個什麼樣的結果呢?結果是:20Hz的訊號每次振動被取樣了40K/20=2000次,而20K的訊號每次振動只有2次取樣。顯然,在相同的取樣率下,記錄低頻的資訊遠比高頻的詳細。這也是為什麼有些音響發燒友指責CD有數碼聲不夠真實的原因,CD的44.1KHz取樣也無法保證高頻訊號被較好記錄。要較好的記錄高頻訊號,看來需要更高的取樣率,於是有些朋友在捕捉CD音軌的時候使用48KHz的取樣率,這是不可取的!這其實對音質沒有任何好處,對抓軌軟體來說,保持和CD提供的44.1KHz一樣的取樣率才是最佳音質的保證之一,而不是去提高它。較高的取樣率只有相對模擬訊號的時候才有用,如果被取樣的訊號是數字的,請不要去嘗試提高取樣率。

常用的取樣率為:44.1KHz與48KHz

什麼是取樣精度?

1 位元組(也就是8bit) 只能記錄 256 個數, 也就是隻能將振幅劃分成 256 個等級;
2 位元組(也就是16bit) 可以細到 65536 個數, 這已是 CD 標準了;
4 位元組(也就是32bit) 能把振幅細分到 4294967296 個等級, 實在是沒必要了.

如果是雙聲道(stereo), 取樣就是雙份的, 檔案也差不多要大一倍.

我們來看一張圖就能明白:

上述的模擬資料模擬就好比人的聲音是有振幅有頻率的波,假設上面的模擬資料時長為1秒。
那麼取樣,可以看到我們取樣了10根線,那取樣率就是10Hz。(44100Hz是多高自己體會)
再看量化,分為了8個等級,也就是取樣進度是3bit。(可以想象16bit是多麼精確了)
最後1秒鐘的資料,被編碼成了3bit×10 即30個二進位制資料。

單聲道和立體聲

如果是8bit的取樣,對於單聲道聲音檔案,取樣資料為八位的短整數(short int 00H-FFH);

而對於雙聲道立體聲聲音檔案,每次取樣資料為一個16位的整數(int),高八位(左聲道)和低八位(右聲道)分別代表兩個聲道。

位元速率計算

算一個PCM音訊流的位元速率是一件很輕鬆的事情,取樣率值×取樣大小值×聲道數bps。一個取樣率為44.1KHz,取樣大小為16bit,雙聲道的PCM編碼的WAV檔案,它的資料速率則為 44.1K×16×2 =1411.2 Kbps。我們常說128K的MP3,對應的WAV的引數,就是這個1411.2 Kbps,這個引數也被稱為資料頻寬,它和ADSL中的頻寬是一個概念。將位元速率除以8,就可以得到這個WAV的資料速率,即176.4KB/s。這表示儲存一秒鐘取樣率為44.1KHz,取樣大小為16bit,雙聲道的PCM編碼的音訊訊號,需要176.4KB的空間,1分鐘則約為10.34M,這對大部分使用者是不可接受的,尤其是喜歡在電腦上聽音樂的朋友,要降低磁碟佔用,只有2種方法,降低取樣指標或者壓縮。降低指標是不可取的,因此專家們研發了各種壓縮方案。

位元速率的不同帶來的是音訊品質的不同,我們的音樂軟體裡面有音樂的品質其實就是這些,正常我們聽的當然是有失真壓縮的歌曲,比如QQ音樂裡面聽歌有SQ無損品質,就是無失真壓縮的音訊。

WAV檔案介紹

PCM流我們可以直接儲存為檔案,但是這就是PCM格式了,正常播放器都沒有播放pcm的功能,我們可以把PCM轉成WAV。WAV檔案是一種一種無損的音訊檔案格式,裡面還是PCM的編碼,只不過是在我們原有的pcm檔案上加上一個WAV規定的協議頭而已。這個頭是44個byte大小。所以一個0bit的pcm檔案轉成wav大小是44B。

因為WAV並沒有進行壓縮,所以WAV佔用的空間是最大的。因此為了傳輸以及儲存的需求後來人們設計了很多的音訊壓縮格式,mp3就是一種有損的壓縮音訊,至於怎麼壓縮的那是各種壓縮演算法的事情了。


本文作者:Anderson/Jerey_Jobs

部落格地址 : jerey.cn/
簡書地址 : Anderson大碼渣
github地址 : github.com/Jerey-Jobs

相關文章