Sign in to follow this  
HugosHoH

Streaming to DS buffer!

Recommended Posts

HugosHoH    100
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; } }

Share this post


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

Share this post


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

Share this post


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

Share this post


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

Share this post


Link to post
Share on other sites

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