Sign in to follow this  

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

This topic is 4300 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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[i] = 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][i] = 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][i] = 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]

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
I think a pointer is needed in the second parameter of waveOutUnprepareHeader()

//OLD
result = waveOutUnprepareHeader(pCSound->outHandle, pCSound->WaveHeader[nBufferReturned], sizeof(WAVEHDR));
//NEW
result = waveOutUnprepareHeader(pCSound->outHandle, &(pCSound->WaveHeader[nBufferReturned]), sizeof(WAVEHDR));

Share this post


Link to post
Share on other sites
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][i] = 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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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][i] = 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 FREEZES
waveOutReset(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][i] = NULL;
}









//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][i] = 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.

Share this post


Link to post
Share on other sites
Could that be a problem? Each buffer is just large enough to fill one screen with samples. This makes graphing the data really easy, I just print the buffer to the screen when it returns. I will definately have to look into this though. I will try in the morning, thank you though, something tells me you might be right.

Dev578

Share this post


Link to post
Share on other sites
If the wave file is small enough why not use PlaySound() or sndPlaySound()?

As Mastaba indicated, buffer management may be your problem. I put together a little program that uses the Waveform-Audio Interface to play some sound. It includes source code and an sample program. Let me know if it helped.

It can be downloaded from here.
waveform_help.zip

Share this post


Link to post
Share on other sites
That was very helpful, thank you very much. The problem was the amount of buffers, anything over 8 can produce undesirable results. This then gave me the problem of graphing the wave in real-time. I just made my buffer size the screen size*4, and had 8 buffers (just to be safe). I just crammed the 4 screens worth of samples into one screen every time a buffer returned. It looks ok. I also liked the polling idea, so I did that as to avoid doing so much in the CALLBACKS. Thank you very much. Rating++;

Dev578

Share this post


Link to post
Share on other sites

This topic is 4300 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this