从pcm,u,A率到g729A转化的实现,delphi代码

来源:互联网 发布:智能物流软件 编辑:程序博客网 时间:2024/05/24 02:49

//该类可以实现,任何wav的转化,可以从pcm->adpcm,adpcm->mp3,gsm->mp3,mp3->a率,u率 ,a 率 u率->g729A

TWaveBufConverter = class
  private
    fphad: HACMDRIVER;
    fhadid: HACMDRIVERID;

    FMaxFmtSize: DWord;
    CurrentFormat: TACMWaveFormat;
    NewFormat: TACMWaveFormat;
    //转化
    fStreamHeaderM: TACMStreamHeader;
    fStreamHeader: TACMStreamHeader;
    fStreamHandle: HACMStream;
    FStreamHandleM: HACMStream;
    srcDataBuf: PChar;
    mDataBuf: PChar;
    DscDataBuf: PChar;
    srcBufferSize: DWORD;
    mBufferSize: DWORD;
    DscBufferSize: DWORD;
    //获得指定的一个格式
    function FormatSuggest(pFDInfo: pFIND_DRIVER_INFO): Boolean;
  public
    constructor Create(SrcConverFormat, ConverFormat: Integer);
    destructor Destroy; override;
    //开始转化
    function StartConvert(ConvertSize: Integer): Boolean;
    //结束转化
    function EndConvert: Boolean;
    //开始转化
    function RunConvvert(srcBuf: PChar; srcBufSize: Integer; out DrcBuf: PChar; out DrcBufSize: Integer): Boolean;

  end;
implementation
uses
  DataDefine, g729A;
 
function FormatCallback(hadid:HACMDRIVERID; pafd: PAcmFormatDetailsA;
    dwInstance: DWORD; fdwSupport: DWORD): BOOL; stdcall;
begin
  Result := True;

  if dwInstance = 1 then
  begin
    if (pafd^.pwfx^.nChannels = 1) and
       (pafd^.pwfx^.nSamplesPerSec = 8000) and
       (pafd^.pwfx^.wBitsPerSample = 8) then
    begin
      Result := False;
    end;
  end
  else if dwInstance = 6 then
  begin
    if (pafd^.pwfx^.nChannels = 1) and
       (pafd^.pwfx^.nSamplesPerSec = 8000) and
       (pafd^.pwfx^.nAvgBytesPerSec = 8000) then
    begin
      Result := False;
    end;
  end
  else if dwInstance = 7 then
  begin
    if (pafd^.pwfx^.wFormatTag = 7) and
       (pafd^.pwfx^.nChannels = 1) and
       (pafd^.pwfx^.nSamplesPerSec = 8000) and
       (pafd^.pwfx^.nAvgBytesPerSec = 8000) then
    begin
      Result := False;
    end;
  end
  else if dwInstance = 17 then
  begin
    if (pafd^.pwfx^.wFormatTag = 17) and
       (pafd^.pwfx^.nChannels = 1) and
       (pafd^.pwfx^.nSamplesPerSec = 8000) then
    begin
      Result := False;
    end;
  end
  else if dwInstance = 49 then
  begin
    if (pafd^.pwfx^.wFormatTag = 49) and
       (pafd^.pwfx^.nChannels = 1) and
       (pafd^.pwfx^.nSamplesPerSec = 8000) then
    begin
      Result := False;
    end;
  end
  else if dwInstance = 85 then
  begin
    if (pafd^.pwfx^.nChannels = 1) and
       (pafd^.pwfx^.nSamplesPerSec = 8000) and
       (pafd^.pwfx^.nAvgBytesPerSec = 1000) then
    begin
      Result := False;
    end;
  end
  else if dwInstance = 131 then
  begin
    if (pafd^.pwfx^.wFormatTag = 131) and
       (pafd^.pwfx^.nChannels = 1) then
    begin
      Result := False;
    end;
  end;
end;

function DriverCallback(hadif: HACMDRIVERID; dwInstance, fdwSupport: DWORD): BOOL; stdcall;
var
  padd: TAcmDriverDetails;
  pFIND_DRIVER_INFOTmp: pFIND_DRIVER_INFO;
  phad: HACMDRIVER;
  AcmFormatDetailsTmp: TAcmFormatDetails;
  Res: MMRESULT;
  intSize: Integer;
  TWAVEFORMATEXTmp: TWAVEFORMATEX;
