Jump to content


Can we use function acmStreamConvert() to decode an mp3 file?


5 replies to this topic

#1 Cherish_He

    New Member

  • Members
  • PipPip
  • 16 posts

Posted 02 April 2006 - 12:35 PM

Can we use function acmStreamConvert() to decode an mp3 file or any other kind of compressed audio format?
If it can? How to do that?
Thanks a lot^_^.

#2 juhnu

    Valued Member

  • Members
  • PipPipPip
  • 292 posts

Posted 02 April 2006 - 02:43 PM

depends whether you have an mp3 codec (or whatever compressed audio format is in question) installed on your system or not.

#3 Cherish_He

    New Member

  • Members
  • PipPip
  • 16 posts

Posted 04 April 2006 - 08:08 AM

juhnu said:

depends whether you have an mp3 codec (or whatever compressed audio format is in question) installed on your system or not.

I can get the driver id of the mp3 codec, but the most important is that I did not how to fill the WAVEFORMATEX struct. Which function can be called to get the information such as the sample rate? Thanks a lot^_^.

#4 Nils Pipenbrinck

    Senior Member

  • Members
  • PipPipPipPip
  • 597 posts

Posted 04 April 2006 - 08:11 PM

why don't you just encode or convert a file (the plain old soundrecorder can do this), load the WAVEFORMATEX structure and take a look what they put into the fields?

