ilbc编解码

时间:2023-03-09 07:30:48
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:= to FRecBufferSize do
AddPrepareBuffer;
WaveInStart(FWaveID^);
FActive:= True;

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

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

然后进行ilbc解码和播放

function TTalkClass.PlayData(pData: PByte; size: Integer): Boolean;
var
pDecodeBuf: array [..-] of SHORT;
eSize: Integer;
begin
//传入的是编码后的数据 先解码
eSize := ilbc_decoder(pData, @pDecodeBuf);
FWaveOut.WriteData(@pDecodeBuf, eSize*);
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字节进行解码.

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