crashing in AHX/HVL audio thread.
category: code [glöplog]
Hi, I have been trying to play someone's AHX tune using xeron's currently available replayer code as a base.
for some reason, it crashes in wdmaud.drv on exit, not sure why. Any pointers as to why this code could be crap would be appreciated.
Code:
DWORD WINAPI AudioThread(LPVOID lpParameter)
{
HANDLE eventh;
HWAVEOUT hWaveOut = (HWAVEOUT)INVALID_HANDLE_VALUE;
WAVEFORMATEX wfx;
LPSTR audblock;
char audiobuffer[BUFFNUM][((44100*2*2)/50)];
struct hvl_tune *ht = NULL;
thrddata* instance = (thrddata*)lpParameter;
wfx.nSamplesPerSec = 44100;
wfx.wBitsPerSample = 16;
wfx.nChannels = 2;
wfx.cbSize = 0;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
hvl_InitReplayer();
ht = hvl_load_ahx((uint8*)instance->data,instance->len,2,44100);
if( !ht ) return FALSE;
eventh = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // initial state is nonsignaled
TEXT("WriteEvent") // object name
);
int nextbuf = 0;
if( waveOutOpen( (HWAVEOUT*)&hWaveOut, WAVE_MAPPER, &wfx, (unsigned int)eventh, 0, CALLBACK_EVENT ) != MMSYSERR_NOERROR )
{
printf( "Unable to open waveout\n" );
return FALSE;
}
int i;
WAVEHDR header[BUFFNUM];
for ( i=0; i<BUFFNUM; i++ ){
memset( &header[i], 0, sizeof( WAVEHDR ) );
header[i].dwBufferLength = ((44100*2*2)/50);
header[i].lpData = (LPSTR)audiobuffer[i];
}
for ( i=0; i<BUFFNUM-1; i++ ){
hvl_DecodeFrame( ht, (int8*)audiobuffer[nextbuf], (int8*)audiobuffer[nextbuf]+2, 4 );
waveOutPrepareHeader( hWaveOut, &header[nextbuf], sizeof( WAVEHDR ) );
waveOutWrite( hWaveOut, &header[nextbuf], sizeof( WAVEHDR ) );
nextbuf = (nextbuf+1)%BUFFNUM;
}
while(true)
{
hvl_DecodeFrame( ht, (int8*)audiobuffer[nextbuf], (int8*)audiobuffer[nextbuf]+2, 4 );
waveOutPrepareHeader( hWaveOut, &header[nextbuf], sizeof( WAVEHDR ) );
waveOutWrite( hWaveOut, &header[nextbuf], sizeof( WAVEHDR ) );
nextbuf = (nextbuf+1)%BUFFNUM;
while( waveOutUnprepareHeader( hWaveOut, &header[nextbuf], sizeof( WAVEHDR ) ) == WAVERR_STILLPLAYING ){
WaitForSingleObject(eventh, INFINITE);
}
ResetEvent(eventh);
}
if( ht ) hvl_FreeTune( ht );
if( hWaveOut != INVALID_HANDLE_VALUE ) waveOutClose( hWaveOut );
}
for some reason, it crashes in wdmaud.drv on exit, not sure why. Any pointers as to why this code could be crap would be appreciated.
did some changes like adding a variable to while(true) to check whether the thread is being shut down, and using WaitForSingleObject(handle,INFINITE) but still no dice.
are you using a recent version of the replayer (1.8, or svn head)?
Well, i don't see any chance how you leave your while(true) loop. On exit i suppose your AudioThread is going crazy and tries to play buffers which were already freed by the runtime...
le w00t! a recent version of AHX player!!!! <3
for visual C++? the player will work with a (very very) old version? (I'm still using VC6.0).
for visual C++? the player will work with a (very very) old version? (I'm still using VC6.0).
xeron: yes, I am using 1.8.
code is
Code:
struct thrddata {
void *data;
int len;
int subsong;
};
bool isplaying=false;
DWORD WINAPI AudioThread(LPVOID lpParameter)
{
HANDLE eventh;
HWAVEOUT hWaveOut = (HWAVEOUT)INVALID_HANDLE_VALUE;
WAVEFORMATEX wfx;
LPSTR audblock;
char audiobuffer[BUFFNUM][((44100*2*2)/50)];
struct hvl_tune *ht = NULL;
thrddata* instance = (thrddata*)lpParameter;
wfx.nSamplesPerSec = 44100;
wfx.wBitsPerSample = 16;
wfx.nChannels = 2;
wfx.cbSize = 0;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
hvl_InitReplayer();
ht = hvl_load_ahx((uint8*)instance->data,instance->len,2,44100);
if( !ht ) return FALSE;
eventh = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // initial state is nonsignaled
TEXT("WriteEvent") // object name
);
int nextbuf = 0;
if( waveOutOpen( (HWAVEOUT*)&hWaveOut, WAVE_MAPPER, &wfx, (unsigned int)eventh, 0, CALLBACK_EVENT ) != MMSYSERR_NOERROR )
{
printf( "Unable to open waveout\n" );
return FALSE;
}
int i;
WAVEHDR header[BUFFNUM];
for ( i=0; i<BUFFNUM; i++ ){
memset( &header[i], 0, sizeof( WAVEHDR ) );
header[i].dwBufferLength = ((44100*2*2)/50);
header[i].lpData = (LPSTR)audiobuffer[i];
}
for ( i=0; i<BUFFNUM-1; i++ ){
hvl_DecodeFrame( ht, (int8*)audiobuffer[nextbuf], (int8*)audiobuffer[nextbuf]+2, 4 );
waveOutPrepareHeader( hWaveOut, &header[nextbuf], sizeof( WAVEHDR ) );
waveOutWrite( hWaveOut, &header[nextbuf], sizeof( WAVEHDR ) );
nextbuf = (nextbuf+1)%BUFFNUM;
}
isplaying=true;
while(isplaying)
{
hvl_DecodeFrame( ht, (int8*)audiobuffer[nextbuf], (int8*)audiobuffer[nextbuf]+2, 4 );
waveOutPrepareHeader( hWaveOut, &header[nextbuf], sizeof( WAVEHDR ) );
waveOutWrite( hWaveOut, &header[nextbuf], sizeof( WAVEHDR ) );
nextbuf = (nextbuf+1)%BUFFNUM;
// Don't do this in your own player or plugin :-)
//while( waveOutUnprepareHeader( hWaveOut, &header[nextbuf], sizeof( WAVEHDR ) ) == WAVERR_STILLPLAYING ) ;
while( waveOutUnprepareHeader( hWaveOut, &header[nextbuf], sizeof( WAVEHDR ) ) == WAVERR_STILLPLAYING ){
WaitForSingleObject(eventh, INFINITE);
}
ResetEvent(eventh);
}
if( ht ) hvl_FreeTune( ht );
if( hWaveOut != INVALID_HANDLE_VALUE ) waveOutClose( hWaveOut );
}
Code:
int intro_init( int xr, int yr, int nomusic, IntroProgressDelegate *pd )
{
.....
DWORD g_id = NULL;
threaddata = (thrddata*)malloc( sizeof(thrddata));
threaddata->data = (void*)music;
threaddata->len = music_len;
g_handle = CreateThread( NULL, 0, AudioThread,(LPVOID)threaddata, NULL, &g_id );
Code:
void intro_end()
{
isplaying=false;
WaitForSingleObject(g_handle,INFINITE);
free(threaddata);
}
@rez
Its just plain C, should compile everywhere.
Its just plain C, should compile everywhere.
Depends on which flavour of plain C it is, though. ;)
Worked out a fix.
Indeed, it seemed some buffers were not cleaned and sent.
Code:
if( hWaveOut != INVALID_HANDLE_VALUE )
{
for (int i = 0; i < BUFFNUM; ++i)
{
if (header[i].lpData)
{
waveOutUnprepareHeader(hWaveOut, &header[nextbuf], sizeof( WAVEHDR ) );
header[i].dwFlags &= ~WHDR_PREPARED;
}
}
waveOutReset(hWaveOut);
waveOutClose(hWaveOut);
}
Indeed, it seemed some buffers were not cleaned and sent.
cool :-)