zoukankan      html  css  js  c++  java
  • ilbc编解码

          针对国内的博客或者技术论坛对 ILBC的论述都是把文章抄来抄去, 本人在此对 ILBC的具体代码实现详细列出代码.

          ILBC是由Global IP Sound公司提出的一种专为包交换网络通信设计的编解码,优于目前流行的G.729A、G.723.1,对丢包进行了特殊处理,既使在丢包率相当高的网络环境下,仍可获得非常清晰的语音效果。
        ILBC 对于20 ms的帧,共使用了304个比特来表示编码后的语音信号,被封装在38个字节中;对于30ms的帧,共使用了480个比特,封装在50个字节中。

    1.  ILBC的编译

         ILBC代码部分是网络上找的,    点此下载.

         dll和lib(使用的是20 ms的帧)  点此下载.

    2. 与PCM结合编解码.

        ILBC对WaveFormat的值有要求, 即下列代码的@FFormat, 取其他值时会有问题.

        PCMFormat: TWaveFormatEx = (
        wFormatTag: WAVE_FORMAT_PCM;
        nChannels: 1;
        nSamplesPerSec: 8000; 
        nAvgBytesPerSec: 16000;
        nBlockAlign: 2;
        wBitsperSample: 16; 
        cbSize: 0 );  

       由于使用的是20 ms的帧, 1秒应该是回调50次, 每次的语音数据为320字节.

       即FRecBufferSize的值取50

      

    FDataSize:= FFormat.nAvgBytesPerSec div DWORD(RecBufferSize);
          GetMem(FWaveID,sizeof(HWaveIn));
          i := WaveInOpen(FWaveID, WAVE_MAPPER, @FFormat, DWORD(@waveInCallback),
                     DWORD(Self), CALLBACK_FUNCTION);
          if i=MMSYSERR_NOERROR then
          else begin
            FActive := False;
            Exit;
          end;
          for I:= 1 to FRecBufferSize do
            AddPrepareBuffer;
          WaveInStart(FWaveID^);
          FActive:= True;

    以下函数为PCM数据回调后编码

    procedure TTalkClass.DoRecordData(Data: Pointer; size: Integer);
    var
      pEncodeBuf: array[0..37] of Byte;
      eSize: Integer;
    begin
      //先进行编码 压缩
      eSize := ilbc_encoder(Data, @pEncodeBuf);
      if Assigned(FOnTalkData) then
        FOnTalkData(@pEncodeBuf, eSize); //已经编码的数据  320->38 压缩后的
    end;

    然后进行ilbc解码和播放

    function TTalkClass.PlayData(pData: PByte; size: Integer): Boolean;
    var
      pDecodeBuf: array [0..160-1] of SHORT;
      eSize: Integer;
    begin
      //传入的是编码后的数据  先解码
      eSize := ilbc_decoder(pData, @pDecodeBuf);
      FWaveOut.WriteData(@pDecodeBuf, eSize*2);
    end;

    这个地方必须要注意eSize*2, 由于ilbc_decoder这个函数解码后的数据为short型数组, 返回值eSize表示的是数组长度.
    这个地方不注意的话, 就很有问题了.

    再贴一下delphi中引用这个dll的代码

    const
      Dll = 'ilbc.dll';
    
      function ilbc_init(): Boolean; stdcall; external Dll name '_ilbc_init@0';
      function ilbc_encoder(pin: Pointer; pout: PByte): Integer; stdcall; external Dll name '_ilbc_encoder@8';
      function ilbc_decoder(pin: PByte; pout: Pointer): Integer; stdcall; external Dll name '_ilbc_decoder@8';


    需要编码后的ilbc语音数据的点此下载.  用文件流读取时记得每次取38字节进行解码.

    最后声明下我说的只是个人这几天的心得, 有什么说的不对的请指正.

      

  • 相关阅读:
    Spring MVC 文件上传简单示例(form、ajax方式 )
    Spring MVC Theme(简单示例)
    查看Spring MVC 父容器和子容器的对象的实例
    Spring mvc i18n国际化的简单demo
    idea中使用JRebel插件
    简单使用logback日志框架
    EC20指令
    keil中的一些技巧
    XModem与YModem
    codeblocks与MINGW的配置
  • 原文地址:https://www.cnblogs.com/doorsky/p/3266102.html
Copyright © 2011-2022 走看看