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