I have been searching for days on google and through the FMOD documentation. I have not been able to find a clear answer on this so far.
I’m looking into doing adaptive music, but the problem is that the number of potential channels is absolutely massive (currently 70 and growing). However, we only need a few channels loaded in at once; usually 2-3, but they can be in any combination.
The solution we were thinking of is to [b:ift1hwzm]save each channel to a .wav file, then load in the needed channels at runtime and combine them into a single sound[/b:ift1hwzm], and then we can raise and lower the channels of that new sound to do the blending. I would like to know if there is any easy way to do this.
The [b:ift1hwzm]other alternative is actually our preferred option[/b:ift1hwzm], but I have not been able to find any claims on its reliability. We could load each wav file as a separate sound and play them at the same time. The problem is that [b:ift1hwzm]we need these sounds to be perfectly synced at all times (as if they were a single sound playing on a single channel)[/b:ift1hwzm].
Because of potential audio latency, I know that just playing the two sounds at the same time is not enough. Can someone please give some pointers on what functions could be used to accomplish these?
Thanks in advance.
- Beta_Carotene asked 5 years ago
Your second (and preferred option) will work. FMOD will have no problem keeping all the channels in sync. However you must make sure they are all started at exactly the same time (in terms of the mixer clock). You can do this by calling System::lockDSP(), calling N x System::playSound(), then calling System::unlockDSP().
Another way to sync the start time without blocking the mixer thread would be:
unsigned int clockhi, clocklo;
unsigned int blocksize;
FMOD_64BIT_ADD(clockhi, clocklo, 0, blocksize * 2); /* Push operation into the future by 2 mixer blocks. */
for (int i =0; i < NUM_SOUNDS; i++)
system->playSound(FMOD_CHANNEL_FREE, sounds[i], true, &channels[i]);
channels[i]->setDelay(FMOD_DELAYTYPE_DSPCLOCK_START, clockhi, clocklo);
All the channels are scheduled to start at the same time, and that time is far enough in the future that you’ll be certain that your loop has finished and all channels are added to the mixer before the clock reaches that point.
System::getDSPClock, Channel::setDelay() and Channel::getDelay() are the functions you need to become familiar with for syncing channels.
Thanks so much Nick! That’s fantastic help and exactly what I needed.
I always prefer to keep things as simple as possible, so [b:2jjpiybo][u:2jjpiybo]in what situations could blocking the mixer harm me[/u:2jjpiybo][/b:2jjpiybo]? I would suspect that it would defer the playing of other sounds as well? I think I read something about that causing stuttering but I don’t fully recall.
Having only the setPaused inside the lock will have the desired effect.
The risk of blocking the mixer for too long is that the output could stutter. What constitutes "too long" is hard to say. It depends on factors such as the size of the system DSP buffer (System::[get|set]DSPBuffer) and how long each mix is taking (use System::getCPUUsage and look at the DSP value).
Please login first to submit.