DirectSound

Started by
5 comments, last by blaze02 17 years, 9 months ago
I've almost got this thing complete. I have a thread that helps me count how many times a buffer has been played. I'm using the DirectSound Notification system, each buffer has its own event created with CreateEvent and manaul reset is set to TRUE. So every 1/10th of a second, my thread gathers up all the events that are associated with buffers that are repeating. If the event is signal'd, the buffer's repeat count is decremented. And now for my favorite 4 words: "Everything works fine... except" When multiple sounds are playing at once, it seems as though one buffer's event gets signal'd when another buffer's event should be. I've spent the last 48 hours making sure I was passing a valid event handle, and making sure the event was the same as the one originally tied to the buffer and used for SetNotificationPositions. Any ideas? Edit: So this is the closest I've come to figuring this out. I changed the thread so that it waits on ALL the handles, even if the sound isn't currently playing. The I call WaitForMultipleObjects. I check the return value to determine which event was signal'd. The return value is zero (telling me that the handle at index 0 was signal'd). Its on manual reset, so if I don't call ResetEvent on the event at index 0, it repeatedly breaks the WaitForMultipleObjects (as you would expect). So the problem is: The event at index 0 is getting signal'd by the DirectSound notification system. The buffer, that this event is associated with, is not playing. The event associated with the playing buffer is playing, but only 20% through the buffer (all events are set at buffersize - 1). Can somebody at least verify that WaitForMultipleEvents returns the index of the handle that was signal'd? I mean, i know MSDN says it does... I just don't understand how any of my events can be signal'd unless DirectSound's notification system does it. In which case, I want to know why and when. [Edited by - blaze02 on June 25, 2006 2:40:25 PM]
-------Harmotion - Free 1v1 top-down shooter!Double Jump StudiosBlog
Advertisement
Hi man,

i had THE SAME PROBLEM two days ago. I was implementing audio streaming with DirectSound and I have used buffer notifications and WaitForMultipleObjects function to wait for them.

If only one sound was streamed everything worked fine, until i tried to stream second sound. After creating second sound buffer for streaming and setting notification positions for this buffer I immediatelly began to receive notifications for second buffer even when it was not playing. And even worse - i was notified for some buffer positions more often than for some other positions.

I have lost one day with this issue and after that i decided to do not use notifications at all. I just use GetCurrentPositon to determine buffer play position and I am calling update each 20ms for each streamed sound to fill new data. Everything works fine and I can stream many sounds at one moment without any problems.

Solution: Do not use DirectSound notifications.
Quote:Original post by UBrothers
Hi man,

i had THE SAME PROBLEM two days ago. I was implementing audio streaming with DirectSound and I have used buffer notifications and WaitForMultipleObjects function to wait for them.

If only one sound was streamed everything worked fine, until i tried to stream second sound. After creating second sound buffer for streaming and setting notification positions for this buffer I immediatelly began to receive notifications for second buffer even when it was not playing. And even worse - i was notified for some buffer positions more often than for some other positions.

I have lost one day with this issue and after that i decided to do not use notifications at all. I just use GetCurrentPositon to determine buffer play position and I am calling update each 20ms for each streamed sound to fill new data. Everything works fine and I can stream many sounds at one moment without any problems.

Solution: Do not use DirectSound notifications.


Son of a bitch. I've lost at least 48 hours on this. I don't know whats going on. My backup plan is to keep using the notification system, but verify (after the event is signal'd) that the sound buffer is at a valid position. Depending on the speed of the updates and the length of the sample, I will make sure the buffer is at least 90% played before incrementing my loop counter.

Well, thanks a ton for at least verifying my theory.
-------Harmotion - Free 1v1 top-down shooter!Double Jump StudiosBlog
Yes verification of current play/write position can be a solution (I have used it too and it worked well), but since this experience, that notifications do not work right, i can not be absolutely sure, that there will be no more problems with them.

Why do you must use notifications - i think, that it is no problem to get rid of notifications and use GetCurrentPosition call instead.

btw. Audiere library does not use notifications for streaming also. I think, that there a reason for this :-)
Quote:Original post by UBrothers
Why do you must use notifications - i think, that it is no problem to get rid of notifications and use GetCurrentPosition call instead.


If I don't use notifications, I'll be polling my current position more often than I need to. And how often should the thread poll the current position? What should I consider the end of the buffer? Notifications will alert my thread when the last byte has been read and played. If I poll every x milliseconds, I surely won't get lucky enough to get the exact end of the buffer. So I have to make a threshold for the end, how much should that be?