begin
  Result := TRUE;
  pFIND_DRIVER_INFOTmp := pFIND_DRIVER_INFO(dwInstance);
  padd.cbStruct := SizeOf(TAcmDriverDetails);
  acmDriverDetails(hadif, padd, 0);

  if ((LowerCase(padd.szShortName) = LowerCase('Lame mp3')) and (pFIND_DRIVER_INFOTmp^.wfx.wFormatTag = 85)) or
     ((LowerCase(padd.szShortName) = LowerCase('Microsoft IMA ADPCM')) and (pFIND_DRIVER_INFOTmp^.wfx.wFormatTag = 17)) or
     ((LowerCase(padd.szShortName) = LowerCase('Microsoft GSM 6.10')) and (pFIND_DRIVER_INFOTmp^.wfx.wFormatTag = 49)) or
     ((LowerCase(padd.szShortName) = LowerCase('Microsoft CCITT G.711')) and (pFIND_DRIVER_INFOTmp^.wfx.wFormatTag = 7)) or
     ((LowerCase(padd.szShortName) = LowerCase('MS-PCM')) and (pFIND_DRIVER_INFOTmp^.wfx.wFormatTag = 1)) or
     ((LowerCase(padd.szShortName) = LowerCase('SynWay G.729A ')) and (pFIND_DRIVER_INFOTmp^.wfx.wFormatTag = 131)) then
  begin
    Res := acmDriverOpen(phad, hadif, 0);
    if Res <> 0 then
    begin
      exit;
    end;
    acmMetrics(HACMOBJ(phad), ACM_METRIC_MAX_SIZE_FORMAT, intSize);
    Fillchar(TWAVEFORMATEXTmp, Sizeof(TWAVEFORMATEX), 0);
    TWAVEFORMATEXTmp.cbSize := 0;
    TWAVEFORMATEXTmp.wFormatTag := 0;

    Fillchar(AcmFormatDetailsTmp, Sizeof(TAcmFormatDetails), 0);
    AcmFormatDetailsTmp.cbStruct := SizeOf(TAcmFormatDetails);
    AcmFormatDetailsTmp.dwFormatTag := 0;
    AcmFormatDetailsTmp.pwfx := @TWAVEFORMATEXTmp;
    AcmFormatDetailsTmp.cbwfx := intSize;
    Res := acmFormatEnum(phad, AcmFormatDetailsTmp, FormatCallback, Integer(pFIND_DRIVER_INFOTmp^.wfx.wFormatTag), 0);
    if Res = 0 then
    begin
      pFIND_DRIVER_INFOTmp^.hadid := hadif;
      Move(AcmFormatDetailsTmp.pwfx^, pFIND_DRIVER_INFOTmp^.wfx, SizeOf(TWAVEFORMATEX));
      Result := False;
    end;
    acmDriverClose(phad, 0);
  end;
end;

{ TWaveBufConverter }

constructor TWaveBufConverter.Create(SrcConverFormat, ConverFormat: Integer);
var
  WaveFormatTmp: TWAVEFORMATEX;
  FIND_DRIVER_INFOTmp: TFIND_DRIVER_INFO;
  intLength: Integer;
