文獻(xiàn)標(biāo)識碼: A
DOI:10.16157/j.issn.0258-7998.2016.02.005
中文引用格式: 劉喬壽,,黃國臣,,吉福生. 基于FPGA的FLAC音頻硬解碼的設(shè)計(jì)與實(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音頻的特點(diǎn)而設(shè)計(jì)的壓縮方式?,F(xiàn)今大多數(shù)據(jù)系統(tǒng)采用專用芯片或者軟件實(shí)現(xiàn)FLAC音頻的解碼。使用專用芯片靈活性差,,不利于FLAC解碼器的特殊應(yīng)用,。而軟件實(shí)現(xiàn)解碼需要占用大量的系統(tǒng)資源,且解碼效率低,。
FPGA具有運(yùn)行速度快,、可重復(fù)編程、集成度高等優(yōu)點(diǎn),,是進(jìn)行原始設(shè)計(jì)最理想的載體[2],。為此,筆者以音頻播放系統(tǒng)中FLAC解碼為應(yīng)用背景,,提出了一種采用Verilog 語言設(shè)計(jì)的通用FLAC音頻解碼器的FPGA模塊化解決方案,。所設(shè)計(jì)的解碼器可作為IP核用于專用音頻集成電路設(shè)計(jì)或者FPGA設(shè)計(jì)中,可以縮短設(shè)計(jì)周期,,提高系統(tǒng)設(shè)計(jì)的成功率,。
1 FLAC編碼原理及FALC音頻格式
與其他的音頻編碼器類似,,F(xiàn)LAC對音頻的編碼需要經(jīng)過四階段:分塊、聲道去相關(guān),、預(yù)測編碼和殘差編碼,。首先,把未經(jīng)壓縮的音頻流劃分為塊,,并進(jìn)行獨(dú)立壓縮,,分塊的大小是可變的;然后,,對每個分塊進(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校驗(yàn)碼以及編碼主數(shù)據(jù),。在FLAC比特流中,,所有的數(shù)值都是整數(shù),沒有浮點(diǎn)運(yùn)算,。所有的數(shù)值都采用大端模塊,,且如果沒有特殊說明,所有的數(shù)值都是無符號的,。
2 FLAC音頻解碼器的設(shè)計(jì)
2.1 硬件結(jié)構(gòu)設(shè)計(jì)
FLAC音頻解碼器的整體設(shè)計(jì)框圖見圖3,,其中FLAC音頻解碼器由以下9個模塊組成:FLAC文件緩存模塊、預(yù)處理模塊,、主控模塊,、元數(shù)據(jù)處理模塊,、幀同步模塊、幀解碼模塊,、左右聲道緩存,、逆去相關(guān)模塊和I2S音頻接口模塊。其中主控模塊控制FLAC解碼器運(yùn)行以及數(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è)計(jì)了如下自啟動方式:在處理器開始往解碼器寫入數(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è)計(jì)了預(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ù)輸入的移位比特?cái)?shù)n,,在讀請求信號的驅(qū)動下,,將高位的n比特移出,更新輸出,。
2.4 控制模塊
此模塊是整個FLAC解碼器的核心控制模塊,,主要功能是檢測FLAC文件緩存的儲存狀態(tài),控制各個模塊的運(yùn)行與停止,,并響應(yīng)模塊解碼過程中反饋的信息,,同時完成將FLAC文件數(shù)據(jù)傳送到相應(yīng)模塊。具體過程如圖6所示,。在控制器中采用了狀態(tài)機(jī)的設(shè)計(jì)方式,。
主控模塊的狀態(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(解碼失敗)狀態(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è)計(jì)的元數(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從高位開始計(jì)算停止位“1”前“0”的個數(shù)為n,。再從停止位“1”后面取出g比特的二進(jìn)制碼,用k表示此二進(jìn)制碼所代表的十進(jìn)制數(shù),,再進(jìn)行如下計(jì)算:H=n*(2m)+g,。最后根據(jù)下面的方法計(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ù)測算法計(jì)算得到,。
對使用FIR線性預(yù)測模型編碼得到信號,,計(jì)算過程稍微復(fù)雜些。在編碼時為了避免小數(shù)乘法運(yùn)行,,需要將實(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)獨(dú)立編碼,。左右聲道分別獨(dú)立編碼,,不做去相關(guān)性處理。
(2)中邊編碼。通過對左右聲道信號進(jìn)行運(yùn)算產(chǎn)生中值聲道和邊值聲道,。而且規(guī)定中值聲道是左右聲道信號的均值,,邊值聲道都是左聲道減右聲道得到的。
(3)左邊編碼,。被編碼成獨(dú)立的左聲道和差值聲道,。
(4)右邊編碼。被編碼成獨(dú)立的右聲道和差值聲道,。
逆去相關(guān)模塊內(nèi)部結(jié)構(gòu)如圖7所示,。
逆去相關(guān)模塊主要由相關(guān)性還原模塊、聲道配置隊(duì)列模塊,、采樣數(shù)隊(duì)列模塊和減法計(jì)數(shù)器等組成,。由于左右聲道緩存中可能存在數(shù)幀,因此需要聲道配置隊(duì)列模塊和采樣數(shù)隊(duì)列模塊將左右聲道緩存中各個幀的聲道配置信息和采樣數(shù)緩存起來,,采用減法計(jì)數(shù)器計(jì)算緩存中當(dāng)前剩余采樣數(shù),,當(dāng)計(jì)數(shù)器計(jì)數(shù)到“0”時,會從采樣數(shù)隊(duì)列模塊中獲取下一幀的采樣數(shù)并預(yù)裝計(jì)數(shù)初值,,同時聲道配置隊(duì)列模塊的輸出也更新到下一幀的聲道配置信息,。相關(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]。
為了解決音源采樣率的問題,,實(shí)現(xiàn)對44.1 kHz和48 kHz音頻的精確采樣,,本設(shè)計(jì)采用了雙晶振方案。22.579 2 MHz晶振用于44.1/88.2 kHz的音源采樣率,,24.576 MHz用于48/96/192 kHz的音源采樣率,。
本文設(shè)計(jì)的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è)計(jì),、綜合仿真,并將設(shè)計(jì)下載到DE2-115開發(fā)板的Cyclone IV EP4CE115F29C7N上,。為了驗(yàn)證設(shè)計(jì)的正確性,,通過modelsim工具對FLAC解碼器的工作狀況進(jìn)行仿真驗(yàn)證。筆者編寫了test_bench文件讀取計(jì)算機(jī)中的音頻文件輸入到FLAC解碼器中,。圖9為解碼器解碼輸出時序,。從圖中可看出,F(xiàn)LAC解碼器能實(shí)現(xiàn)正確解碼,,且I2S音頻接口模塊各種信號完全滿足時序要求,。
4 總結(jié)
為了解決高保真FLAC音頻播放系統(tǒng)中軟件解碼效率低下、占用系統(tǒng)資源大的問題,,本文提出了一種基于FPGA的FLAC音頻硬解碼的設(shè)計(jì)方案,。本設(shè)計(jì)采用Verilog語言,在ALTERA公司的FPGA(Cyclone IV EP4CE115F29C7N)芯片上成功實(shí)現(xiàn)了對FLAC音頻文件的解碼,。利用FPGA實(shí)現(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è)計(jì)教程[M].北京:北京航空航天大學(xué)出版社,,2003.
[3] 張景璐,,周金和,朱恭生,,等.IIS接口的FPGA實(shí)現(xiàn)[J].電子技術(shù)應(yīng)用,,2007(6).