原址:http://blog.csdn.net/linweifeng/article/details/1768070
//该类可以实现,任何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:[email protected]