Sign in to follow this  

DS Buffer Duplicate - Multiple Buffers

This topic is 4596 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

I may be wrong but I've read that using the duplicatebuffer functions do not help in playing a single buffer multiple times at once. As you may know a buffer has a write/read pointer, when you play that pointer slides across the memory, since there is only 1 pointer you cannot play the same buffer twice at once. The solution is to check if it is currently playing and then play a copy of that sound buffer. I need to know which is the most effecient way of doing this, since DuplicateBuffer, stated on the MSDN will only sometimes create a buffer with new memory, most of the time the DuplicateBuffer will use the same memory location thus 1 pointer still thus the same problem. So, my solution is to at compile time tell each buffer if it needs copies of itself and create them before gametime. For example, a machine gun sound effect will need like 10 buffers to allow a user to fire constantly and hear multiple bullet shots at once. I have seen some programs which just check during gametime if a sound is playing and if it is then it will create a copy and play it, then release the copy. I find that very ineffiecent. If I was running, multiple footsteps may need to be played, thus a new buffer created every few frames, pointless CPU work. So em I correct by assuming multiplebuffers at game loadtime and loading the buffers into an array or is it better to have only one and duplicate it if necessary during a frame, or is a combination of the two the better way to go.

Share this post


Link to post
Share on other sites
I think you are confusing the pointer to the actual data buffer with the IDirectSoundBuffer8 pointer. It is the IDirectSoundBuffer8 that maintains the read/write pointer and buffer parameters. If you use DuplicateSoundBuffer(), you will get a new IDirectSoundBuffer8 that points to the same sound buffer, but with it's own read/write pointer and parameters.

From MSDN:
Quote:
Initially, the duplicate buffer will have the same parameters as the original buffer. However, the application can change the parameters of each buffer independently, and each can be played or stopped without affecting the other.


You should be able to use DuplicateSoundBuffer to play the same sound as many times as you want.

Share this post


Link to post
Share on other sites
I wasn't confused just my terminology was.
I have tried this method before tho and ended up with nothing. Although last time I tried it was Dx7 DirectSound.

A very simple GetStatus, if playing, duplicate buffer, play new buffer. The new buffer never makes a peep of noise :(

Share this post


Link to post
Share on other sites
When you duplicate the buffer, everything about the buffer is duplicated, including the current position. So, unless you reset the position to 0, it will play at the same point as the already playing buffer. It may just be that you don't hear anything because you now have two buffers playing at the same position.

I've used this method before and not had any problems with it. Generally, I never play the original buffer. I load the sounds up front and, whenever I need to play a sound, I duplicate the buffer for that sound and play the duplicate. When the duplicate is done playing, I release it.

Share this post


Link to post
Share on other sites
Given that the sound buffer data itself isn't actually duplicated the cost is quite minimal. It's like having 100 sprites sharing the same texture.

Share this post


Link to post
Share on other sites
Sorry for the little bump here but the problem is now being shown.

I just got around to attempting to play one buffer twice, nearly at once.

if (IsPlaying()) {
LPDIRECTSOUNDBUFFER pDestBuf = 0;
hr = cSoundLayer::Sound()->DuplicateSoundBuffer(m_pBuffer, &pDestBuf);
pDestBuf->SetCurrentPosition(0);
pDestBuf->Play(0,0,false);
pDestBuf->Release();
return true;
}

Nothing, not a peep.
any assistance? I know the original buffer works flawlessly.

Share this post


Link to post
Share on other sites
This may be a completely worthless reply (I'm good at these), but I'll try anyways.

Do you ever set the volume of any sound effects? If you use a 3D or 2D panning / volume calculation based on distance from the screen, the last sound played may have been out of range to hear it. If so, you may need to set all of the sound's properties when you duplicate it.

You don't seem to be checking the return value of DuplicateSoundBuffer. Are you sure it's succeeding? Seems like a crash would occur, but you never know.

You release the duplicate right after you duplicate it. Was this just for an example or test? I don't think you should even check to see if the original sound was playing if you plan to immediately release the duplicate. There's very little reason to ever play the original sound with your current setup. It might be that the original sound was not playing when you tested the second play. Of course I have no idea. Just tossing guesses at you.

Share this post


Link to post
Share on other sites
Well actually I am just fiddling with it, so that is my current setup but it is not to stay. I just wanted to see it work. So because I am fiddling I am not setting volume or panning. I have a 5sec wave file which I want to play twice over.

So I actually went and the only buffer I play when the sound is requested is the duplicate and it is 100% blank.

Also, when in break mode stepping through I confirmed that it is returning S_OK everytime or at least many 100's of times in a row...




Ugh, I had this exacty problem in DX7 DirectSound, the only solution was to create multiple buffers and use up extra memory... Saved repetitious Duplicatebuffer calls....

Share this post


Link to post
Share on other sites
WELL!

I hope someone replies to this for some help...

The fix was to not Release it right away obviously.
How and where should I wait to release it now???

Share this post


Link to post
Share on other sites
Actually, I just realized that you're releasing the duplicate right after you call play(). I don't think released duplicates keep on playing.

You need to wait until it's done before releasing it. What I do is just preallocate 8 duplicates for every sound, and keep an index of the last one played. Increase the index (but wrap back from 7) every time a sound is played. It allows up to 8 simultanious plays with no allocations and very little memory or processing.

edit: Oops, you beat me to it.

Share this post


Link to post
Share on other sites
I may have beat you to it but you gave me my solution.
I was already working on having 8 pre-ready buffers.

All I wanted was a tiny small play routine, I suppose at the cost of memory I could pre-allocate all the buffers I wanted and simplify the routines but thats all to think of when the game engine is created.

Optimization last, working product first!

Thanks for your help Jiia,
Halsafar

Share this post


Link to post
Share on other sites
Hmm would just declaring a new buffer and memcpying the original one to it work?

Well anyway, I while ago I tried this, I can't remember how i did it, but I remember that I got a really ugly echo effect when I tried it.

So I just either if in the same loop the sound played, I would get the average of the variables(eg position, velocity) and then play it with the average variables.

And if the buffer was playing in one loop, and in a couple later while its still playing, I would just reset its position to 0, and replay it with the new variables.

Let me know if you get your way working, as I might use that way aswell.

Share this post


Link to post
Share on other sites
Quote:
Original post by Halsafar
All I wanted was a tiny small play routine, I suppose at the cost of memory I could pre-allocate all the buffers I wanted and simplify the routines but thats all to think of when the game engine is created.


I don't think duplicates will cost you much memory. I'm thinking lower than the 100 byte range. I actually have no idea. But it should be just enough memory to store play positions, volume settings, and that sort of attributes.

Share this post


Link to post
Share on other sites
Hey because I'm now trying the same thing as you, I was wondering what the best way of removing the soundBuffers from the array.

Like I'm using a vector<dxsoundbuffer> to store the multiple buffers.
And when a buffer stops playing I want to remove it from the array list.

So say I've got 5 buffers in my arrayList, and buffer[1] has stopped playing, and I want to remove it from the array.

Would I just memcpy buffer[lastElement] to buffer[1] and then pop_back, the array?

Or would using pointers be better. Eg
delete buffer[1];
buffer[1] = buffer[lastElement];
buffer.pop_back();
?

Thanks

Share this post


Link to post
Share on other sites
You're probably hurting performance by releasing and allocating small duplicate space. Where if you just leave them alone, you get zero negative effects, other than a small memory cost. Unless you have thousands of sounds loaded or want a single sound to be capable of playing 32+ times simultaniously, there's really no reason to ever release them.

Just my opinion.

Share this post


Link to post
Share on other sites

This topic is 4596 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