speexの基本符号化と復号化の流れ


最近speexの符号化と復号化の流れを研究している.
以前はIMで音声クリップを使っていましたが、これは簡単で、googlecodeのgaussのコードを見つけて、セットすれば使えます.
しかしgooglecodeは閉じて、ある人は彼をgithubに導入して、住所はここにありますhttps://github.com/cczufish/OggSpeex-android
私も導入しましたが、成功していません.何の問題か分かりません.レベルが足りないかもしれません.ははははhttps://github.com/dongweiq/android-recorder
音声クリップをつなぎ合わせて合成し、UIに再生中の時間を表示する必要がある.gaussのコードを見てみると、彼のコードは復号しながら再生され、short[160]のクリップに従って一つ一つ再生されていることが分かった.
 1 /* decode each segment, writing output to wav */

 2                 for (curseg = 0; curseg < segments; curseg++) {

 3 

 4                     if (Thread.interrupted()) {

 5                         dis.close();

 6                         track.stop();

 7                         track.release();

 8                         return;

 9                     }

10 

11                     while (this.isPaused()) {

12                         track.stop();

13                         track.release();

14                         // Thread.sleep(100);

15                     }

16 

17                     /* get the number of bytes in the segment */

18                     bodybytes = header[OGG_HEADERSIZE + curseg] & 0xFF;

19                     if (bodybytes == 255) {

20                         System.err.println("sorry, don't handle 255 sizes!");

21                         return;

22                     }

23                     dis.readFully(payload, 0, bodybytes);

24                     chksum = OggCrc.checksum(chksum, payload, 0, bodybytes);

25 

26                     /* decode the segment */

27                     /* if first packet, read the Speex header */

28                     if (packetNo == 0) {

29                         if (readSpeexHeader(payload, 0, bodybytes, true)) {

30                             packetNo++;

31                         } else {

32                             packetNo = 0;

33                         }

34                     } else if (packetNo == 1) { // Ogg Comment packet

35                         packetNo++;

36                     } else {

37 

38                         /* get the amount of decoded data */

39                         short[] decoded = new short[160];

40                         if ((decsize = speexDecoder.decode(payload, decoded, 160)) > 0) {

41                             track.write(decoded, 0, decsize);

42                             float maxVol = AudioTrack.getMaxVolume();

43                             track.setStereoVolume(maxVol, maxVol);//  

44                             track.play();

45                         }

46                         packetNo++;

47                     }

48                 }

また、pacetNoが0の場合はspeexのファイルヘッダで80バイトを占め、packetNoが1の場合はパケット番号2を検索し、2の場合は160 shortでオーディオを復号し、復号後のwavを再生するパケット番号もある.
その後、ネット上で以下の内容を見つけました.http://blog.163.com/yuan_zhch/blog/static/193790046201172611527217/
speex全体の符号化と復号化の過程の総括に相当するだろう.
一:符号化プロセス
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は、SPEX_などの定義するパラメータのタイプを表します.GET_ FRAME_SIZEは設定フレームサイズを表し、SPEX_SET_QUALITYは量子化サイズを表し、これは符号化の品質を決定する.パラメータptrは、設定する値を表します.
speex_経由encoder_ctl(enc_state,SPEX_GET_FRAME_SIZE,&frame_size)とspeex_encoder_ctl(enc_state,SPEX_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  
  • #include  
  • /*フレームのサイズはこのルーチンでは一定の値であるが、必ずしもそうではない*/
  • #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(15 kbps)
  • tmp=8; 
  • speex_encoder_ctl(state, SPEEX_SET_QUALITY, &tmp); 
  • inFile = argv[1]; 
  •   
  • fin = fopen(inFile, "r"); 
  • //初期化構造によりデータ
  • を保存
  • speex_bits_init(&bits); 
  • while (1) 
  • //1フレーム16 bitsの音
  • を読み込む
  • fread(in, sizeof(short), FRAME_SIZE, fin); 
  • if (feof(fin)) 
  • break; 
  • //16 bitsの値をfloatに変換し、speexライブラリが
  • で動作できるようにします.
  • for (i=0;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; 
  • }