一:MP3转换为WAV
function acmDriverEnumCallback(hadid: HACMDRIVERID; dwInstance: DWORD; fdwSupport: DWORD): BOOL; stdcall;
var
driver : HACMDRIVER;
details : TACMDRIVERDETAILS;
i : integer;
fmtDetails : TACMFORMATTAGDETAILS;
begin
if (fdwSupport and ACMDRIVERDETAILS_SUPPORTF_CODEC) <> 0 then
begin
details.cbStruct := sizeof(TACMDRIVERDETAILS);
acmDriverDetails(hadid, details, 0);
acmDriverOpen(driver, hadid, 0);
for i := 0 to details.cFormatTags - 1 do
begin
ZeroMemory(@fmtDetails, sizeof(fmtDetails));
fmtDetails.cbStruct := sizeof(TACMFORMATTAGDETAILS);
fmtDetails.dwFormatTagIndex := i;
acmFormatTagDetails(driver, fmtDetails, ACM_FORMATTAGDETAILSF_INDEX);
if (fmtDetails.dwFormatTag = WAVE_FORMAT_MPEGLAYER3) then inc(g_mp3Drivers);
end;
acmDriverClose(driver, 0);
end;
Result := true;
end;
function ConverMP3ToRaw(Mp3FileName: pChar; const Channels, SamplesPerSec, BitsPerSample: Integer): Boolean; stdcall;
var
mmr : MMRESULT;
maxFormatSize : DWORD;
waveFormat : PWAVEFORMATEX;
mp3format : PMPEGLAYER3WAVEFORMAT;
g_mp3stream : HACMSTREAM;
fpIn, fpOut : Integer;
rawbufsize : Cardinal;
mp3buf, rawbuf : PBYTE;
mp3streamHead : TACMSTREAMHEADER;
count : Cardinal;
RawFileName : string;
begin
Result := False;
acmDriverEnum(acmDriverEnumCallback, 0, 0); // try to find an MP3 codec
if (g_mp3Drivers = 0) then Exit;
maxFormatSize := 0; // find the biggest format size
acmMetrics(nil, ACM_METRIC_MAX_SIZE_FORMAT, maxFormatSize);
waveFormat := PWAVEFORMATEX(Pointer(LocalAlloc(LPTR, maxFormatSize))); // define desired output format
waveFormat^.wFormatTag := WAVE_FORMAT_PCM;
if Channels = 1 then waveFormat^.nChannels := 1;
if Channels = 2 then waveFormat^.nChannels := 2;
waveFormat^.nSamplesPerSec := SamplesPerSec; // 44.1kHz
waveFormat^.wBitsPerSample := BitsPerSample; // 16 bits
waveFormat^.nBlockAlign := waveFormat^.nChannels * waveFormat^.wBitsperSample div 8; // 4; // 4 bytes of data at a time are useful (1 sample)
waveFormat^.nAvgBytesPerSec := waveFormat^.nBlockAlign * SamplesPerSec; // byte-rate
waveFormat^.cbSize := 0; // no more data to follow
mp3format := PMPEGLAYER3WAVEFORMAT(Pointer(LocalAlloc(LPTR, maxFormatSize))); // define MP3 input format
mp3format^.wfx.cbSize := MPEGLAYER3_WFX_EXTRA_BYTES;
mp3format^.wfx.wFormatTag := WAVE_FORMAT_MPEGLAYER3;
mp3format^.wfx.nChannels := 2;
mp3format^.wfx.nAvgBytesPerSec := 128 * (1024 div 8); // not really used but must be one of 64, 96, 112, 128, 160kbps
mp3format^.wfx.wBitsPerSample := 0; // MUST BE ZERO
mp3format^.wfx.nBlockAlign := 1; // MUST BE ONE
mp3format^.wfx.nSamplesPerSec := 44100; // 44.1kHz
mp3format^.fdwFlags := MPEGLAYER3_FLAG_PADDING_OFF;
mp3format^.nBlockSize := MP3_BLOCK_SIZE; // voodoo value #1
mp3format^.nFramesPerBlock := 1; // MUST BE ONE
mp3format^.nCodecDelay := 1393; // voodoo value #2
mp3format^.wID := MPEGLAYER3_ID_MPEG;
g_mp3stream := nil;
mmr := acmStreamOpen(g_mp3stream, // open an ACM conversion stream
nil, // querying all ACM drivers
TWAVEFORMATEX(Pointer(mp3format)^), //TWAVEFORMATEX(Pointer(LongInt(@mp3format))), // converting from MP3
waveFormat^, // to WAV
nil, // with no filter
0, // or async callbacks
0, // (and no data for the callback)
0 // and no flags
);
LocalFree(LongInt(mp3format));
LocalFree(LongInt(waveFormat));
if mmr <> 0 then Exit;
// MP3 stream converter opened correctly
// now, let's open a file, read in a bunch of MP3 data, and convert it!
// open file
fpIn := FileOpen(MP3FileName, fmOpenRead);
if (fpIn = 0) then Exit;
// find out how big the decompressed buffer will be
rawbufsize := 0;
acmStreamSize(g_mp3stream, MP3_BLOCK_SIZE, rawbufsize, ACM_STREAMSIZEF_SOURCE);
// allocate our I/O buffers
mp3Buf := PByte(LocalAlloc(LPTR, MP3_BLOCK_SIZE));
rawbuf := pByte(LocalAlloc(LPTR, rawbufsize));
// prepare the decoder
ZeroMemory(@mp3streamHead, sizeof(TACMSTREAMHEADER));
mp3streamHead.cbStruct := sizeof(TACMSTREAMHEADER);
mp3streamHead.pbSrc := mp3buf;
mp3streamHead.cbSrcLength := MP3_BLOCK_SIZE;
mp3streamHead.pbDst := rawbuf;
mp3streamHead.cbDstLength := rawbufsize;
acmStreamPrepareHeader(g_mp3stream, mp3streamHead, 0);
// let's dump this data off to disk (for debug checking!)
RawFileName := ChangeFileExt(MP3FileName, '.raw');
fpOut := FileCreate(RawFileName);
if (fpOut = 0) then Exit;
FileSeek(fpIn, 0, 0);
while True do
begin
//suck in some MP3 data
Count := FileRead(fpIn, mp3buf^, MP3_BLOCK_SIZE);
if (Count <> MP3_BLOCK_SIZE) then break;
// convert the data
mmr := acmStreamConvert(g_mp3stream, mp3streamHead, ACM_STREAMCONVERTF_BLOCKALIGN);
if mmr <> 0 then
begin
MessageBox(0, '输入参数错误。请检查你的输入参数。', '系统提示: ', 64);
Exit;
end;
//write the decoded PCM to disk
Count := FileWrite(fpOut, rawbuf^, mp3streamHead.cbDstLengthUsed);
if Count <> mp3streamHead.cbDstLengthUsed then
begin
MessageBox(0, '输入参数错误。请检查你的输入参数。', '系统提示: ', 64);
Exit;
end;
end; ;
// clean up after yourself like a good little boy
FileClose(fpIn);
FileClose(fpOut);
acmStreamUnprepareHeader(g_mp3stream, mp3streamHead, 0);
LocalFree(LongInt(rawbuf));
LocalFree(LongInt(mp3buf));
acmStreamClose(g_mp3stream, 0);
Result := True;
end;
ConverMP3ToRaw函数是将MP3转换成RAW(RIFF格式),添加WAV文件头就是WAV文件了。
待续......