pouët.net

Go to bottom

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.

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.
added on the 2014-04-23 22:20:34 by mudlord mudlord
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.
added on the 2014-04-23 22:38:48 by mudlord mudlord
are you using a recent version of the replayer (1.8, or svn head)?
added on the 2014-04-23 23:24:38 by xeron xeron
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...
added on the 2014-04-23 23:59:26 by RufUsul RufUsul
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).
added on the 2014-04-24 00:29:30 by rez rez
xeron: yes, I am using 1.8.
added on the 2014-04-24 02:18:50 by mudlord mudlord
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); }
added on the 2014-04-24 03:11:15 by mudlord mudlord
@rez
Its just plain C, should compile everywhere.
added on the 2014-04-24 08:00:29 by xeron xeron
Depends on which flavour of plain C it is, though. ;)
Worked out a fix.

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.
added on the 2014-04-25 02:36:40 by mudlord mudlord
cool :-)
added on the 2014-04-26 20:22:52 by xeron xeron

login

Go to top