PDA

View Full Version : Can we use function acmStreamConvert() to decode an mp3 file?


Cherish_He
04-02-2006, 06:35 AM
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^_^.

juhnu
04-02-2006, 08:43 AM
depends whether you have an mp3 codec (or whatever compressed audio format is in question) installed on your system or not.

Cherish_He
04-04-2006, 02:08 AM
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^_^.

Nils Pipenbrinck
04-04-2006, 02: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.104/search?q=cache:5uQJbHx_Jf0J:david.weekly.org/code/mp3acm.html+WAVE_FORMAT_MPEGLAYER3&hl=it

Cherish_He
04-10-2006, 01:52 AM
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.104/search?q=cache:5uQJbHx_Jf0J:david.weekly.org/code/mp3acm.html+WAVE_FORMAT_MPEGLAYER3&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^_^.

Nils Pipenbrinck
04-11-2006, 02: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;
}