文獻(xiàn)標(biāo)識(shí)碼: A
DOI:10.16157/j.issn.0258-7998.2016.02.005
中文引用格式: 劉喬壽,,黃國(guó)臣,,吉福生. 基于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是音頻的無(wú)損壓縮格式,,即音頻以FALC編碼解碼后不會(huì)丟失任何信息,,F(xiàn)LAC音頻文件解碼還原為WAV文件后,與壓縮前的WAV文件內(nèi)容是一樣的[1],。FLAC是專門針對(duì)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 語(yǔ)言設(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對(duì)音頻的編碼需要經(jīng)過(guò)四階段:分塊,、聲道去相關(guān)、預(yù)測(cè)編碼和殘差編碼。首先,,把未經(jīng)壓縮的音頻流劃分為塊,,并進(jìn)行獨(dú)立壓縮,分塊的大小是可變的,;然后,,對(duì)每個(gè)分塊進(jìn)行聲道去相關(guān)操作,去除聲道間的冗余信息,;之后進(jìn)入預(yù)測(cè)器進(jìn)行預(yù)測(cè)編碼,,分塊越大,壓縮等級(jí)越高,,就越難以找到高效的壓縮模型,;最后使用殘差編碼對(duì)預(yù)測(cè)編碼殘留下來(lái)的殘差進(jìn)行編碼,得到最終的音頻編碼信號(hào),。FLAC編碼過(guò)程如圖1所示,。
圖2為FLAC音頻文件格式示意圖。所有FLAC文件都以四個(gè)字節(jié)的“fLaC”標(biāo)志開頭,。FLAC文件標(biāo)志之后就是數(shù)個(gè)元數(shù)據(jù)塊,,每個(gè)元數(shù)據(jù)塊用來(lái)描述特定的音頻信息。最后就是音頻幀,。每個(gè)音頻幀主要包括了幀同步字,、子幀樣本數(shù)量、采樣率,、聲道分配,、樣本采樣深度、CRC-8校驗(yàn)碼以及編碼主數(shù)據(jù),。在FLAC比特流中,,所有的數(shù)值都是整數(shù),沒有浮點(diǎn)運(yùn)算,。所有的數(shù)值都采用大端模塊,,且如果沒有特殊說(shuō)明,所有的數(shù)值都是無(wú)符號(hào)的,。
2 FLAC音頻解碼器的設(shè)計(jì)
2.1 硬件結(jié)構(gòu)設(shè)計(jì)
FLAC音頻解碼器的整體設(shè)計(jì)框圖見圖3,,其中FLAC音頻解碼器由以下9個(gè)模塊組成:FLAC文件緩存模塊、預(yù)處理模塊,、主控模塊,、元數(shù)據(jù)處理模塊、幀同步模塊,、幀解碼模塊,、左右聲道緩存,、逆去相關(guān)模塊和I2S音頻接口模塊。其中主控模塊控制FLAC解碼器運(yùn)行以及數(shù)據(jù)的流向,。FLAC音頻解碼器除了有時(shí)鐘和復(fù)位信號(hào)外,,與處理器連接的還有數(shù)據(jù)輸入端口、寫請(qǐng)求信號(hào)線和寫滿信號(hào)線,。采用I2S音頻總線與音頻數(shù)模轉(zhuǎn)換芯片連接,。FLAC音頻解碼器的各個(gè)模塊功能將在下面詳細(xì)介紹。
2.2 FLAC文件緩存模塊
FLAC文件緩存模塊負(fù)責(zé)儲(chǔ)存處理器傳遞進(jìn)來(lái)的FLAC數(shù)據(jù),。如圖4所示,,F(xiàn)LAC文件緩存模塊由兩部分組成:FIFO模塊和啟動(dòng)信號(hào)發(fā)生器。這里的FIFO輸入輸出寬度為32 bit,,深度為1K,。FIFO模塊的寫滿標(biāo)志信號(hào)線作為輸出外,還作為啟動(dòng)信號(hào)發(fā)生器的輸入信號(hào),。為了減少操作的復(fù)雜性,,此FLAC解碼器并不向外部提供專用的啟動(dòng)控制信號(hào)線,筆者設(shè)計(jì)了如下自啟動(dòng)方式:在處理器開始往解碼器寫入數(shù)據(jù)時(shí),,解碼器并沒有立即啟動(dòng)相應(yīng)的模塊進(jìn)行解碼,。當(dāng)FLAC文件緩存模塊首次緩存滿后,啟動(dòng)信號(hào)發(fā)生器會(huì)產(chǎn)生一個(gè)有效的啟動(dòng)信號(hào),,主控模塊檢測(cè)到啟動(dòng)信號(hào)有效才會(huì)跳出空閑狀態(tài),,啟動(dòng)相應(yīng)的模塊開始進(jìn)行解碼。
2.3 預(yù)處理模塊
由于FLAC文件緩存模塊輸出的數(shù)據(jù)是并行數(shù)據(jù),,而內(nèi)部各個(gè)模塊每次取數(shù)是不定長(zhǎng)度的,,為了降低取數(shù)操作的復(fù)雜性,本文設(shè)計(jì)了預(yù)處理模塊,,負(fù)責(zé)將并行的碼流轉(zhuǎn)換成可取任意位碼元的碼流,。預(yù)處理模塊為控制模塊提供編碼器輸入FIFO的狀態(tài)信息,當(dāng)其他模塊讀取數(shù)據(jù)前需要對(duì)FIFO空狀態(tài)進(jìn)行檢測(cè),。同時(shí),,預(yù)處理模塊還為幀解碼模塊提供字節(jié)對(duì)齊信息。
圖5給出了預(yù)處理模塊結(jié)構(gòu)框圖,,其主要由兩部分組成:邊沿檢測(cè)器和任意位移位寄存器。邊沿檢測(cè)器將檢測(cè)到的讀請(qǐng)求信號(hào)電平變化轉(zhuǎn)換為與時(shí)鐘同步的單脈沖信號(hào),,以此作為任意移位寄存器移位控制信號(hào),。任意移位寄存器模塊的工作機(jī)制是根據(jù)輸入的移位比特?cái)?shù)n,在讀請(qǐng)求信號(hào)的驅(qū)動(dòng)下,,將高位的n比特移出,,更新輸出,。
2.4 控制模塊
此模塊是整個(gè)FLAC解碼器的核心控制模塊,主要功能是檢測(cè)FLAC文件緩存的儲(chǔ)存狀態(tài),,控制各個(gè)模塊的運(yùn)行與停止,,并響應(yīng)模塊解碼過(guò)程中反饋的信息,同時(shí)完成將FLAC文件數(shù)據(jù)傳送到相應(yīng)模塊,。具體過(guò)程如圖6所示,。在控制器中采用了狀態(tài)機(jī)的設(shè)計(jì)方式。
主控模塊的狀態(tài)機(jī)狀態(tài)有:Idle(空閑),、S1(解析元數(shù)據(jù)),、S2(幀同步)、S3(幀解碼),、S4(完成文件解碼),、S5(解碼失敗)。
FLAC文件緩存模塊首次儲(chǔ)存滿時(shí),,向主控模塊發(fā)出Start信號(hào)有效,,主控模塊檢測(cè)到啟動(dòng)信號(hào)有效后會(huì)立即從預(yù)處理模塊獲取前4個(gè)字節(jié)的碼流,如果檢測(cè)到這4個(gè)字節(jié)是FLAC文件的標(biāo)志“FlaC”,,則會(huì)進(jìn)入S1(元數(shù)據(jù)解析)狀態(tài),,并啟動(dòng)元數(shù)據(jù)解析模塊。如果檢測(cè)到不是有效和FLAC文件標(biāo)志,,則會(huì)向外部處理發(fā)出文件錯(cuò)誤信號(hào),。
在解析元數(shù)據(jù)過(guò)程中,如果FLAC元數(shù)據(jù)存在錯(cuò)誤,,元數(shù)據(jù)解析模塊會(huì)向主控模塊發(fā)出S1_Error信號(hào)有效,,主控模塊檢測(cè)到此S1_Error信號(hào)有效后進(jìn)入S5(解碼失敗)狀態(tài),,并最終返回到Idle(空閑)狀態(tài),,同時(shí)FLAC解碼器向外部處理器發(fā)出文件錯(cuò)誤信號(hào)。如果元數(shù)據(jù)解析模塊成功完成所有元數(shù)據(jù)的解析工作,,則會(huì)向主控模塊發(fā)出S1_Finish信號(hào)有效,,主控模塊檢測(cè)到S1_Finish信號(hào)有效后會(huì)進(jìn)入S2(幀同步)狀態(tài),啟動(dòng)幀同步模塊進(jìn)行幀同步,。
幀同步模塊如果同步成功會(huì)產(chǎn)生Syn_Frame信號(hào)有效,,主控模塊檢測(cè)到此有效信號(hào)會(huì)進(jìn)入S3(幀解碼)狀態(tài),并啟動(dòng)幀解碼模塊開始解碼FLAC數(shù)據(jù),。幀解碼模塊完成一幀數(shù)據(jù)的解碼會(huì)向主控模塊發(fā)出有效的Finish信號(hào),,主控模塊據(jù)此會(huì)再次進(jìn)入S2(幀同步)狀態(tài),如此循環(huán),,直到完成整個(gè)文件的解碼,。
2.5 元數(shù)據(jù)解析模塊
FLAC最多支持128種元數(shù)據(jù)塊,,目前只定義了7種。但并不是所有的元數(shù)據(jù)塊都對(duì)FALC解碼有用,,因此本文設(shè)計(jì)的元數(shù)據(jù)解析模塊只對(duì)其中STREAMINFO類型的元數(shù)據(jù)進(jìn)行解析,,其他類型的元數(shù)據(jù)塊不作解析。所有的FLAC文件都包含STREAMINFO類型的元數(shù)據(jù)塊,,此元數(shù)據(jù)塊提供了關(guān)于整個(gè)FLAC音頻流的信息:采樣率,、聲道數(shù)量、總采樣數(shù)等,。其中的總采樣數(shù)參數(shù)提供給主控模塊,,主控模塊將此總采樣數(shù)與當(dāng)前已經(jīng)解碼的采樣數(shù)進(jìn)行比較,以此來(lái)判斷是否完成整個(gè)FLAC的解碼,。
2.6 幀解碼
解碼是編碼的反過(guò)程,,解碼器并不關(guān)心FLAC文件的壓縮等級(jí),而只需要根據(jù)FLAC文件中提供的編碼參數(shù)進(jìn)行解碼即可,。與編碼過(guò)程相對(duì)應(yīng),,解碼同樣也依次經(jīng)過(guò)四個(gè)階段:殘差解碼、預(yù)測(cè)編碼還原,、逆去相關(guān),、重組。
2.6.1 殘差解碼
信號(hào)經(jīng)過(guò)預(yù)測(cè)編碼時(shí),,預(yù)測(cè)器不能非常精確的描述整個(gè)信號(hào),,因此使用預(yù)測(cè)模型描述的信號(hào)與原始信號(hào)是存在差值的。FLAC只采用一種方法(Rice Coding)對(duì)殘差進(jìn)行無(wú)損編碼,,殘差編碼后的數(shù)據(jù)量遠(yuǎn)遠(yuǎn)小于原始數(shù)據(jù)量,。對(duì)殘差編碼值進(jìn)行解碼很簡(jiǎn)單,本文采用下面的算法對(duì)之進(jìn)行解碼,。
解碼前需要從FLAC碼流中提取出相應(yīng)的殘差解碼參數(shù):階數(shù)m,。假設(shè)S為當(dāng)前FLAC碼流,高位在前,。首先對(duì)S從高位開始計(jì)算停止位“1”前“0”的個(gè)數(shù)為n,。再?gòu)耐V刮弧?”后面取出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ù)測(cè)編碼還原模塊。需要指出的是,,F(xiàn)LAC的殘差解碼采用四種預(yù)測(cè)模型:原樣模型,、常量模型、固定的線性預(yù)測(cè)模型和FIR線性預(yù)測(cè)模型,。而只有采用后兩種預(yù)測(cè)模型的編碼才會(huì)產(chǎn)生殘差,,前兩種預(yù)測(cè)模型只在預(yù)測(cè)編碼還原階段進(jìn)行解碼還原。
2.6.2 預(yù)測(cè)編碼還原
如前文所述,,F(xiàn)LAC有四種預(yù)測(cè)編碼模型,,對(duì)使用原樣模塊和常量模型編碼的信號(hào)進(jìn)行還原比較簡(jiǎn)單。如果是原樣模型,,只需要根據(jù)幀頭部的編碼個(gè)數(shù)L和原樣模型中編碼長(zhǎng)度n從FLAC碼流中直接提取L個(gè)長(zhǎng)度為n編碼值即可,。對(duì)于常量模型,需要從FLAC碼流中提取出一常量值,,依次輸出L個(gè)此常量值即可,。
對(duì)使用固定線性預(yù)測(cè)模型編碼得到的信號(hào),還原信號(hào)等于預(yù)測(cè)值加上殘差值,。預(yù)測(cè)值根據(jù)前n個(gè)訓(xùn)練樣本通過(guò)固定的預(yù)測(cè)算法計(jì)算得到,。
對(duì)使用FIR線性預(yù)測(cè)模型編碼得到信號(hào),計(jì)算過(guò)程稍微復(fù)雜些,。在編碼時(shí)為了避免小數(shù)乘法運(yùn)行,,需要將實(shí)數(shù)型的預(yù)測(cè)因子都擴(kuò)大2n倍,舍去小數(shù),,同樣也需要將原始信號(hào)擴(kuò)大2n倍,。因此解碼時(shí)使用擴(kuò)大了的預(yù)測(cè)因子和訓(xùn)練樣本還原得到的信號(hào)需要縮小2n倍,再與所對(duì)應(yīng)的殘差相加得到還原信號(hào),。
2.7 逆去相關(guān)模塊
在立體聲音頻流中,,左右聲道之間的相關(guān)性導(dǎo)致存在大量的冗余信息。FLAC有多種去除聲道相關(guān)性的方法,。對(duì)一幀中,,編碼器會(huì)選擇效果最優(yōu)的一種方法去除聲道相關(guān)性。
(1)獨(dú)立編碼,。左右聲道分別獨(dú)立編碼,,不做去相關(guān)性處理。
(2)中邊編碼,。通過(guò)對(duì)左右聲道信號(hào)進(jìn)行運(yùn)算產(chǎn)生中值聲道和邊值聲道,。而且規(guī)定中值聲道是左右聲道信號(hào)的均值,邊值聲道都是左聲道減右聲道得到的,。
(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ì)列模塊將左右聲道緩存中各個(gè)幀的聲道配置信息和采樣數(shù)緩存起來(lái),,采用減法計(jì)數(shù)器計(jì)算緩存中當(dāng)前剩余采樣數(shù),,當(dāng)計(jì)數(shù)器計(jì)數(shù)到“0”時(shí),會(huì)從采樣數(shù)隊(duì)列模塊中獲取下一幀的采樣數(shù)并預(yù)裝計(jì)數(shù)初值,,同時(shí)聲道配置隊(duì)列模塊的輸出也更新到下一幀的聲道配置信息,。相關(guān)性還原模塊根據(jù)新的聲道配置信息對(duì)新一幀的左右聲道數(shù)據(jù)進(jìn)行相關(guān)性還原。
2.8 I2S音頻接口
I2S有3個(gè)主要信號(hào):(1)比特時(shí)鐘BCLK,,即對(duì)應(yīng)數(shù)字音頻的每一位數(shù)據(jù),,BCLK都有一個(gè)脈沖。BCLK的頻率=2×采樣頻率×采樣位數(shù),;(2)幀時(shí)鐘LRCK,,用于切換左右聲道的數(shù)據(jù)。LRCK的頻率等于采樣頻率,;(3)串行數(shù)據(jù)SDATA,,就是用二進(jìn)制補(bǔ)碼表示的音頻數(shù)據(jù)。有時(shí)為了使系統(tǒng)間能更好地同步,,還需要另外傳輸一個(gè)信號(hào)MCLK,,稱為主時(shí)鐘[3]。
為了解決音源采樣率的問(wèn)題,,實(shí)現(xiàn)對(duì)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作為輸入時(shí)鐘,,并分頻出I2S的3個(gè)時(shí)鐘信號(hào)。同時(shí)分頻出的BCLK也作為并串轉(zhuǎn)換模塊的時(shí)鐘,,并串轉(zhuǎn)換模塊將DATA信號(hào)總線上的數(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ì)的正確性,,通過(guò)modelsim工具對(duì)FLAC解碼器的工作狀況進(jìn)行仿真驗(yàn)證。筆者編寫了test_bench文件讀取計(jì)算機(jī)中的音頻文件輸入到FLAC解碼器中,。圖9為解碼器解碼輸出時(shí)序,。從圖中可看出,F(xiàn)LAC解碼器能實(shí)現(xiàn)正確解碼,,且I2S音頻接口模塊各種信號(hào)完全滿足時(shí)序要求。
4 總結(jié)
為了解決高保真FLAC音頻播放系統(tǒng)中軟件解碼效率低下,、占用系統(tǒng)資源大的問(wèn)題,,本文提出了一種基于FPGA的FLAC音頻硬解碼的設(shè)計(jì)方案。本設(shè)計(jì)采用Verilog語(yǔ)言,,在ALTERA公司的FPGA(Cyclone IV EP4CE115F29C7N)芯片上成功實(shí)現(xiàn)了對(duì)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).