MP3 互相转换 WAV (无需任何第三方dll)

一: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文件了。

待续......

你可能感兴趣的:(MP3 互相转换 WAV (无需任何第三方dll))