Streaming to DS buffer!

Started by
3 comments, last by HugosHoH 16 years, 6 months ago
Hello, This is my elementary streaming code to a DirectSound buffer. It plays the track ok but with glitches and in consistency at certain periodic points. Could you guys help me figure out where the source of the problem? Hope my code is clear enough. void CSoundDevice::Stream(int sndname) const { static unsigned int s = m_dsbArray.at(sndname)->size; // total dsb size static unsigned int r = 0; // refill position static unsigned int c = m_pcmCacheArray.at(sndname)->numBytes; // bytes left to stream static unsigned int pd = 2 * m_dsbArray.at(sndname)->bytesPerSec; // 2 sec threshold value after which start refilling the buffer static DWORD p0 = 0, p1; static unsigned int k = s, a = 0; m_dsbArray.at(sndname)->buf->GetCurrentPosition(&p1, NULL); if (p1 - p0 < 0) { a += (s - p0 + p1); } else { a += (p1 - p0); } p0 = p1; if (a >= s - pd) { CopyPcmCacheToDsb(m_dsbArray.at(sndname), m_pcmCacheArray.at(sndname), r, k, s - pd); r += (s - pd); r %= s; k += (s - pd); k %= c; a = 0; //c = 0; } }
Advertisement
GetCurrentPosition() is a really bad way to check the buffer position. First, it's rarely correct (Which is probably causing the stuttering), and second it's expensive to constantly poll the buffer.

You should really set up notifications, typically you create one in the middle of the buffer, and one at the end, then you fill in the half of the buffer before the notification when it's signalled. That also works really well for a multithreaded solution.
Thanks.

But it's advised by several resources not to count on notifications as they are not reliable in a sense that the HW may not accurately set them.

Regardless from being expensive to poll the play position, is it accurate enough even with a padding distance I have here which is 2 seconds before the end of the recently updated data?
Quote:Original post by HugosHoH
But it's advised by several resources not to count on notifications as they are not reliable in a sense that the HW may not accurately set them.

Regardless from being expensive to poll the play position, is it accurate enough even with a padding distance I have here which is 2 seconds before the end of the recently updated data?
Yup, although there's very little reason to use hardware buffers for streaming buffers. The CPU cost really isn't an issue, and notifications work perfectly.

Is there a reason you're using static variables? You know that if m_dsbArray.at(sndname)->size, m_pcmCacheArray.at(sndname)->numBytes or m_dsbArray.at(sndname)->bytesPerSec ever changes during the course of the program, that they won't be updated in this function? If they change you'll need to terminate your exe and start it again to reset them.

Have you created the buffer with the DSBCAPS_GETCURRENTPOSITION2 flag? That makes GetCurrentPosition() much more accurate.
Yes created with this flag. Static vars because the streaming func is called frequently every frame, and i need to preserve the value of these vars.

The idea is to refill part of the buffer which is DS buffer size - padding threshold, when the no. of bytes played is equal or greater than the currenly filled size - padding. And this occurs in a circular manner in both DS buffer and pcm cache.

This topic is closed to new replies.

Advertisement