0
0

Currently I’m trying to play 4 loops together synchronously.
Each loop has Channel::setPosition() called to start each loop slightly deeper into the same sound file. I then call playSound() on each loop consecutively. These 4 loops are all turned on or off depending on whether a particular button is being pushed. The group of 4 loops are triggered on and off on a regular basis.

This works fine (the 4 loops stay in sync) until the scene gets busy and lots of sounds are playing, at which point the initial playback of the loops will sometimes lose sync – i.e. I go to play the 4 loops, and some of them are perhaps delayed and have lost sync and I hear phasing effects etc. I’m not sure if this is a setPosition problem or a playSound one.

My question is – how can best ensure that these four loops never lose sync?

  • You must to post comments
0
0

Hi, your issue is probably due to playSound inaccuracies. Are you starting the channels paused and then unpausing them? That may help.

Alternatively, if you need more precision, I suggest you investigate the Channel::setDelay function. The FMOD_DELAYTYPE_DSPCLOCK_START delay type allows you to specify an exact starting time for a channel, as long as it is far enough into the future.

Ben

  • You must to post comments
0
0

Have you considered authoring a multichannel sound and using the channel mixer effect to cut channels in and out? With such an arrangement it would be impossible for the channels to get out of sync.

-jason

  • You must to post comments
0
0

I forgot to mention that the four loops are played in 3D at four different (but equidistant) points in 3D space. So unfortunately I don’t think a multichannel sound would work…interesting suggestion though.

I read another post where Brett suggested using lockDSP() and unlockDSP() to synchronise the playback of 2 loops. Would those functions be helpful here? How does locking the DSP help?

  • You must to post comments
0
0

[quote="grimus":2gvd7ulu]I read another post where Brett suggested using lockDSP() and unlockDSP() to synchronise the playback of 2 loops. Would those functions be helpful here? How does locking the DSP help?[/quote:2gvd7ulu]

They might be helpful. The lockDSP function pauses the mixer (which runs in a separate thread) so you can guarantee that the mixer doesn’t start playing some of your channels before you’ve started them all (this is what causes them to go out of sync):

[quote="FMOD Programmers API Win32":2gvd7ulu]Mutual exclusion function to lock the FMOD DSP engine (which runs asynchronously in another thread), so that it will not execute. If the FMOD DSP engine is already executing, this function will block until it has completed.
The function may be used to synchronize DSP network operations carried out by the user.
An example of using this function may be for when the user wants to construct a DSP sub-network, without the DSP engine executing in the background while the sub-network is still under construction.
[/quote:2gvd7ulu]

However, this can cause problems if you take too much time between lockDSP and unlockDSP:

[quote="FMOD Programmers API Win32":2gvd7ulu]Note that the DSP engine should not be locked for a significant amount of time, otherwise inconsistency in the audio output may result. (audio skipping/stuttering).
[/quote:2gvd7ulu]

I would recommend trying the Channel::setDelay method before trying the lockDSP method.

Ben

  • You must to post comments
0
0

I’m at the end of my tether, I’ve tried everything now.

We have 4 or 5 layers of audio, all loaded into ram, NOT streamed.

We have the volume effects across them all, none go below -59db (in case going virtual messes them up)

All wav’s are a multiple of each other in samples. The initial wav is rounded to 64 samples for ADPCM compression (ie, if first wav is 10 64 blocks, the next would be 20 64 blocks)

They are all in one event.

They are started in event->start(), which is wrapped in lockdsp/unlock dsp.

They go out of sync very quickly, what else can I physically do to make them not go out of sync? They seem to be find in the designer.

Other games use a similar system (Splinter Cell for example) what did you guys do differently to me? (can PM / email me – if you want too)

  • You must to post comments
0
0

Thanks Ben,
I forgot to mention that the setDelay() worked fine for me – that fixed our problem.

Thanks again!

  • You must to post comments
0
0

[quote="a1psx":b9n1jlpr]They go out of sync very quickly, what else can I physically do to make them not go out of sync? They seem to be find in the designer.
[/quote:b9n1jlpr]

Do you mean they start off in sync then go out of sync? This sounds a bit to me like you have optimize sample rate on maybe.

You really are trying to do it in the worst way though, stalling the main thread using lockdsp.
You should be creating a single interleaved file and playing it as a stream, they are locked together using this method.

  • You must to post comments
0
0

Here’s an idea we just came up with that doesnt require lockDSP.

  1. Call getEvent
  2. Call Event::setPaused(true).
  3. Call Event::start
  4. Call Event::getChannelGroup and then ChannelGroup::getDSPHead
  5. Call DSP::setActive(false) on the dsp pointer from step 4.
  6. Call Event::setPaused(true).
  7. Call DSP::setActive(true) on the dsp pointer from step 4.

Because the event system uses a for() loop with ordinary Channels, it can have the same problem of channels being started in one mixer thread update, then other channels in that loop starting on the next mixer thread update, just due to timing issues. LockDSP gets them all together so you dont get that problem but also causes a main thread stall.

The above method does the loop, but ‘pauses’ the channelgroup that the channels belong to, so they’ll never start until you do the final DSP::setActive(true) on the channelgroup’s dsp node, this way they’re guaranteed to all be in sync, because some channels wont start before the other.

Now this wont help ‘going out of sync over time’.
The reasons for this will be

  1. frequencies are different, ie optimize sample rate was turned on.
  2. sounds are not block aligned to the compression format’s native block size. This is because fmod stretches each the sound if they’re not block aligned and might stretch the sounds by different amounts so that they go out of sync.
  3. channels in the event went virtual then became real again. This should be avoided by setting a high priority before starting the channel, and making sure there are enough real voices available before starting the event. FMOD_INIT_VOL0BECOMESVIRTUAL can also make it go virtual.

We’re going to put the above setactive logic inside of a future version of Event::start, so that you dont have to do it yourself. This way we can guarantee all sounds start at exactly the same time when the event starts – with no extra code on the user side.

  • You must to post comments
0
0

[quote="brett":2v98a0t4]Here’s an idea we just came up with that doesnt require lockDSP.

  1. Call getEvent
  2. Call Event::setPaused(true).
  3. Call Event::start
  4. Call Event::getChannelGroup and then ChannelGroup::getDSPHead
  5. Call DSP::setActive(false) on the dsp pointer from step 4.
  6. Call Event::setPaused(true).
  7. Call DSP::setActive(true) on the dsp pointer from step 4.[/quote:2v98a0t4]

Is this process valid for the current code? If so, where are Events?

  • You must to post comments
Showing 9 results
Your Answer

Please first to submit.