waveOutReset()? crashing my program [Solved, thank you]

Started by
11 comments, last by dev578 18 years, 1 month ago
Every time I try to stop waveform audio, my program hangs on waveOutUnprepareHeader(). Why would this be happening? I can't find a single reason why it would crash on it. I guess I can post the relevant code:

//
//My Callback Function
//
int CALLBACK VoiceWaveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
	//this message can be sent if a buffer is sent back, or if the stop button was pressed
 	if (uMsg == WOM_DONE)
	{
		//get a pointer to the instance of CSound
		CSound* pCSound = reinterpret_cast<CSound*>((DWORD_PTR)dwInstance);
		unsigned long result;

		char *Buffer;
		//get the number of the buffer returned
		int nBufferReturned = 0;
		
		for (int x = 0; x < NBUFFERS; x++)
		{
			if (dwParam1 == (DWORD_PTR)&pCSound->WaveHeader[x])
			{
				nBufferReturned = x;
				Buffer = pCSound->Buffer[x];
				if (x!= NBUFFERS-1)
					pCSound->CurrentBuffer = pCSound->Buffer[x+1];
				else
					pCSound->CurrentBuffer = pCSound->Buffer[0];
			}
		}


		//if we aren't playing, return
		if (pCSound->iAction == -1)
		{
			char TempChar[512];
			sprintf(TempChar,"Buffer %i returned for clearing\n",nBufferReturned);
			OutputDebugString(TempChar);

//CRASHES RIGHT HERE, the first time it is called
			result = waveOutUnprepareHeader(pCSound->outHandle, pCSound->WaveHeader[nBufferReturned], sizeof(WAVEHDR));
			if(result) return 1;

			for (int i = 0; i < (int)pCSound->m_dwLength; i++)
				Buffer = NULL;
			return 0;
		}
//...
}
}

//Play Function
int CSound::Play()
{
	if (iAction == 2)
	{
		waveOutRestart(outHandle);
		iAction = 0;
		return 0;
	}
	
	for (int x = 0; x < NBUFFERS; x++)
		for (int i = 0; i < (int)m_dwLength; i++)
			Buffer[x] = 0;

	PlayOffset = 0;

	FILE *fp = fopen(CurFile,"rb");
	fseek(fp,0,SEEK_END);
	PlaySize = (int)ftell(fp);
	fseek(fp,0,SEEK_SET);
	if (PlaySize == 0)
	{
		fclose(fp);
		PlayDone();
		return 0;
	}

	unsigned long result;
	
	for (int x = 0; x < NBUFFERS; x++)
	{
		fread(Buffer[x],sizeof(char),(int)m_dwLength,fp);
		PlayOffset+=1;

		WaveHeader[x].lpData = Buffer[x];
		WaveHeader[x].dwBufferLength=m_dwLength;
		WaveHeader[x].dwBytesRecorded=0;
		WaveHeader[x].dwUser=0;
		WaveHeader[x].dwFlags=0;
		WaveHeader[x].reserved=0;
		WaveHeader[x].lpNext=0;

		result = waveOutPrepareHeader(outHandle,&WaveHeader[x],sizeof(WAVEHDR));
		if(result) return 1;

		result = waveOutWrite(outHandle,&WaveHeader[x],sizeof(WAVEHDR));
		if(result) return 1;
	}

	fclose(fp);
	
	iAction = 0;

	CurrentBuffer = Buffer[0];

	return 0;
}

//Stop Function
//...
iAction = -1;
result = waveOutReset(outHandle);
//...

//Additional Info

#define NBUFFERS 16

//in class
WAVEHDR WaveHeader[NBUFFERS];
WAVEFORMATEX waveFormat;
char* Buffer[NBUFFERS];

//Initialization
for (int x = 0; x < NBUFFERS; x++)
{
	Buffer[x] = new char[m_dwLength];
	for (int i = 0; i < (int)m_dwLength; i++)
		Buffer[x] = 0;
}




Urgh, I don't see any reason for it to hang on that. If anyone has any ideas, I would appreciate them. Thank you, Dev578 [Edited by - dev578 on March 5, 2006 2:10:39 PM]
Advertisement
You really need to give more info to be helpful.

- by 'hang' do you mean crash?
- What info does the debugger give you? (expception information, addresses etc.)
- Do you have a full callstack when it crashes?
- Does it crash in Debug?
- Has it ever worked? (i.e. is this old code that has recently been changed, or is it completely new work)

Thanks

Paul
By hang, I mean the program just becomes unresponsive. There is no debug error or anything. I have to stop it from the debugger, there is also no error messages. No it has never worked correctly, although when I ran all the waveOutUnprepareHeaders() in the stop function after waveOutReset(), I altered between playing and stoping. It would work right for awile, and then hang like it is doing now. The way I have it now, it hangs the first time you play and then hit the stop button. Hope this helps, I don't see what is going wrong.

Thank you,



Dev578
After doing some googling it might be that you cannot use any of the WaveOut... functions within the callback, just google "waveOutUnprepareHeader hang callback" to find people with the same problem as you,

Paul
Ok, if that is the case, on my CALLBACK, I will just return when the buffers get sent back when stop is pressed. In my stop function I will call waveOutReset() and then after it cycle through and Unprepare all the Headers as well as zero out all the buffers. Now something interesting happens here. It works seemingly perfect for a random amount of times, and then when you hit stop, it freezes. This time it doesn't freeze on unpreparing the header, it freezes on waveOutReset(), it never returns. Umm... ??? I still can't see any reason for this.