begin
  acmMetrics(nil, ACM_METRIC_MAX_SIZE_FORMAT, FMaxFmtSize);

  FillChar(NewFormat.Format, FMaxFmtSize, 0);
  FillChar(CurrentFormat.Format, FMaxFmtSize, 0);

  case SrcConverFormat of
    RecordMode_M:              //= 7;   //m-率
    begin
      with WaveFormatTmp do
      begin
        wFormatTag := 7;         { format type }
        nChannels := 1;          { number of channels (i.e. mono, stereo, etc.) }
        nSamplesPerSec := 8000;  { sample rate }
        nAvgBytesPerSec := 8000; { for buffer estimation }
        nBlockAlign := 1;        { block size of data }
        wBitsPerSample := 8;     { number of bits per sample of mono data }
        cbSize := 0;             { the count in bytes of the size of }
      end;
      Move(WaveFormatTmp, CurrentFormat.Format, SizeOf(TWAVEFORMATEX));
    end;
    RecordMode_ADPCM:
    begin
      with WaveFormatTmp do
      begin
        wFormatTag := 17;        { format type }
        nChannels := 1;          { number of channels (i.e. mono, stereo, etc.) }
        nSamplesPerSec := 8000;  { sample rate }
        nAvgBytesPerSec := 4055; { for buffer estimation }
        nBlockAlign := 256;      { block size of data }
        wBitsPerSample := 4;     { number of bits per sample of mono data }
        cbSize := 2;             { the count in bytes of the size of }
      end;
      Move(WaveFormatTmp, CurrentFormat.Format, SizeOf(TWAVEFORMATEX));
      intLength := $1F9;
      Move(intLength, PChar(PChar(@CurrentFormat.Format) + SizeOf(TWAVEFORMATEX))^, 2);
    end;
    RecordMode_GSM:
    begin
      with WaveFormatTmp do
      begin
        wFormatTag := 49;         { format type }
        nChannels := 1;          { number of channels (i.e. mono, stereo, etc.) }
        nSamplesPerSec := 8000;  { sample rate }
        nAvgBytesPerSec := 1625; { for buffer estimation }
        nBlockAlign := 65;        { block size of data }
        wBitsPerSample := 0;     { number of bits per sample of mono data }
        cbSize := 2;             { the count in bytes of the size of }
      end;
      Move(WaveFormatTmp, CurrentFormat.Format, SizeOf(TWAVEFORMATEX));
      intLength := $140;
      Move(intLength, PChar(PChar(@CurrentFormat.Format) + SizeOf(TWAVEFORMATEX))^, 2);
    end;
    RecordMode_MP3:
    begin
      with WaveFormatTmp do
      begin
        wFormatTag := 85;         { format type }
        nChannels := 1;          { number of channels (i.e. mono, stereo, etc.) }
        nSamplesPerSec := 8000;  { sample rate }
        nAvgBytesPerSec := 1000; { for buffer estimation }
        nBlockAlign := 1;        { block size of data }
        wBitsPerSample := 0;     { number of bits per sample of mono data }
        cbSize := 12;             { the count in bytes of the size of }
      end;
      Move(WaveFormatTmp, CurrentFormat.Format, SizeOf(TWAVEFORMATEX));
      Move(Wave_Mp3CbSize, PChar(PChar(@CurrentFormat.Format) + SizeOf(TWaveFormatEx))^, 12);
    end;
  end;

  FIND_DRIVER_INFOTmp.wfx.wFormatTag := ConverFormat;
  if FormatSuggest(@FIND_DRIVER_INFOTmp) then
  begin
    Move(FIND_DRIVER_INFOTmp.wfx, NewFormat.Format, SizeOf(TWaveFormatEx));
    if ConverFormat = RecordMode_MP3 then
    begin
      //Move(Wave_Mp3CbSize, PChar(PChar(@NewFormat.Format) + SizeOf(TWaveFormatEx))^, 12);
    end
    else if ConverFormat = RecordMode_ADPCM then
    begin
      intLength := $1F9;
      Move(intLength, PChar(PChar(@NewFormat.Format) + SizeOf(TWAVEFORMATEX))^, 2);
    end
    else if ConverFormat = RecordMode_GSM then
    begin
      intLength := $140;
      Move(intLength, PChar(PChar(@NewFormat.Format) + SizeOf(TWAVEFORMATEX))^, 2);
    end
    else if ConverFormat = RecordMode_G729A then
    begin
      initCoder;
    end;
  end;
end;

destructor TWaveBufConverter.Destroy;
begin
  inherited;

end;

function TWaveBufConverter.EndConvert: Boolean;
begin
  try
    Result := False;
    //
    // Unprepeare the header
    //
    acmStreamUnprepareHeader(FStreamhandleM, fStreamHeaderM, 0);
    //
    // Unprepeare the header
    //
    if NewFormat.Format.wFormatTag = 131 then //如果是转化为g729A方式,需要g729.dll进行转化
    begin
      //...
    end
    else                                      //如果不是转化为g729A方式,用acm进行转化
    begin
      acmStreamUnprepareHeader(FStreamhandle, FStreamHeader, 0);
    end;
    //
    // Close the stream
    //
    if srcDataBuf <> nil then
      FreeMem(srcDataBuf);
    if mDataBuf <> nil then
      FreeMem(mDataBuf);
    if NewFormat.Format.wFormatTag = 131 then //如果是转化为g729A方式,需要g729.dll进行转化
    begin
      //...
    end
    else                                      //如果不是转化为g729A方式,用acm进行转化
    begin
      if DscDataBuf <> nil then
        FreeMem(DscDataBuf);
    end;

    acmStreamClose(FStreamHandleM, 0);
    if NewFormat.Format.wFormatTag = 131 then //如果是转化为g729A方式,需要g729.dll进行转化
    begin
      //...
    end
    else                                      //如果不是转化为g729A方式,用acm进行转化
    begin
      acmStreamClose(FStreamHandle, 0);
    end;
   
    Result := True;
  except
  end;
end;

function TWaveBufConverter.FormatSuggest(
  pFDInfo: pFIND_DRIVER_INFO): Boolean;
var
  Res: MMRESULT;
begin
  Result := False;
  Res := acmDriverEnum(DriverCallback, Integer(pFDInfo), 0);
  if Res <> 0 then
  begin
    exit;
  end;
  fhadid := pFDInfo^.hadid;
  acmDriverOpen(fphad, fhadid, 0);
  Result := True;
end;

function TWaveBufConverter.RunConvvert(srcBuf: PChar; srcBufSize: Integer;
  out DrcBuf: PChar; out DrcBufSize: Integer): Boolean;
