Wav->Mp3 ACM encoding problem

Tech-Archive recommends: Fix windows errors by optimizing your registry



I want to convert 16kHz mono 16bit PCM .wav file into .mp3 using Fraunhofer codec built into Windows XP.

I am using code pasted below, but something is wrong with it.

Mp3 file encoded that way looks good, but there is annoying "click" at the beginning of file, and when I playing it in WMP (or any other player that use windows codecs) audio ends about half second to early (winamp can play file to the end).


When I load same source .wav file into "sound recorder", and there convert it using same Fraunhofer ACM codec with same settings, into MPEG-3 encoded .wav file, there is no "click", and every player plays file to the end.
When I remove .wav file header from that compressed .wav file, and leave only mp3 data - that mp3 works prefect in all mp3 players (no click, and plays to the end).

Please, look at code below and tell me, what is wrong with it.






#define PCM_BLOCK_SIZE 1024

BOOL CALLBACK CAudioCon::mp3Callback( HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport )
{
ACMDRIVERDETAILS det;
det.cbStruct = sizeof(det);
if (!acmDriverDetails(hadid,&det,0))
{
if (strstr(det.szShortName, "MPEG Layer-3"))
{
CAudioCon* p=(CAudioCon*)dwInstance;
p->m_mp3id=hadid;
}
}
return TRUE;
}


int CAudioCon::convertMP3(char* wavFile, char* mp3File, int mode)
{
MMRESULT mmr;

m_mp3id=0;
acmDriverEnum( (ACMDRIVERENUMCB)mp3Callback, (DWORD)this, 0 );

if(m_mp3id == 0)
{
OutputDebugString( "No MP3 codecs found!\n" );
return E_FAIL;
}

HACMDRIVER driver;
if (acmDriverOpen( &driver, m_mp3id, 0 ))
{
OutputDebugString( "Error loading codec!\n" );
return E_FAIL;
}

// find the biggest format size
DWORD maxFormatSize = 0;
mmr = acmMetrics( NULL, ACM_METRIC_MAX_SIZE_FORMAT, &maxFormatSize );

LPWAVEFORMATEX waveFormat = (LPWAVEFORMATEX) LocalAlloc( LPTR, maxFormatSize );
waveFormat->wFormatTag = WAVE_FORMAT_PCM;
waveFormat->nChannels = 1;
waveFormat->nSamplesPerSec = 16000;
waveFormat->wBitsPerSample = 16;
waveFormat->nBlockAlign = 2;
waveFormat->nAvgBytesPerSec=
waveFormat->nBlockAlign*waveFormat->nSamplesPerSec;
waveFormat->cbSize = 0;

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

mp3format->wfx.nChannels = 1;
mp3format->wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3;

MMRESULT ret=acmFormatSuggest( driver, waveFormat,
(LPWAVEFORMATEX)mp3format, maxFormatSize,
ACM_FORMATSUGGESTF_NCHANNELS|
ACM_FORMATSUGGESTF_WFORMATTAG);

HACMSTREAM pcmToMp3 = NULL;
mmr = acmStreamOpen( &pcmToMp3, driver,
waveFormat,
(LPWAVEFORMATEX) mp3format,
NULL, 0, 0,
ACM_STREAMOPENF_NONREALTIME );

LocalFree( mp3format );
LocalFree( waveFormat );

switch( mmr )
{
case MMSYSERR_NOERROR:
break; // success!
case MMSYSERR_INVALPARAM:
OutputDebugString( "Invalid parameters passed to acmStreamOpen" );
acmStreamClose( pcmToMp3, 0 );
acmDriverClose( driver, 0 );
return E_FAIL;
case ACMERR_NOTPOSSIBLE:
OutputDebugString( "No ACM filter found" );
acmStreamClose( pcmToMp3, 0 );
acmDriverClose( driver, 0 );
return E_FAIL;
default:
OutputDebugString( "Some error opening ACM decoding stream!" );
acmStreamClose( pcmToMp3, 0 );
acmDriverClose( driver, 0 );
return E_FAIL;
}

FILE *fpIn = fopen( wavFile, "rb" );
if( fpIn == NULL )
{
OutputDebugString( "can't open source file!" );
acmStreamClose( pcmToMp3, 0 );
return E_FAIL;
}

unsigned long outbufsize = 0;
mmr = acmStreamSize( pcmToMp3, PCM_BLOCK_SIZE, &outbufsize,
ACM_STREAMSIZEF_SOURCE );
ASSERT( mmr == 0 );
ASSERT( outbufsize > 0 );

LPBYTE inBuf = (LPBYTE) LocalAlloc( LPTR, PCM_BLOCK_SIZE );
LPBYTE rawbuf = (LPBYTE) LocalAlloc( LPTR, outbufsize );

ACMSTREAMHEADER mp3streamHead;
ZeroMemory( &mp3streamHead, sizeof(ACMSTREAMHEADER ) );
mp3streamHead.cbStruct = sizeof(ACMSTREAMHEADER );
mp3streamHead.pbSrc = inBuf;
mp3streamHead.cbSrcLength = PCM_BLOCK_SIZE;
mp3streamHead.pbDst = rawbuf;
mp3streamHead.cbDstLength = outbufsize;
mmr = acmStreamPrepareHeader( pcmToMp3, &mp3streamHead, 0 );
ASSERT( mmr == 0 );

FILE *fpOut;

if (mode==0)
fpOut = fopen( mp3File, "wb" );
else
fpOut = fopen( mp3File, "ab" );

if( fpOut == NULL )
{
OutputDebugString( "can't output output!" );
acmStreamClose( pcmToMp3, 0 );
acmDriverClose( driver, 0 );
return E_FAIL;
}

while(1)
{
bool brk=false;
int count = fread( inBuf, 1, PCM_BLOCK_SIZE, fpIn );
if( count != PCM_BLOCK_SIZE )
{
for(int i=count; i<PCM_BLOCK_SIZE; i++)
inBuf[i]=0;
brk=true;
}

mmr = acmStreamConvert( pcmToMp3, &mp3streamHead,
ACM_STREAMCONVERTF_BLOCKALIGN );
ASSERT( mmr == 0 );
count = fwrite( rawbuf, 1, mp3streamHead.cbDstLengthUsed, fpOut );
ASSERT( count == mp3streamHead.cbDstLengthUsed );

if( brk )
break;
};

mmr = acmStreamUnprepareHeader( pcmToMp3, &mp3streamHead, 0 );
ASSERT( mmr == 0 );
LocalFree(rawbuf);
LocalFree(inBuf);
mmr = acmStreamClose( pcmToMp3, 0 );
ASSERT( mmr == 0 );
fclose( fpIn );
fclose( fpOut );
acmDriverClose( driver, 0 );

return S_OK;
}
.