As far as I remember (I decoded mp3's using the ACM-services) everything was pretty obvious (e.g. bitrate directly translated into nAvgBytesPerSec ect.).

also - this could be helpful:

http://64.233.183.10...PEGLAYER3&hl=it

#5 Cherish_He

    New Member

  • Members
  • PipPip
  • 16 posts

Posted 10 April 2006 - 07:52 AM

Nils Pipenbrinck said:

why don't you just encode or convert a file (the plain old soundrecorder can do this), load the WAVEFORMATEX structure and take a look what they put into the fields?

As far as I remember (I decoded mp3's using the ACM-services) everything was pretty obvious (e.g. bitrate directly translated into nAvgBytesPerSec ect.).

also - this could be helpful:

http://64.233.183.10...PEGLAYER3&hl=it

My mission is to decode some compressed wave format file and play it by direct sound. I does not have the original uncompressed wave file, and I want to play the compressed wave file just like direct show do. But if I use direct show, I cound not controll some 3D parameters such as position. So I had to use the ACM-services to decode such file and play it with direct sound. But since the file format is unknown, I want to know that how to choose the right driver and how to fill the WAVEFORMATEX just like direct show do? Thanks a lot^_^

I can not open the url you gave me, can you paste the code in the url to me? Or send to my email? My email box is ho19@hotmail.com. Thanks a lot^_^.

#6 Nils Pipenbrinck

    Senior Member

  • Members
  • PipPipPipPip
  • 597 posts

Posted 11 April 2006 - 08:02 PM


#include <windows.h>

#include <stdio.h>

#include <assert.h>

#include <mmreg.h>

#include <msacm.h>


#define MP3_BLOCK_SIZE 522

#define SOURCE_MP3 "C:\\audiograbber\\At The Club Last Night\\At_The_Club_Last_Night_-_Haven't_You_Heard.mp3"

#define OUTPUT_PCM_FILE "c:\\dump.pcm"


int g_mp3Drivers = 0;


BOOL CALLBACK acmDriverEnumCallback( HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport ){

  if( fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC ) {

    MMRESULT mmr;


    ACMDRIVERDETAILS details;

    details.cbStruct = sizeof(ACMDRIVERDETAILS);

    mmr = acmDriverDetails( hadid, &details, 0 );


    HACMDRIVER driver;

    mmr = acmDriverOpen( &driver, hadid, 0 );


    int i;

    for(i = 0; i < details.cFormatTags; i++ ){

      ACMFORMATTAGDETAILS fmtDetails;

      ZeroMemory( &fmtDetails, sizeof(fmtDetails) );

      fmtDetails.cbStruct = sizeof(ACMFORMATTAGDETAILS);

      fmtDetails.dwFormatTagIndex = i;

      mmr = acmFormatTagDetails( driver, &fmtDetails, ACM_FORMATTAGDETAILSF_INDEX );

      if( fmtDetails.dwFormatTag == WAVE_FORMAT_MPEGLAYER3 ){

	OutputDebugString( L"Found an MP3-capable ACM codec: " );

	OutputDebugString( details.szLongName );

	OutputDebugString( L"\n" );

	g_mp3Drivers++;

      }

    }

    mmr = acmDriverClose( driver, 0 );

  }

  return true;

}


HACMSTREAM g_mp3stream = NULL;




convertMP3(){

  

  MMRESULT mmr;

  

  // try to find an MP3 codec

  acmDriverEnum( acmDriverEnumCallback, 0, 0 );

  if(g_mp3Drivers == 0){

    OutputDebugString( L"No MP3 decoders found!\n" );

    return E_FAIL;

  }

  

  // find the biggest format size

  DWORD maxFormatSize = 0;

  mmr = acmMetrics( NULL, ACM_METRIC_MAX_SIZE_FORMAT, &maxFormatSize );

  

  // define desired output format

  LPWAVEFORMATEX waveFormat = (LPWAVEFORMATEX) LocalAlloc( LPTR, maxFormatSize );

  waveFormat->wFormatTag = WAVE_FORMAT_PCM;

  waveFormat->nChannels = 2; // stereo

  waveFormat->nSamplesPerSec = 44100; // 44.1kHz

  waveFormat->wBitsPerSample = 16; // 16 bits

  waveFormat->nBlockAlign = 4; // 4 bytes of data at a time are useful (1 sample)

  waveFormat->nAvgBytesPerSec = 4 * 44100; // byte-rate

  waveFormat->cbSize = 0; // no more data to follow

  

  

  // define MP3 input format

  LPMPEGLAYER3WAVEFORMAT mp3format = (LPMPEGLAYER3WAVEFORMAT) LocalAlloc( LPTR, maxFormatSize );

  mp3format->wfx.cbSize = MPEGLAYER3_WFX_EXTRA_BYTES;

  mp3format->wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3;

  mp3format->wfx.nChannels = 2;

  mp3format->wfx.nAvgBytesPerSec = 128 * (1024 / 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 = NULL;

  mmr = acmStreamOpen( &g_mp3stream,               // open an ACM conversion stream

  		     NULL,                       // querying all ACM drivers

  		     (LPWAVEFORMATEX) mp3format, // converting from MP3

  		     waveFormat,                 // to WAV

  		     NULL,                       // with no filter

  		     0,                          // or async callbacks

  		     0,                          // (and no data for the callback)

  		     0                           // and no flags

  		     );

  

  LocalFree( mp3format );

  LocalFree( waveFormat );

  

  switch( mmr ) {

   case MMSYSERR_NOERROR:

     break; // success!

   case MMSYSERR_INVALPARAM:

     assert( !"Invalid parameters passed to acmStreamOpen" );

     return E_FAIL;

   case ACMERR_NOTPOSSIBLE:

     assert( !"No ACM filter found capable of decoding MP3" );

     return E_FAIL;

   default:

     assert( !"Some error opening ACM decoding stream!" );

     return E_FAIL;

  }

  

  // MP3 stream converter opened correctly

  // now, let's open a file, read in a bunch of MP3 data, and convert it!

  

  // open file

  FILE *fpIn = fopen( SOURCE_MP3, "rb" );

  if( fpIn == NULL ){

    assert( !"can't open MP3 file!" );

    return E_FAIL;

  }

  

  // find out how big the decompressed buffer will be

  unsigned long rawbufsize = 0;

  mmr = acmStreamSize( g_mp3stream, MP3_BLOCK_SIZE, &rawbufsize, ACM_STREAMSIZEF_SOURCE );

  assert( mmr == 0 );

  assert( rawbufsize > 0 );

  

  // allocate our I/O buffers

  LPBYTE mp3buf = (LPBYTE) LocalAlloc( LPTR, MP3_BLOCK_SIZE );

  LPBYTE rawbuf = (LPBYTE) LocalAlloc( LPTR, rawbufsize );

  

  // prepare the decoder

  ACMSTREAMHEADER mp3streamHead;

  ZeroMemory( &mp3streamHead, sizeof(ACMSTREAMHEADER ) );

  mp3streamHead.cbStruct = sizeof(ACMSTREAMHEADER );

  mp3streamHead.pbSrc = mp3buf;

  mp3streamHead.cbSrcLength = MP3_BLOCK_SIZE;

  mp3streamHead.pbDst = rawbuf;

  mp3streamHead.cbDstLength = rawbufsize;

  mmr = acmStreamPrepareHeader( g_mp3stream, &mp3streamHead, 0 );

  assert( mmr == 0 );

  

  // let's dump this data off to disk (for debug checking!)

  FILE *fpOut = fopen( OUTPUT_PCM_FILE, "wb" );

  if( fpOut == NULL ){

    assert( !"can't output output PCM!" );

    return E_FAIL;

  }

  

  while(1) {

    // suck in some MP3 data

    int count = fread( mp3buf, 1, MP3_BLOCK_SIZE, fpIn );

    if( count != MP3_BLOCK_SIZE )

      break;

  

    // convert the data

    mmr = acmStreamConvert( g_mp3stream, &mp3streamHead, ACM_STREAMCONVERTF_BLOCKALIGN );

    assert( mmr == 0 );

  

    // write the decoded PCM to disk

    count = fwrite( rawbuf, 1, mp3streamHead.cbDstLengthUsed, fpOut );

    assert( count == mp3streamHead.cbDstLengthUsed );

  };

  

  // clean up after yourself like a good little boy

  fclose( fpIn );

  fclose( fpOut );

  mmr = acmStreamUnprepareHeader( g_mp3stream, &mp3streamHead, 0 );

  assert( mmr == 0 );

  LocalFree(rawbuf);

  LocalFree(mp3buf);

  mmr = acmStreamClose( g_mp3stream, 0 );

  assert( mmr == 0 );

  

  return S_OK;

}






1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users