var
  intResult, intOut: Integer;
  inData: array of Shortint;
  outData: array of Shortint;
begin
  Result := False;
  try
    FillChar(srcDataBuf^, srcBufferSize, #0);
    //FillChar(mDataBuf^, mBufferSize, #0);
    //FillChar(DscDataBuf^, DscBufferSize, #0);
    Move(srcBuf^, srcDataBuf^, srcBufSize);

    //fStreamHeaderM.cbSrcLength := srcBufSize;
    intResult := acmStreamConvert(FStreamhandleM, fStreamHeaderM, ACM_STREAMCONVERTF_BLOCKALIGN);
    if intResult <> 0 then
      exit;
    if NewFormat.Format.wFormatTag = 131 then //如果是转化为g729A方式,需要g729.dll进行转化
    begin
      SetLength(inData, SIZE_AUDIO_FRAME);

      Move(fStreamHeaderM.pbDst^, PChar(@inData[0])^, fStreamHeaderM.cbDstLengthUsed);
      SetLength(outdata, SIZE_AUDIO_PACKED);
      if EncodeAudioData(indata, fStreamHeaderM.cbDstLengthUsed, outdata, intOut) then
      begin
        GetMem(DrcBuf, intOut);
        Move(PChar(@outdata[0])^, DrcBuf^, intOut);
        DrcBufSize := intOut;
      end;
    end
    else                                      //如果不是转化为g729A方式,用acm进行转化
    begin
      //FStreamHeader.cbSrcLength := fStreamHeaderM.cbDstLengthUsed;
      intResult := acmStreamConvert(FStreamhandle, FStreamHeader, ACM_STREAMCONVERTF_BLOCKALIGN);
      if intResult <> 0 then
        exit;
      GetMem(DrcBuf, FStreamHeader.cbDstLengthUsed);
      Move(DscDataBuf^, DrcBuf^, FStreamHeader.cbDstLengthUsed);
      DrcBufSize := FStreamHeader.cbDstLengthUsed;
    end;
    Result := True;
  except
  end;
end;

function TWaveBufConverter.StartConvert(ConvertSize: Integer): Boolean;
var
  WaveFormatExM: TWaveFormatEx;
  ValidItems: LongWord;
  intResult: MMRESULT;
begin
  try
    Result := False;

    FStreamHandle := nil;
    FStreamhandleM := nil;
    //
    // Open the stream we're going to use to convert from the current to the
    // new format
    //
    FillChar(WaveFormatExM, SizeOf(TWaveFormatEx), #0);
    WaveFormatExM.wFormatTag := WAVE_FORMAT_PCM;
    ValidItems := ACM_FORMATSUGGESTF_WFORMATTAG;
    intResult := acmFormatSuggest(nil, CurrentFormat.format,
                                  WaveFormatExM, SizeOf(TACMWaveFormat), ValidItems);
    if intResult <> 0 then
      exit;

    intResult := acmStreamOpen(FStreamhandleM, nil, CurrentFormat.Format,
                               WaveFormatExM, nil, 0, 0, ACM_STREAMOPENF_NONREALTIME);
    if intResult <> 0 then
      Exit;

    if NewFormat.Format.wFormatTag = 131 then //如果是转化为g729A方式,需要g729.dll进行转化
    begin
      //...
    end
    else
    begin                                     //如果不是转化为g729A方式,用acm进行转化
      intResult := acmStreamOpen(FStreamhandle, fphad, WaveFormatExM,
                                 NewFormat.Format, nil, 0, 0, ACM_STREAMOPENF_NONREALTIME);
    end;

    if intResult <> 0 then
      Exit;

    //中间格式转化
    //
    // Calculate the size of the converted data
    //
    srcBufferSize := ConvertSize;
    intResult := acmStreamSize(FStreamhandleM, srcBufferSize, mBufferSize,
                               ACM_STREAMSIZEF_SOURCE);
    if intResult <> 0 then
      Exit;
    //
    // Allocate memory for the converted data
    //
    GetMem(srcDataBuf, srcBufferSize);
    FillChar(srcDataBuf^, srcBufferSize, #0);
    GetMem(mDataBuf, mBufferSize);
    FillChar(mDataBuf^, mBufferSize, #0);
   
    //
    // Initialize and prepare a header
    //
    with fStreamHeaderM do
    begin
      cbStruct := SizeOf(TACMStreamHeader);
      fdwStatus := 0;
      dwUser := 0;
      pbSrc := PBYTE(srcDataBuf);
      cbSrcLength := srcBufferSize;
      cbSrcLengthUsed := 0;
      dwSrcUser := 0;
      pbDst := PBYTE(mDataBuf);
      cbDstLength := mBufferSize;
      cbDstLengthUsed := 0;
      dwDstUser := 0;
    end;
    intResult := acmStreamPrepareHeader(FStreamhandleM, fStreamHeaderM, 0);
    if intResult <> 0 then
    begin
      //    SetError('acmStreamPrepareHeader', Result);
      FreeMem(srcDataBuf);
      FreeMem(mDataBuf);
      Exit;
    end;
   
    if NewFormat.Format.wFormatTag = 131 then //如果是转化为g729A方式,需要g729.dll进行转化
    begin
      //...
    end
    else
    begin   //如果不是转化为g729A方式,用acm进行转化
      //最终格式转化
      intResult := acmStreamSize(FStreamHandle, mBufferSize, DscBufferSize, ACM_STREAMSIZEF_SOURCE);
      if intResult <> 0 then
      begin
        FreeMem(srcDataBuf);
        FreeMem(mDataBuf);
        Exit;
      end;

      GetMem(DscDataBuf, DscBufferSize);
      FillChar(DscDataBuf^, DscBufferSize, #0);

      //
      // Initialize and prepare a header
      //
      with FStreamHeader do
      begin
        cbStruct := SizeOf(TACMStreamHeader);
        fdwStatus := 0;
        dwUser := 0;
        pbSrc := PBYTE(mDataBuf);
        cbSrcLength := mBufferSize;
        cbSrcLengthUsed := 0;
        dwSrcUser := 0;
        pbDst := PBYTE(DscDataBuf);
        cbDstLength := DscBufferSize;
        cbDstLengthUsed := 0;
        dwDstUser := 0;
      end;
      intResult := acmStreamPrepareHeader(FStreamhandle, FStreamHeader, 0);
      if intResult <> 0 then
      begin
        FreeMem(srcDataBuf);
        FreeMem(mDataBuf);
        FreeMem(DscDataBuf);
        Exit;
      end;
    end;
  except
  end;
end; 

实现a率u率->g729A的转化:

常量

  WaveLength      = 58;              //wave头长度
  WaveLengthMp3   = 70;              //mp3 wave头长度
  WareLengthG729  = 56;              //G729 wave 头长度

转化函数

procedure RunConv;
var
  buf: array [0..WaveLengthMp3 - 1] of Char;
  fHandle, fHandleRes, fHandleCopy, fWaveLength, intReadSize, intRead, intSize, intLength,
  fDataLength, fDataLengthRes, intOutLength, intWareLengthRes: Integer;
  hmmioIn: HMMIO;
  indata: array of shortint;
  outdata: array of shortint;
  Getbuf, outBuf: PChar;

  fWaveBufConverter: TWaveBufConverter;
begin

 fWaveBufConverter := TWaveBufConverter.Create(RecordMode_M, RecordMode_G729A);
  fHandle := FileCreate('g729.wav');

  fWaveLength := GetWaveHead(RecordMode_G729A, @buf[0], WareLengthG729);
  FileWrite(fHandle, buf, fWaveLength);

  hmmioIn := mmioOpen('u.wav', nil, MMIO_READ);//u.wav是u率的语音文件
  intSize := mmioSeek(hmmioIn, 0, SEEK_END);
  intReadSize := (960 div 2) * 10;  //先要把u率转化从中间格式pcm(nAvgBytesPerSec=16000)是u率的2倍,中间的格式buf大小最小要960
  fWaveBufConverter.StartConvert(intReadSize);

  intSize := intSize - 58;
  mmioSeek(hmmioIn, 58, SEEK_SET);

  fDataLength := 0;
  fDataLengthRes := 0;
  while intSize > 0 do
  begin
    intRead := intSize;
    if intSize > intReadSize then
      intRead := intReadSize;

    GetMem(Getbuf, intRead);
    intRead := mmioRead(hmmioIn, Getbuf, intRead);
    if intRead > 0 then
    begin

      intLength := intRead;
      WriteLog(IntToStr(fNo) + '.txt', 'StartTime');
      if fWaveBufConverter.RunConvvert(Getbuf, intLength, outBuf, intOutLength) then
      begin
        sleep(100);
        WriteLog(IntToStr(fNo) + '.txt', 'EndTime');
        intLength := intOutLength;
        FileSeek(fHandle, 0, 2);
        FileWrite(fHandle, outBuf^, intLength);

        fDataLength := fDataLength + intLength;
        FileSeek(fHandle, 4, 0);
        intLength := fDataLength + fWaveLength - 8;
        FileWrite(fHandle, intLength, 4);
        FileSeek(fHandle, fWaveLength - 12, 0);
        FileWrite(fHandle, fDataLength, 4);
        FileSeek(fHandle, fWaveLength - 4, 0);
        FileWrite(fHandle, fDataLength, 4);

        if outBuf <> nil then
          FreeMem(outBuf);
      end;
      FreeMem(Getbuf);

      intSize := intSize - intRead;
    end;
  end;
  mmioClose(hmmioIn, 0);
  FileClose(fHandle);
end;

//取得wav文件的头数据

function GetWaveHead(fType: Integer; Headbuf: PChar;
  bufSize: Integer): Integer;
var
  buf: array [0..WaveLengthMp3 - 1] of char;
  intLength, intWaveLength: Integer;
  WaveFormatTmp: TWAVEFORMATEX;
begin
  Result := 0;
  if bufSize + 2 >= WaveLength then
  begin
    case fType of
      RecordMode_PCM8:              //PCM8无符号
      begin
        intWaveLength := WaveLength;
        //Move('RIFF', buf, 4);
        Move('RIFF', buf, 4);
        intLength := intWaveLength - 8;
        Move(intLength, buf[4], 4);
        Move('WAVE', buf[4 + 4], 4);
        Move('fmt ', buf[4 + 4 + 4], 4);
        intLength := 18;
        Move(intLength, buf[4 + 4 + 4 + 4], 4);
        with WaveFormatTmp do
        begin
          wFormatTag := 1;         { format type }
          nChannels := 1;          { number of channels (i.e. mono, stereo, etc.) }
          nSamplesPerSec := 22050;  { sample rate }
          nAvgBytesPerSec := 22050; { for buffer estimation }
          nBlockAlign := 1;        { block size of data }
          wBitsPerSample := 8;     { number of bits per sample of mono data }
          cbSize := 0;             { the count in bytes of the size of }
        end;
        Move(WaveFormatTmp, buf[4 + 4 + 4 + 4], SizeOf(TWAVEFORMATEX));
        Move('fact4444', buf[4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX)], 4);
        intLength := 0;
        Move(intLength, buf[4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 4], 4);
        Move('data', buf[4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 4 + 4], 4);
        intLength := 0;
        Move(intLength, buf[4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 4 + 4], 4);
      end;
      RecordMode_A:                //A-率
      begin
        intWaveLength := WaveLength;
        //Move('RIFF', buf, 4);
        Move('RIFF', buf, 4);
        intLength := intWaveLength - 8;
        Move(intLength, buf[4], 4);
        Move('WAVE', buf[4 + 4], 4);
        Move('fmt ', buf[4 + 4 + 4], 4);
        intLength := 18;
        Move(intLength, buf[4 + 4 + 4 + 4], 4);
        with WaveFormatTmp do
        begin
          wFormatTag := 6;         { format type }
          nChannels := 1;          { number of channels (i.e. mono, stereo, etc.) }
          nSamplesPerSec := 8000;  { sample rate }
          nAvgBytesPerSec := 8000; { for buffer estimation }
          nBlockAlign := 1;        { block size of data }
          wBitsPerSample := 8;     { number of bits per sample of mono data }
          cbSize := 0;             { the count in bytes of the size of }
        end;
        Move(WaveFormatTmp, buf[4 + 4 + 4 + 4], SizeOf(TWAVEFORMATEX));
        Move('fact4444', buf[4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX)], 4);
        intLength := 0;
        Move(intLength, buf[4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 4], 4);
        Move('data', buf[4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 4 + 4], 4);
        intLength := 0;
        Move(intLength, buf[4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 4 + 4], 4);
      end;
      RecordMode_M, RecordMode_MP3Soft:                //m-率
      begin
        intWaveLength := WaveLength;
        //Move('RIFF', buf, 4);
        Move('RIFF', buf, 4);
        intLength := intWaveLength - 8;
        Move(intLength, buf[4], 4);
        Move('WAVE', buf[4 + 4], 4);
        Move('fmt ', buf[4 + 4 + 4], 4);
        intLength := 18;
        Move(intLength, buf[4 + 4 + 4 + 4], 4);
        with WaveFormatTmp do
        begin
          wFormatTag := 7;         { format type }
          nChannels := 1;          { number of channels (i.e. mono, stereo, etc.) }
          nSamplesPerSec := 8000;  { sample rate }
          nAvgBytesPerSec := 8000; { for buffer estimation }
          nBlockAlign := 1;        { block size of data }
          wBitsPerSample := 8;     { number of bits per sample of mono data }
          cbSize := 0;             { the count in bytes of the size of }
        end;
        Move(WaveFormatTmp, buf[4 + 4 + 4 + 4 + 4], SizeOf(TWAVEFORMATEX));
        Move('fact', buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX)], 4);
        intLength := 4;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 4], 4);
        intLength := 0;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 4 + 4], 4);
        Move('data', buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 4 + 4 + 4], 4);
        intLength := 0;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 4 + 4 + 4 + 4], 4);
      end;
      RecordMode_ADPCM:            //IMA ADPCM
      begin
        intWaveLength := WaveLength + 2;
        //Move('RIFF', buf, 4);
        Move('RIFF', buf, 4);
        intLength := intWaveLength - 8;
        Move(intLength, buf[4], 4);
        Move('WAVE', buf[4 + 4], 4);
        Move('fmt ', buf[4 + 4 + 4], 4);
        intLength := 20;
        Move(intLength, buf[4 + 4 + 4 + 4], 4);
        with WaveFormatTmp do
        begin
          wFormatTag := 17;         { format type }
          nChannels := 1;          { number of channels (i.e. mono, stereo, etc.) }
          nSamplesPerSec := 8000;  { sample rate }
          nAvgBytesPerSec := 4055; { for buffer estimation }
          nBlockAlign := 256;        { block size of data }
          wBitsPerSample := 4;     { number of bits per sample of mono data }
          cbSize := 2;             { the count in bytes of the size of }
        end;
        Move(WaveFormatTmp, buf[4 + 4 + 4 + 4 + 4], SizeOf(TWAVEFORMATEX));
        intLength := $1F9;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX)], 2);
        Move('fact', buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 2], 4);
        intLength := 4;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 2 + 4], 4);
        intLength := 0;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 2 + 4 + 4], 4);
        Move('data', buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 2 + 4 + 4 + 4], 4);
        intLength := 0;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 2 + 4 + 4 + 4 + 4], 4);
      end;
      RecordMode_GSM:              //GSM
      begin
        intWaveLength := WaveLength + 2;
        //Move('RIFF', buf, 4);
        Move('RIFF', buf, 4);
        intLength := intWaveLength - 8;
        Move(intLength, buf[4], 4);
        Move('WAVE', buf[4 + 4], 4);
        Move('fmt ', buf[4 + 4 + 4], 4);
        intLength := 20;
        Move(intLength, buf[4 + 4 + 4 + 4], 4);
        with WaveFormatTmp do
        begin
          wFormatTag := 49;         { format type }
          nChannels := 1;          { number of channels (i.e. mono, stereo, etc.) }
          nSamplesPerSec := 8000;  { sample rate }
          nAvgBytesPerSec := 1625; { for buffer estimation }
          nBlockAlign := 65;        { block size of data }
          wBitsPerSample := 0;     { number of bits per sample of mono data }
          cbSize := 2;             { the count in bytes of the size of }
        end;
        Move(WaveFormatTmp, buf[4 + 4 + 4 + 4 + 4], SizeOf(TWAVEFORMATEX));
        intLength := $140;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX)], 2);
        Move('fact', buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 2], 4);
        intLength := 4;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 2 + 4], 4);
        intLength := 0;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 2 + 4 + 4], 4);
        Move('data', buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 2 + 4 + 4 + 4], 4);
        intLength := 0;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 2 + 4 + 4 + 4 + 4], 4);
      end;
      RecordMode_MP3:              //MP3
      begin
        intWaveLength := WaveLengthMp3;
        Move('RIFF', buf, 4);
        intLength := intWaveLength - 8;
        Move(intLength, buf[4], 4);
        Move('WAVE', buf[4 + 4], 4);
        Move('fmt ', buf[4 + 4 + 4], 4);
        intLength := 30;
        Move(intLength, buf[4 + 4 + 4 + 4], 4);
        with WaveFormatTmp do
        begin
          wFormatTag := 85;         { format type }
          nChannels := 1;          { number of channels (i.e. mono, stereo, etc.) }
          nSamplesPerSec := 8000;  { sample rate }
          nAvgBytesPerSec := 1000; { for buffer estimation }
          nBlockAlign := 1;        { block size of data }
          wBitsPerSample := 0;     { number of bits per sample of mono data }
          cbSize := 12;             { the count in bytes of the size of }
        end;
        Move(WaveFormatTmp, buf[4 + 4 + 4 + 4 + 4], SizeOf(TWAVEFORMATEX));
        Move(Wave_Mp3CbSize, buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX)], 12);
        Move('fact', buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 12], 4);
        intLength := 4;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 12 + 4], 4);
        intLength := 0;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 12 + 4 + 4], 4);
        Move('data', buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 12 + 4 + 4 + 4], 4);
        intLength := 0;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + SizeOf(TWAVEFORMATEX) + 12 + 4 + 4 + 4 + 4], 4);

      end;
      RecordMode_PCM16:            //PCM16
      begin

      end;
      RecordMode_G729A:           //G729A
      begin
        intWaveLength := WareLengthG729;
        Move('RIFF', buf, 4);
        intLength := intWaveLength - 8;
        Move(intLength, buf[4], 4);
        Move('WAVE', buf[4 + 4], 4);
        Move('fmt ', buf[4 + 4 + 4], 4);
        intLength := 16;
        Move(intLength, buf[4 + 4 + 4 + 4], 4);
        with WaveFormatTmp do
        begin
          wFormatTag := 131;         { format type }
          nChannels := 1;          { number of channels (i.e. mono, stereo, etc.) }
          nSamplesPerSec := 8000;  { sample rate }
          nAvgBytesPerSec := 1000; { for buffer estimation }
          nBlockAlign := 10;        { block size of data }
          wBitsPerSample := 1;     { number of bits per sample of mono data }
          cbSize := 0;             { the count in bytes of the size of }
        end;
        Move(WaveFormatTmp, buf[4 + 4 + 4 + 4 + 4], 16);
        Move('fact', buf[4 + 4 + 4 + 4 + 4 + 16], 4);
        intLength := 4;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + 16 + 4], 4);
        intLength := 0;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + 16 + 4 + 4], 4);
        Move('data', buf[4 + 4 + 4 + 4 + 4 + 16 + 4 + 4 + 4], 4);
        intLength := 0;
        Move(intLength, buf[4 + 4 + 4 + 4 + 4 + 16 + 4 + 4 + 4 + 4], 4);
      end;
    end;
    Move(buf, Headbuf^, intWaveLength);
    Result := intWaveLength;
  end;
