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字节进行解码.

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

  

原文地址:https://www.cnblogs.com/doorsky/p/3266102.html