文獻(xiàn)標(biāo)識碼: A
DOI:10.16157/j.issn.0258-7998.2016.02.005
中文引用格式: 劉喬壽,黃國臣,吉福生. 基于FPGA的FLAC音頻硬解碼的設(shè)計與實現(xiàn)[J].電子技術(shù)應(yīng)用,2016,42(2):21-24.
英文引用格式: Liu Qiaoshou,Huang Guochen,Ji Fusheng. Design and implementation of FLAC hardware decoding based on FPGA[J].Application of Electronic Technique,2016,42(2):21-24.
0 引言
FLAC是音頻的無損壓縮格式,即音頻以FALC編碼解碼后不會丟失任何信息,F(xiàn)LAC音頻文件解碼還原為WAV文件后,與壓縮前的WAV文件內(nèi)容是一樣的[1]。FLAC是專門針對PCM音頻的特點而設(shè)計的壓縮方式?,F(xiàn)今大多數(shù)據(jù)系統(tǒng)采用專用芯片或者軟件實現(xiàn)FLAC音頻的解碼。使用專用芯片靈活性差,不利于FLAC解碼器的特殊應(yīng)用。而軟件實現(xiàn)解碼需要占用大量的系統(tǒng)資源,且解碼效率低。
FPGA具有運行速度快、可重復(fù)編程、集成度高等優(yōu)點,是進(jìn)行原始設(shè)計最理想的載體[2]。為此,筆者以音頻播放系統(tǒng)中FLAC解碼為應(yīng)用背景,提出了一種采用Verilog 語言設(shè)計的通用FLAC音頻解碼器的FPGA模塊化解決方案。所設(shè)計的解碼器可作為IP核用于專用音頻集成電路設(shè)計或者FPGA設(shè)計中,可以縮短設(shè)計周期,提高系統(tǒng)設(shè)計的成功率。
1 FLAC編碼原理及FALC音頻格式
與其他的音頻編碼器類似,F(xiàn)LAC對音頻的編碼需要經(jīng)過四階段:分塊、聲道去相關(guān)、預(yù)測編碼和殘差編碼。首先,把未經(jīng)壓縮的音頻流劃分為塊,并進(jìn)行獨立壓縮,分塊的大小是可變的;然后,對每個分塊進(jìn)行聲道去相關(guān)操作,去除聲道間的冗余信息;之后進(jìn)入預(yù)測器進(jìn)行預(yù)測編碼,分塊越大,壓縮等級越高,就越難以找到高效的壓縮模型;最后使用殘差編碼對預(yù)測編碼殘留下來的殘差進(jìn)行編碼,得到最終的音頻編碼信號。FLAC編碼過程如圖1所示。
圖2為FLAC音頻文件格式示意圖。所有FLAC文件都以四個字節(jié)的“fLaC”標(biāo)志開頭。FLAC文件標(biāo)志之后就是數(shù)個元數(shù)據(jù)塊,每個元數(shù)據(jù)塊用來描述特定的音頻信息。最后就是音頻幀。每個音頻幀主要包括了幀同步字、子幀樣本數(shù)量、采樣率、聲道分配、樣本采樣深度、CRC-8校驗碼以及編碼主數(shù)據(jù)。在FLAC比特流中,所有的數(shù)值都是整數(shù),沒有浮點運算。所有的數(shù)值都采用大端模塊,且如果沒有特殊說明,所有的數(shù)值都是無符號的。
2 FLAC音頻解碼器的設(shè)計
2.1 硬件結(jié)構(gòu)設(shè)計
FLAC音頻解碼器的整體設(shè)計框圖見圖3,其中FLAC音頻解碼器由以下9個模塊組成:FLAC文件緩存模塊、預(yù)處理模塊、主控模塊、元數(shù)據(jù)處理模塊、幀同步模塊、幀解碼模塊、左右聲道緩存、逆去相關(guān)模塊和I2S音頻接口模塊。其中主控模塊控制FLAC解碼器運行以及數(shù)據(jù)的流向。FLAC音頻解碼器除了有時鐘和復(fù)位信號外,與處理器連接的還有數(shù)據(jù)輸入端口、寫請求信號線和寫滿信號線。采用I2S音頻總線與音頻數(shù)模轉(zhuǎn)換芯片連接。FLAC音頻解碼器的各個模塊功能將在下面詳細(xì)介紹。
2.2 FLAC文件緩存模塊
FLAC文件緩存模塊負(fù)責(zé)儲存處理器傳遞進(jìn)來的FLAC數(shù)據(jù)。如圖4所示,F(xiàn)LAC文件緩存模塊由兩部分組成:FIFO模塊和啟動信號發(fā)生器。這里的FIFO輸入輸出寬度為32 bit,深度為1K。FIFO模塊的寫滿標(biāo)志信號線作為輸出外,還作為啟動信號發(fā)生器的輸入信號。為了減少操作的復(fù)雜性,此FLAC解碼器并不向外部提供專用的啟動控制信號線,筆者設(shè)計了如下自啟動方式:在處理器開始往解碼器寫入數(shù)據(jù)時,解碼器并沒有立即啟動相應(yīng)的模塊進(jìn)行解碼。當(dāng)FLAC文件緩存模塊首次緩存滿后,啟動信號發(fā)生器會產(chǎn)生一個有效的啟動信號,主控模塊檢測到啟動信號有效才會跳出空閑狀態(tài),啟動相應(yīng)的模塊開始進(jìn)行解碼。
2.3 預(yù)處理模塊
由于FLAC文件緩存模塊輸出的數(shù)據(jù)是并行數(shù)據(jù),而內(nèi)部各個模塊每次取數(shù)是不定長度的,為了降低取數(shù)操作的復(fù)雜性,本文設(shè)計了預(yù)處理模塊,負(fù)責(zé)將并行的碼流轉(zhuǎn)換成可取任意位碼元的碼流。預(yù)處理模塊為控制模塊提供編碼器輸入FIFO的狀態(tài)信息,當(dāng)其他模塊讀取數(shù)據(jù)前需要對FIFO空狀態(tài)進(jìn)行檢測。同時,預(yù)處理模塊還為幀解碼模塊提供字節(jié)對齊信息。
圖5給出了預(yù)處理模塊結(jié)構(gòu)框圖,其主要由兩部分組成:邊沿檢測器和任意位移位寄存器。邊沿檢測器將檢測到的讀請求信號電平變化轉(zhuǎn)換為與時鐘同步的單脈沖信號,以此作為任意移位寄存器移位控制信號。任意移位寄存器模塊的工作機(jī)制是根據(jù)輸入的移位比特數(shù)n,在讀請求信號的驅(qū)動下,將高位的n比特移出,更新輸出。
2.4 控制模塊
此模塊是整個FLAC解碼器的核心控制模塊,主要功能是檢測FLAC文件緩存的儲存狀態(tài),控制各個模塊的運行與停止,并響應(yīng)模塊解碼過程中反饋的信息,同時完成將FLAC文件數(shù)據(jù)傳送到相應(yīng)模塊。具體過程如圖6所示。在控制器中采用了狀態(tài)機(jī)的設(shè)計方式。
主控模塊的狀態(tài)機(jī)狀態(tài)有:Idle(空閑)、S1(解析元數(shù)據(jù))、S2(幀同步)、S3(幀解碼)、S4(完成文件解碼)、S5(解碼失敗)。
FLAC文件緩存模塊首次儲存滿時,向主控模塊發(fā)出Start信號有效,主控模塊檢測到啟動信號有效后會立即從預(yù)處理模塊獲取前4個字節(jié)的碼流,如果檢測到這4個字節(jié)是FLAC文件的標(biāo)志“FlaC”,則會進(jìn)入S1(元數(shù)據(jù)解析)狀態(tài),并啟動元數(shù)據(jù)解析模塊。如果檢測到不是有效和FLAC文件標(biāo)志,則會向外部處理發(fā)出文件錯誤信號。
在解析元數(shù)據(jù)過程中,如果FLAC元數(shù)據(jù)存在錯誤,元數(shù)據(jù)解析模塊會向主控模塊發(fā)出S1_Error信號有效,主控模塊檢測到此S1_Error信號有效后進(jìn)入S5(解碼失?。顟B(tài),并最終返回到Idle(空閑)狀態(tài),同時FLAC解碼器向外部處理器發(fā)出文件錯誤信號。如果元數(shù)據(jù)解析模塊成功完成所有元數(shù)據(jù)的解析工作,則會向主控模塊發(fā)出S1_Finish信號有效,主控模塊檢測到S1_Finish信號有效后會進(jìn)入S2(幀同步)狀態(tài),啟動幀同步模塊進(jìn)行幀同步。
幀同步模塊如果同步成功會產(chǎn)生Syn_Frame信號有效,主控模塊檢測到此有效信號會進(jìn)入S3(幀解碼)狀態(tài),并啟動幀解碼模塊開始解碼FLAC數(shù)據(jù)。幀解碼模塊完成一幀數(shù)據(jù)的解碼會向主控模塊發(fā)出有效的Finish信號,主控模塊據(jù)此會再次進(jìn)入S2(幀同步)狀態(tài),如此循環(huán),直到完成整個文件的解碼。
2.5 元數(shù)據(jù)解析模塊
FLAC最多支持128種元數(shù)據(jù)塊,目前只定義了7種。但并不是所有的元數(shù)據(jù)塊都對FALC解碼有用,因此本文設(shè)計的元數(shù)據(jù)解析模塊只對其中STREAMINFO類型的元數(shù)據(jù)進(jìn)行解析,其他類型的元數(shù)據(jù)塊不作解析。所有的FLAC文件都包含STREAMINFO類型的元數(shù)據(jù)塊,此元數(shù)據(jù)塊提供了關(guān)于整個FLAC音頻流的信息:采樣率、聲道數(shù)量、總采樣數(shù)等。其中的總采樣數(shù)參數(shù)提供給主控模塊,主控模塊將此總采樣數(shù)與當(dāng)前已經(jīng)解碼的采樣數(shù)進(jìn)行比較,以此來判斷是否完成整個FLAC的解碼。
2.6 幀解碼
解碼是編碼的反過程,解碼器并不關(guān)心FLAC文件的壓縮等級,而只需要根據(jù)FLAC文件中提供的編碼參數(shù)進(jìn)行解碼即可。與編碼過程相對應(yīng),解碼同樣也依次經(jīng)過四個階段:殘差解碼、預(yù)測編碼還原、逆去相關(guān)、重組。
2.6.1 殘差解碼
信號經(jīng)過預(yù)測編碼時,預(yù)測器不能非常精確的描述整個信號,因此使用預(yù)測模型描述的信號與原始信號是存在差值的。FLAC只采用一種方法(Rice Coding)對殘差進(jìn)行無損編碼,殘差編碼后的數(shù)據(jù)量遠(yuǎn)遠(yuǎn)小于原始數(shù)據(jù)量。對殘差編碼值進(jìn)行解碼很簡單,本文采用下面的算法對之進(jìn)行解碼。
解碼前需要從FLAC碼流中提取出相應(yīng)的殘差解碼參數(shù):階數(shù)m。假設(shè)S為當(dāng)前FLAC碼流,高位在前。首先對S從高位開始計算停止位“1”前“0”的個數(shù)為n。再從停止位“1”后面取出g比特的二進(jìn)制碼,用k表示此二進(jìn)制碼所代表的十進(jìn)制數(shù),再進(jìn)行如下計算:H=n*(2m)+g。最后根據(jù)下面的方法計算最終的解碼值X:
(1)如果H是偶數(shù),X=H/2;
(2)如果H是奇數(shù),X=-((H+1)/2)。
至此,殘差解碼已經(jīng)完成,解碼得到的X需要輸送到預(yù)測編碼還原模塊。需要指出的是,F(xiàn)LAC的殘差解碼采用四種預(yù)測模型:原樣模型、常量模型、固定的線性預(yù)測模型和FIR線性預(yù)測模型。而只有采用后兩種預(yù)測模型的編碼才會產(chǎn)生殘差,前兩種預(yù)測模型只在預(yù)測編碼還原階段進(jìn)行解碼還原。
2.6.2 預(yù)測編碼還原
如前文所述,F(xiàn)LAC有四種預(yù)測編碼模型,對使用原樣模塊和常量模型編碼的信號進(jìn)行還原比較簡單。如果是原樣模型,只需要根據(jù)幀頭部的編碼個數(shù)L和原樣模型中編碼長度n從FLAC碼流中直接提取L個長度為n編碼值即可。對于常量模型,需要從FLAC碼流中提取出一常量值,依次輸出L個此常量值即可。
對使用固定線性預(yù)測模型編碼得到的信號,還原信號等于預(yù)測值加上殘差值。預(yù)測值根據(jù)前n個訓(xùn)練樣本通過固定的預(yù)測算法計算得到。
對使用FIR線性預(yù)測模型編碼得到信號,計算過程稍微復(fù)雜些。在編碼時為了避免小數(shù)乘法運行,需要將實數(shù)型的預(yù)測因子都擴(kuò)大2n倍,舍去小數(shù),同樣也需要將原始信號擴(kuò)大2n倍。因此解碼時使用擴(kuò)大了的預(yù)測因子和訓(xùn)練樣本還原得到的信號需要縮小2n倍,再與所對應(yīng)的殘差相加得到還原信號。
2.7 逆去相關(guān)模塊
在立體聲音頻流中,左右聲道之間的相關(guān)性導(dǎo)致存在大量的冗余信息。FLAC有多種去除聲道相關(guān)性的方法。對一幀中,編碼器會選擇效果最優(yōu)的一種方法去除聲道相關(guān)性。
(1)獨立編碼。左右聲道分別獨立編碼,不做去相關(guān)性處理。
(2)中邊編碼。通過對左右聲道信號進(jìn)行運算產(chǎn)生中值聲道和邊值聲道。而且規(guī)定中值聲道是左右聲道信號的均值,邊值聲道都是左聲道減右聲道得到的。
(3)左邊編碼。被編碼成獨立的左聲道和差值聲道。
(4)右邊編碼。被編碼成獨立的右聲道和差值聲道。
逆去相關(guān)模塊內(nèi)部結(jié)構(gòu)如圖7所示。
逆去相關(guān)模塊主要由相關(guān)性還原模塊、聲道配置隊列模塊、采樣數(shù)隊列模塊和減法計數(shù)器等組成。由于左右聲道緩存中可能存在數(shù)幀,因此需要聲道配置隊列模塊和采樣數(shù)隊列模塊將左右聲道緩存中各個幀的聲道配置信息和采樣數(shù)緩存起來,采用減法計數(shù)器計算緩存中當(dāng)前剩余采樣數(shù),當(dāng)計數(shù)器計數(shù)到“0”時,會從采樣數(shù)隊列模塊中獲取下一幀的采樣數(shù)并預(yù)裝計數(shù)初值,同時聲道配置隊列模塊的輸出也更新到下一幀的聲道配置信息。相關(guān)性還原模塊根據(jù)新的聲道配置信息對新一幀的左右聲道數(shù)據(jù)進(jìn)行相關(guān)性還原。
2.8 I2S音頻接口
I2S有3個主要信號:(1)比特時鐘BCLK,即對應(yīng)數(shù)字音頻的每一位數(shù)據(jù),BCLK都有一個脈沖。BCLK的頻率=2×采樣頻率×采樣位數(shù);(2)幀時鐘LRCK,用于切換左右聲道的數(shù)據(jù)。LRCK的頻率等于采樣頻率;(3)串行數(shù)據(jù)SDATA,就是用二進(jìn)制補(bǔ)碼表示的音頻數(shù)據(jù)。有時為了使系統(tǒng)間能更好地同步,還需要另外傳輸一個信號MCLK,稱為主時鐘[3]。
為了解決音源采樣率的問題,實現(xiàn)對44.1 kHz和48 kHz音頻的精確采樣,本設(shè)計采用了雙晶振方案。22.579 2 MHz晶振用于44.1/88.2 kHz的音源采樣率,24.576 MHz用于48/96/192 kHz的音源采樣率。
本文設(shè)計的I2S音頻接口模塊由兩部分組成:分頻模塊和并串轉(zhuǎn)換模塊,如圖8所示。分頻模塊根據(jù)外部輸入的采樣率選擇22.579 2 MHz或者24.576 MHz作為輸入時鐘,并分頻出I2S的3個時鐘信號。同時分頻出的BCLK也作為并串轉(zhuǎn)換模塊的時鐘,并串轉(zhuǎn)換模塊將DATA信號總線上的數(shù)據(jù)以串行方式輸出。
3 系統(tǒng)仿真及分析
系統(tǒng)在Quartus II 12.0 中進(jìn)行設(shè)計、綜合仿真,并將設(shè)計下載到DE2-115開發(fā)板的Cyclone IV EP4CE115F29C7N上。為了驗證設(shè)計的正確性,通過modelsim工具對FLAC解碼器的工作狀況進(jìn)行仿真驗證。筆者編寫了test_bench文件讀取計算機(jī)中的音頻文件輸入到FLAC解碼器中。圖9為解碼器解碼輸出時序。從圖中可看出,F(xiàn)LAC解碼器能實現(xiàn)正確解碼,且I2S音頻接口模塊各種信號完全滿足時序要求。
4 總結(jié)
為了解決高保真FLAC音頻播放系統(tǒng)中軟件解碼效率低下、占用系統(tǒng)資源大的問題,本文提出了一種基于FPGA的FLAC音頻硬解碼的設(shè)計方案。本設(shè)計采用Verilog語言,在ALTERA公司的FPGA(Cyclone IV EP4CE115F29C7N)芯片上成功實現(xiàn)了對FLAC音頻文件的解碼。利用FPGA實現(xiàn)FLAC音頻的解碼器可以作為IP核應(yīng)用于不同的SoC音頻播放系統(tǒng)中,有助于縮短產(chǎn)品的開發(fā)周期。
參考文獻(xiàn)
[1] COALSON J.Flac-free lossless audio codec[EB/OL].(2014-12-27)[2015-5-2].http://xiph.org/flac/index.html.
[2] 夏宇聞.Verilog數(shù)字系統(tǒng)設(shè)計教程[M].北京:北京航空航天大學(xué)出版社,2003.
[3] 張景璐,周金和,朱恭生,等.IIS接口的FPGA實現(xiàn)[J].電子技術(shù)應(yīng)用,2007(6).