end;

g729A转化类,包括Dll在附件中.

unit g729A;

interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, syncobjs;

const
  L_FRAME_COMPRESSED = 10 ;
  L_FRAME            = 80 ;
  SIZE_AUDIO_FRAME   = 960 * 10;
  SIZE_AUDIO_PACKED  = 60 * 10;
  procedure g729a_init_encoder();stdcall external 'G729.dll';
  procedure g729a_encoder(speech: Psmallint; bitstream: PshortInt);stdcall external 'G729.dll';
  procedure g729a_init_decoder();stdcall external 'G729.dll';
  procedure g729a_decoder(bitstream: PshortInt; synth_short: Psmallint; bfi:integer);stdcall external 'G729.dll';

  procedure initCoder;
  function EncodeAudioData(indata: array of shortInt; inLen: integer;var outdata: array of shortInt; var outLen: Integer): boolean;
  function DecodeAudioData(indata: array of shortint; inlen: integer; var outdata: array of shortint; var outLen: Integer): boolean;

var
  g729sync: TCriticalSection;
implementation

procedure initCoder;
begin
  g729a_init_encoder;
  g729a_init_decoder;
  g729sync := TCriticalSection.Create;
end;

function EncodeAudioData(indata: array of shortInt; inLen: integer;var outdata: array of shortInt; var outLen: Integer):boolean;
var
  intA, intIndex: Integer;
  pin, pOut: PshortInt;