I've been around and around on all of this. My main concern is the framerate of the polling thread. There may be a slowdown in the system, causing the thread to only get updated once a second, then the code without notifications will go to shit. Granted, the thread will most likely never drop below 20 times per second, but it is a cause for concern.

I've told myself to ALWAYS assume its my code that is at fault. That makes it easier to track down bugs, because there aren't any in the STL, and until now, I'd say there weren't any in DirectX (at least not in the stuff I was using, maybe a few specific driver bugs). But I'm starting to assume this is a problem in DirectSound.
-------Harmotion - Free 1v1 top-down shooter!Double Jump StudiosBlog
You are right that it is not very clear to use GetCurrentPosition to detect if last byte has been played. But notifications are not very exact also. You will never receive notification at the very exact cursor position that you want - it will always be little later (i have tested this) and i think (somebody correct me if i am wrong), that notifications in directsound are implemented with pooling GetCurrentPosition also. I am using separate thread for this (which is independent of framerate).

One more thing - do you think, that GetCurrentPositon call is slow ? I think not and it is ok, to call it for example each 20 milliseconds. (but i may be wrong).

I thought same as you, that there can not be such problems in DirectX, but after this I am more skeptic. (But this can be a driver issue too)
Quote:Original post by UBrothers
You are right that it is not very clear to use GetCurrentPosition to detect if last byte has been played. But notifications are not very exact also. You will never receive notification at the very exact cursor position that you want - it will always be little later (i have tested this) and i think (somebody correct me if i am wrong), that notifications in directsound are implemented with pooling GetCurrentPosition also. I am using separate thread for this (which is independent of framerate).

One more thing - do you think, that GetCurrentPositon call is slow ? I think not and it is ok, to call it for example each 20 milliseconds. (but i may be wrong).

I thought same as you, that there can not be such problems in DirectX, but after this I am more skeptic. (But this can be a driver issue too)


The call to GetCurrentPosition does not take much time. I'm sure the sound buffer just keeps the variable and all you do is access it. But after you poll once, you will most likely need to Sleep and give up the CPU. The problem is that you might not get control of the CPU in 20ms. The OS has a bunch of threads running already, and our game could be hogging a lot of resources at the time.
I don't think notifications poll the current position. I have to think they programmed it smarter than that :) I could be wrong though.
Yeah, you are right about not getting the notification until the buffer is a couple ms past where you want it to be. I was worried about that before. To handle it, if the sound is looping and its on the last repeat, I stop it and play it again without the looping argument. Then I stop checking the signal'd event on that buffer, because it will stop on its own. Of course I have to ResetEvent before playing any sound because the event will most likely be signal'd before playing.

So I added this little snippet to the right after my call to WaitForMultipeObjects and everything seems to work fine:

(I'm probably not going to tag this code the right way)
[source language="c++"]				DWORD currenttime;		//ms since the start of the buffer				DWORD currentposition;	//bytes into the buffer				bool NOTIFICATION_VERIFIED = false;				soundengine->soundsamples[bufferindex].soundbuffer->GetCurrentPosition(&currentposition, 0);				if (currentposition >= soundengine->soundsamples[bufferindex].buffersize - 1)				{					NOTIFICATION_VERIFIED = true;				}				else				{					//get current time in ms					currenttime = (currentposition * 1000) / soundengine->soundsamples[bufferindex].bytespersec;					//this thread updates every JSTHREAD_UPDATE ms, so we can't be too far into the buffer					if (currenttime <= JSTHREAD_UPDATE)						NOTIFICATION_VERIFIED = true;				}


Where JSTHREAD_UPDATE is 100. If no sounds are repeating, I sleep(100). If notifications need to be checked, I waitformultipleobjects for 100ms. So hopefully this will be updated every 100ms. Which should cause no problem unless sound samples are small, say 300ms or less. I may drop it to 20-50 ms update, it all depends on the length of the samples.

Edit: nope, didn't tag it right the first try.

Edit2: Oh yeah, and I was going to say that I don't like notifications because they are exact (as you said, they aren't). But I like them because they are guaranteed (except for the bugs, haha). No matter how low the framerate or poll rate drops, the notification will still be signal'd.
-------Harmotion - Free 1v1 top-down shooter!Double Jump StudiosBlog

This topic is closed to new replies.

Advertisement