热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

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

//该类可以实现,任何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


推荐阅读
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 本文介绍了PHP常量的定义和使用方法,包括常量的命名规则、大小写敏感性、全局范围和标量数据的限制。同时还提到了应尽量避免定义resource常量,并给出了使用define()函数定义常量的示例。 ... [详细]
  • 修复安装win10失败并提示“磁盘布局不受UEFI固件支持”的方法
    本文介绍了修复安装win10失败并提示“磁盘布局不受UEFI固件支持”的方法。首先解释了UEFI的概念和作用,然后提供了两种解决方法。第一种方法是在bios界面中将Boot Mode设置为Legacy Support,Boot Priority设置为Legacy First,并关闭UEFI。第二种方法是使用U盘启动盘进入PE系统,运行磁盘分区工具DiskGenius,将硬盘的分区表设置为gpt格式,并留出288MB的内存。最后,通过运行界面输入命令cmd来完成设置。 ... [详细]
  • 本文介绍了Composer依赖管理的重要性及使用方法。对于现代语言而言,包管理器是标配,而Composer作为PHP的包管理器,解决了PEAR的问题,并且使用简单,方便提交自己的包。文章还提到了使用Composer能够避免各种include的问题,避免命名空间冲突,并且能够方便地安装升级扩展包。 ... [详细]
  • 本文主要复习了数据库的一些知识点,包括环境变量设置、表之间的引用关系等。同时介绍了一些常用的数据库命令及其使用方法,如创建数据库、查看已存在的数据库、切换数据库、创建表等操作。通过本文的学习,可以加深对数据库的理解和应用能力。 ... [详细]
  • 本文介绍了在Windows系统下安装Python、setuptools、pip和virtualenv的步骤,以及安装过程中需要注意的事项。详细介绍了Python2.7.4和Python3.3.2的安装路径,以及如何使用easy_install安装setuptools。同时提醒用户在安装完setuptools后,需要继续安装pip,并注意不要将Python的目录添加到系统的环境变量中。最后,还介绍了通过下载ez_setup.py来安装setuptools的方法。 ... [详细]
author-avatar
鄧淇-琪___106
这个家伙很懒,什么也没留下!
Tags | 热门标签
RankList | 热门文章
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有