Dev578
I think a pointer is needed in the second parameter of waveOutUnprepareHeader()
//OLDresult = waveOutUnprepareHeader(pCSound->outHandle, pCSound->WaveHeader[nBufferReturned], sizeof(WAVEHDR));//NEWresult = waveOutUnprepareHeader(pCSound->outHandle, &(pCSound->WaveHeader[nBufferReturned]), sizeof(WAVEHDR));
0xa0000000
Oh, yes it is a pointer. That would explain why it crashed there that time. It is still doing the same thing though. In my callback, when waveOutReset() is called, I just return 0; Like:

if (pCSound->iAction == -1) return 0;

Then after waveOutReset() finishes, I unprepare all the headers and clear the buffers like so:

for (int x = 0; x < NBUFFERS; x++)
{
result = waveOutUnprepareHeader(outHandle,&(WaveHeader[x]), sizeof(WAVEHDR));
if(result) return 1;

for (int i = 0; i < (int)m_dwLength; i++)
Buffer[x] = NULL;
}

I keep playing a file and then stopping it. It will work perfectly for a random amount of times, and then just lock up and become unresponsive. I don't even know what else it can be. Further tests show that the time I hit stop and it crashes, waveOutReset() never returns, and the callback is never called with the buffers being returned. The other times that the stop works, this all works fine. Any ideas?

Thank you,



Dev578
Sorry, more information needed. I'm not familiar with the waveOut*/audioform interface.

-What are you trying to do (streaming audio)?
-How are you using waveOut* to do it(general overview of implementation using waveOut*)?
-Can you provide a minimal program that reproduces that crash(helps others to debug the problem)?

Good Luck.
0xa0000000
Interesting find, I ran it on another Windows XP Pro machine in VC++ debug mode and it didn't crash. On my computer, it still crashes though. It works fine and does exactly what it is supposed to for awile, and then when you hit stop and it calls waveOutReset(), the CALLBACK funcion is never even called (it is supposed to to return the buffers that were in the queue), and it just freezes as mentioned before. Here is the code with the slight change that I unprepare all the headers on the stop function, and not in the CALLBACK, just incase that is what is freezing it:

int CSound::Play(){	if (iAction == 2)	{		waveOutRestart(outHandle);		iAction = 0;		return 0;	}		for (int x = 0; x < NBUFFERS; x++)		for (int i = 0; i < (int)m_dwLength; i++)			Buffer[x] = 0;	PlayOffset = 0;	FILE *fp = fopen(CurFile,"rb");	fseek(fp,0,SEEK_END);	PlaySize = (int)ftell(fp);	fseek(fp,0,SEEK_SET);	if (PlaySize == 0)	{		fclose(fp);		PlayDone();		return 0;	}	unsigned long result;		for (int x = 0; x < NBUFFERS; x++)	{		fread(Buffer[x],sizeof(char),(int)m_dwLength,fp);		PlayOffset+=1;		WaveHeader[x].lpData = Buffer[x];		WaveHeader[x].dwBufferLength=m_dwLength;		WaveHeader[x].dwBytesRecorded=0;		WaveHeader[x].dwUser=0;		WaveHeader[x].dwFlags=0;		WaveHeader[x].reserved=0;		WaveHeader[x].lpNext=0;		result = waveOutPrepareHeader(outHandle,&(WaveHeader[x]),sizeof(WAVEHDR));		if(result) return 1;		result = waveOutWrite(outHandle,&WaveHeader[x],sizeof(WAVEHDR));		if(result) return 1;	}	fclose(fp);		iAction = 0;	CurrentBuffer = Buffer[0];	return 0;}int CALLBACK VoiceWaveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2){	OutputDebugString("CallBack Called\n");	//this message can be sent if a buffer is sent back, or if the stop button was pressed 	if (uMsg == WOM_DONE)	{		OutputDebugString("WOM_DONE Message Called\n");		//get a pointer to the instance of CSound		CSound* pCSound = reinterpret_cast<CSound*>((DWORD_PTR)dwInstance);		unsigned long result;		OutputDebugString("About to Return if pCSound->iAction == -1\n");		if (pCSound->iAction == -1) return 0;                //the rest should be irrelevant, if it didn't return, I just fill the buffer with more data and send it back to the driver, I know it works, it never crashes on Play        }}//if stop is called and it is playing:OutputDebugString("About to Call WaveOutReset\n");iAction = -1;//THIS IS WHAT CRASHES WHEN THE PROGRAM FREEZES, IT NEVER CALLS THE CALLBACK WHEN IT FREEZESwaveOutReset(outHandle);for (int x = 0; x < NBUFFERS; x++){		result = waveOutUnprepareHeader(outHandle,&(WaveHeader[x]), sizeof(WAVEHDR));		if(result) return 1;	for (int i = 0; i < (int)m_dwLength; i++)		Buffer[x] = NULL;}//Additional Info#define NBUFFERS 16//in classWAVEHDR WaveHeader[NBUFFERS];WAVEFORMATEX waveFormat;char* Buffer[NBUFFERS];//Initializationfor (int x = 0; x < NBUFFERS; x++){	Buffer[x] = new char[m_dwLength];	for (int i = 0; i < (int)m_dwLength; i++)		Buffer[x] = 0;}


Any Ideas? Thank you for your time.



Dev578

Edit: I am trying to play and stop uncompressed PCM sound, and I don't think I can produce a smaller example that crashes because it needs all this to work.
I don't quite understand why you are using so many buffers for one sound. I've been able to quite easily play them with just one or two.
.

This topic is closed to new replies.

Advertisement