天天看點

音頻編解碼-speex庫的使用方法

Speex是近年來開發出的一套功能強大的語音引擎,能夠實作高品質和低比特率的編碼。它不僅提供了基于碼激勵線性預測(CELP)算法的編/解碼子產品, 而且在其最新釋出的版本中還提供了聲音預處理和聲學回聲消除子產品,為保障IP網絡中的語音通信品質提供了技術手段。此外,Speex還具有壓縮後的比特率 低(2~44 kbps)的特點,并支援多種比特率。這些特點使得Speex特别适合VoIP的系統。

雖然是開源的,但是使用的人還不是很多,網上的資料也很少,下面簡單給大家介紹一下如何使用speex的API。

一:編碼流程

使用Speex的API函數對音頻資料進行壓縮編碼要經過如下步驟:

1、定義一個SpeexBits類型變量bits和一個Speex編碼器狀态變量enc_state。

2、調用speex_bits_init(&bits)初始化bits。

3、調用speex_encoder_init(&speex_nb_mode)來初始化enc_state。其中speex_nb_mode是SpeexMode類型的變量,表示的是窄帶模式。還有speex_wb_mode表示寬帶模式、speex_uwb_mode表示超寬帶模式。

4、調用函數int speex_encoder_ ctl(void *state, int request, void *ptr)來設定編碼器的參數,其中參數state表示編碼器的狀态;參數request表示要定義的參數類型,如SPEEX_ GET_ FRAME_SIZE表示設定幀大小,SPEEX_ SET_QUALITY表示量化大小,這決定了編碼的品質;參數ptr表示要設定的值。

可通過speex_encoder_ctl(enc_state, SPEEX_GET_FRAME_SIZE, &frame_size) 和speex_encoder_ctl(enc_state, SPEEX_SET_QUALITY, &quality)來設定編碼器的參數。

5、初始化完畢後,對每一幀聲音作如下處理:調用函數speex_bits_reset(&bits)再次設定SpeexBits,然後調用函數speex_encode(enc_state, input_frame, &bits),參數bits中儲存編碼後的資料流。

6、編碼結束後,調用函數speex_bits_destroy (&bits),    speex_encoder_destroy (enc_state)來

二:解碼流程

同樣,對已經編碼過的音頻資料進行解碼要經過以下步驟:

1、     定義一個SpeexBits類型變量bits和一個Speex編碼狀态變量enc_state。

2、   調用speex_bits_init(&bits)初始化bits。

3、   調用speex_decoder_init (&speex_nb_mode)來初始化enc_state。

4、    調用函數speex_decoder_ctl (void *state, int request, void *ptr)來設定編碼器的參數。

5、   調用函數 speex_decode(void *state, SpeexBits *bits, float *out)對參數bits中的音頻資料進行解編碼,參數out中儲存解碼後的資料流。

6、   調用函數speex_bits_destroy(&bits), speex_ decoder_ destroy (void *state)來關閉和銷毀SpeexBits和解碼器。

下面是一段執行個體代碼:

#include <speex.h> 

#include <stdio.h> 

/*幀的大小在這個例程中是一個固定的值,但它并不是必須這樣*/ 

#define FRAME_SIZE 160 

int main(int argc, char **argv) 

char *inFile; 

FILE *fin; 

short in[FRAME_SIZE]; 

float input[FRAME_SIZE]; 

char cbits[200]; 

int nbBytes; 

/*儲存編碼的狀态*/ 

void *state; 

/*儲存位元組是以他們可以被speex正常讀寫*/ 

SpeexBits bits; 

int i, tmp; 

//建立一個新的編碼狀态在窄寬(narrowband)模式下 

state = speex_encoder_init(&speex_nb_mode); 

//設定品質為8(15kbps) 

tmp=8; 

speex_encoder_ctl(state, SPEEX_SET_QUALITY, &tmp); 

inFile = argv[1]; 

fin = fopen(inFile, "r"); 

//初始化結構使他們儲存資料 

speex_bits_init(&bits); 

while (1) 

//讀入一幀16bits的聲音 

fread(in, sizeof(short), FRAME_SIZE, fin); 

if (feof(fin)) 

break; 

//把16bits的值轉化為float,以便speex庫可以在上面工作 

for (i=0;i<FRAME_SIZE;i++) 

input[i]=in[i]; 

//清空這個結構體裡所有的位元組,以便我們可以編碼一個新的幀 

speex_bits_reset(&bits); 

//對幀進行編碼 

speex_encode(state, input, &bits); 

//把bits拷貝到一個利用寫出的char型數組 

nbBytes = speex_bits_write(&bits, cbits, 200); 

//首先寫出幀的大小,這是sampledec檔案需要的一個值,但是你的應用程式中可能不一樣 

fwrite(&nbBytes, sizeof(int), 1, stdout); 

//寫出壓縮後的數組 

fwrite(cbits, 1, nbBytes, stdout); 

//釋放編碼器狀态量 

speex_encoder_destroy(state); 

//釋放bit_packing結構 

speex_bits_destroy(&bits); 

fclose(fin); 

return 0; 

繼續閱讀