begin

  Result := False;
  if (inLen <> SIZE_AUDIO_FRAME) then
    exit;
  pin := PshortInt(@indata);
  pOut := pShortint(@outdata);

  intIndex := 1;
  for intA := 0 to 6 * 10 - 1 do
  begin
    g729a_encoder(Psmallint(pin),PshortInt(pout));
    inc(pin, 160);
    inc(pout, 10);
  end;
  outLen := SIZE_AUDIO_PACKED;
  Result := True;
end;

function DecodeAudioData(indata: array of shortint; inlen: integer; var outdata: array of shortint; var outLen: Integer): boolean;
var
  pin, pOut: PshortInt;
begin
  Result := False;
  if inlen <> SIZE_AUDIO_PACKED then
    exit;
  pIn := PshortInt(@indata) ;
  Pout := pshortInt(@outData) ;
  g729a_decoder(pshortInt(pin),psmallInt(pout),0);
  inc(pin, 10) ;
  inc(pout, 160);
  g729a_decoder(pshortInt(pin),psmallInt(pout),0);
  inc(pin, 10) ;
  inc(pout, 160);
  g729a_decoder(pshortInt(pin),psmallInt(pout),0);
  inc(pin, 10) ;
  inc(pout, 160);
  g729a_decoder(pshortInt(pin),psmallInt(pout),0);
  inc(pin, 10) ;
  inc(pout, 160);
  g729a_decoder(pshortInt(pin),psmallInt(pout),0);
  inc(pin, 10) ;
  inc(pout, 160);
  g729a_decoder(pshortInt(pin),psmallInt(pout),0);
  outLen := SIZE_AUDIO_FRAME;
  Result := True ;
end;

end.

有问题可以交流hotmail:llongst@hotmail.com