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

weixin_34402090發表於2011-07-21

Speex是近年來開發出的一套功能強大的語音引擎,能夠實現高質量和低位元率的編碼。它不僅提供了基於碼激勵線性預測(CELP)演算法的編/解碼模組,而且在其最新發布的版本中還提供了聲音預處理和聲學回聲消除模組,為保障IP網路中的語音通訊質量提供了技術手段。此外,Speex還具有壓縮後的位元率低(2~44 kbps)的特點,並支援多種位元率。這些特點使得Speex特別適合VoIP的系統。

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

一:編碼流程

   使用SpeexAPI函式對音訊資料進行壓縮編碼要經過如下步驟:

1、      定義一個SpeexBits型別變數bits和一個Speex編碼器狀態變數enc_state

2、     呼叫speex_bits_init(&bits)初始化bits

3、    呼叫speex_encoder_init(&speex_nb_mode)來初始化enc_state。其中speex_nb_modeSpeexMode型別的變數,表示的是窄帶模式。還有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和解碼器。

下面是一段例項程式碼:

轉載請註明:http://hi.baidu.com/a%CC%C7%B3%B4%C0%F5%D7%D3a/

#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;

}

相關文章