I’m working on a rhythm game and am looking for ways to reduce sound effect playback latency as much as possible. Any latency at all decreases the game’s "rhythmic" feeling, so I’m looking for tips on how to reduce latency.
So far, from searching the forums, I have discovered:
- Playing with the values passed to setDSPBufferSize can reduce latency (at a cost of increased CPU usage and possible stuttering)
- Using an ASIO driver can help on Windows (my main target is Windows)
A few questions:
- How can you detect and use an ASIO driver if present? Check if the driver name has "ASIO" in it? If so, you might accidentally get the ASIO4ALL driver which is not true ASIO and, on my machine, is crappy and has high latency
- Is there anything else I can do to reduce latency? Any way to play sounds or load them that will help? Could I perhaps load ALL the sounds and PAUSE them and unpause when needed? Would that help?
Thanks for any insights!
- Ryan Clark asked 3 years ago
We recently switched to FMOD from OpenAL expecting better performance, but testing seems to indicate slightly higher latency (~20ms) on average on a variety of test machines. I was expecting the opposite, so I’m wondering if somehow I’m missing something.
I’ve been using FMODEx for years, playing and loading the sounds the "usual" way as shown in the examples. This is the first game I’ve made that requires low latency however, so I’ve tried messing with the setDSPBufferSize and driver settings for the first time, but am still getting more latency with FMOD than OpenAL.
Any help would be greatly appreciated! I don’t want to have to return to OpenAL! 😮
A couple of ideas:
– First, make sure that you’re using software sounds and not hardware. Software will give you better results anyway on Windows. Pass in FMOD_SOFTWARE when you create the Sounds.
– I’m not sure how to detect a true ASIO driver as compared with ASIO4ALL, but using ASIO is definitely one of the things I’d suggest. The FMOD guys may have more ideas on the subject.
– Not also that the ASIO output type will adjust the System DSP Buffer Size to be optimal for that driver, so fiddling with DSPBufferSize on ASIO may actually be detrimental
– If you’re playing back your sounds as streams, you can also try fiddling with System::setStreamBufferSize() to see if there’s any improvement in latency
– Also for streams, you can try fiddling with the defaultDecodeBufferSize in FMOD_ADVANCEDSETTINGS (System::setAdvancedSettings()) and see if it gets you better results
The FMOD folks are usually pretty good about responding on the forums, but if you’re still struggling with this, I heartily encourage you to contact them at firstname.lastname@example.org, where they are helpful, polite, and prompt!
Hope that helps!
Thanks so much for your help, Adiss! A few questions:
Why would using software be faster than hardware? I would assume that hardware would be faster as the data is already on the sound card and has less "distance" to travel? I’ve tried it just now and I’m not seeing any difference in latency on my machine, but I’ll continue to use FMOD_SOFTWARE based on your advice, in case it helps on other machines
Is there any way to perform automated (and silent) latency testing? (I don’t want to require that the user play a sound and record that sound using a microphone.) Can I do something like play a sound (with zero volume) and ask FMOD when it has actually started playing by checking FMOD_Channel_GetPosition? Would that work? It would be great to be able to remove human error from the latency calculations (I’m currently using a "Guitar Hero"-like manual calibration where the user has to hit a key every time they hear the sound, and then average the returned values. I do something similar to calculate video [+input] latency.)
Thanks again for your help!
one good way to remove latency is to set the software mixer to be the same sample rate as the sound card, so it removes the resampler. The resampler has a double buffer so is a DSP buffer’s word of latency added.
use getDriverCaps and setSoftwareFormat to do this.
just FYI FMOD_HARDWARE is now only supported on consoles like 3ds, ps2, wii, wiiu, psp that I can think of, any other platform will ignore FMOD_HARDWARE and use FMOD_SOFTWARE anyway, especially windows – it stopped supporting hardware in Vista anyway – and the overhead of directsound in XP was slower than just using FMOD_SOFTWARE and cpu mixing in the end, it really was pointless to support it – that’s what adiss would be talking about anyway.
Thanks very much, Brett! Just to make sure that I’m doing this correctly, you’re suggesting that I take the [b:37ny4nu5]controlpaneloutputrate[/b:37ny4nu5] parameter from getDriverCaps and pass it as the [b:37ny4nu5]samplerate[/b:37ny4nu5] parameter of a subsequent setSoftwareFormat call? And I just pass the rest of the parameters as the defaults?:
setSoftwareFormat(samplerate, FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR);
Is that correct?
Also, can you comment on how best to use ASIO? If I call FMOD_System_SetOutput(FMOD_OUTPUTTYPE_ASIO) on my machine, it uses ASIO4ALL and I actually get no output from my speakers! Should I just check to see if, via getDriver, the system is using something with "4ALL" in the driver name and if so, not use ASIO on that machine? Is it otherwise normally safe to use FMOD_System_SetOutput(FMOD_OUTPUTTYPE_ASIO)?
Thanks again for your help!
yes the getdrivercaps controlpaneloutputrate is right, and you would pass it to setSoftwareFormat. Your code looks right.
ASIO support uses the settings and device as set by the asio configuration outside of fmod.
FMOD comes with a little tool called asioconfig.exe which just pops up the device asio config dialog, that you can use to set the right output channel mapping and device settings, that is probably not set up correctly.
Because the user usually needs to do this sort of thing (if they used asio they might know what theyre doing, but its not a general use case for the install base) its not that recommended as a general solution. WASAPI should be as low latency as ASIO really, and less driver dependant.
Thanks for all this great info, Brett. I’ve tried everything you’ve mentioned, and still seemed stuck at about 100ms latency on my crappy sound card. (And was still getting slightly poorer latency on other machines with FMOD than with OpenAL.) Then I tried using FMOD_INIT_WASAPI_EXCLUSIVE and it cut the latency in half!
So is it safe to use FMOD_INIT_WASAPI_EXCLUSIVE on Windows? The docs say it only works on Vista, but it was working fine on my Win 7 machine. Are there any drawbacks to using it, other than the fact that it denies other applications the ability to output sound? Since my application is so latency sensitive, I think this is ok as long as I give the user the option to disable this.
FMOD folks will have more thoughts on the ins and outs of exclusive wasapi output. My gut says that, so long as you’re fine with the restrictions, then there shouldn’t be any drawbacks.
I can, however, speak to the Vista requirement. The statement should read that it’s supported on Vista and up (that is, Vista, Win7, Win8, Win8.1, and higher). More precisely, it is NOT supported on Windows XP or lower, so if you’re targeting that audience, then you’ll need a fallback.
That is helpful, Adiss! Thank you.
So should I just attempt to set FMOD_INIT_WASAPI_EXCLUSIVE and if FMOD returns an error, then just init normally? Or will FMOD not even return an error on unsupported systems?
btw, if you’d like a free pre-order copy of our game as thanks for your help, just contact us via our website: http://necrodancer.com
Please login first to submit.