I’m currently evaluating FMOD for use in a game with partial success. However on one of my test devices, a Sony Ericsson Xperia V, the sound latency is unacceptable. I can confirm this with the example projects, such as "playsound". By running this example on the Xperia and a Nexus 4 side by side, it’s clear that the sound is noticably delayed on the Xperia, perhaps by as much as half a second (no scientific measurements done, just tapping buttons simultaneosly and listening).
The Xperia runs Android 4.1, whereas the Nexus 4 runs 4.3. I do not, however, see that as a reason for the different performance. I have run other games on the Xperia that do not exhibit such sound latency.
Can anyone offer any advice on this matter? As noted above I refer to FMOD’s own example projects for reproducing the problem.
- toreolsensan asked 4 years ago
This is a very old thread however much of it is still relevant.
When tackling latency we try to determine which output interface will give the best results. For some devices this selection isn’t optimal. One setting that can help is System::setOutput, configured with FMOD_OUTPUTTYPE_OPENSL.
@Howu: I’ll follow up directly via e-mail to discuss profiling your specific hardware.
Latency on Android is a pretty serious issue, we provide methods to control the latency added by FMOD but ultimately the lions share of latency comes from the OS and hardware.
Firstly, I would recommend using the AudioTrack output mode: System::setOutput(FMOD_OUTPUTTYPE_AUDIOTRACK), this generally has the lowest latency for everything but the newest of devices. Next I would try System::setDSPBufferSize, it takes two parameters, dsp buffer size (which represents the granularity of our mixer) and dsp num buffers which is multiplied against the buffer size to create the audio ring buffer. If you are using AudioTrack, try 2 buffers of 512 size, that should help some of the latency.
You can adjust the buffer size (and number thereof) how you like, however be aware that setting the value too low you will get stuttering, too high you will get unnecessary latency.
I made the following additions to playsound’s main.c:
result = FMOD_System_SetOutput(gSystem, FMOD_OUTPUTTYPE_AUDIOTRACK); CHECK_RESULT(result); result = FMOD_System_SetDSPBufferSize(gSystem, 512, 2); CHECK_RESULT(result);
When I launch the project, the following is logged:
FMOD: AudioDevice::run : Min buffer size: 12288 bytes
FMOD: AudioDevice::run : Actual buffer size: 12288 bytes
If I don’t select AudioTrack, there is no such warning, but the buffer setting doesn’t help with the latency.
Now I’ve tried the playsound example on several phones. On the devices I have that are running Android 2.x the latency is similar to the Xperia, i.e no good. I tried on the following Android 4.x devices: LG Nexus 4, Samsung Galaxy Nexus and SE Xperia V. The Xperia is on par with Android 2.x while the others are ok.
I realize that Android traditionally has had poor audio latency. However, Hill Climb Racing, which I the benchmark game which I’ve tried on all my devices, has much better performance than I’m able to get using FMOD both in my app and using the examples. Do you have any other tips?
It looks like the hardware is requesting a buffer of 12288 bytes, which is 3072 samples.
You might be able to improve that number by using a higher sample rate, depending on the logic the hardware is using to calculate the minimum size. This would increase CPU usage though.
Could you try System::setSoftwareFormat setting the sample rate to 48000 and report back the min buffer size?
So, introducing the following lines after FMOD_System_Create:
result = FMOD_System_SetSoftwareFormat(gSystem, 48000, FMOD_SOUND_FORMAT_PCM8, 0, 0, FMOD_DSP_RESAMPLER_LINEAR); CHECK_RESULT(result);
(I did experiment with various sound formats, PCM16 gave the same results)
So this made AudioDevice::run report a larger buffer, which given the higher sample rate should cause the same number of samples and the same latency.
The Xperia syslog is very chatty, and interestingly the ALSA driver seems to override the buffer size later on, perhaps you can make some sense out of this?
10-07 08:23:32.799: I/fmod(4277): FMOD: AudioDevice::run : Min buffer size: 24576 bytes
10-07 08:23:32.799: I/fmod(4277): FMOD: AudioDevice::run : Actual buffer size: 24576 bytes
10-07 08:23:32.799: D/PowerManagerService(609): acquireWakeLock flags=0x1 tag=AudioOut_2
10-07 08:23:32.819: D/ALSADevice(263): route: devices 0x2 in mode 0
10-07 08:23:32.819: D/alsa_ucm(263): snd_use_case_set(): uc_mgr 0x400f1fb8 identifier _enadev value Speaker
10-07 08:23:32.819: D/ALSADevice(263): switchDevice: mCurTxUCMDevivce None mCurRxDevDevice Speaker
10-07 08:23:32.819: D/alsa_ucm(263): snd_use_case_set(): uc_mgr 0x400f1fb8 identifier _verb value HiFi
10-07 08:23:32.819: D/alsa_ucm(263): Set mixer controls for Speaker enable 1
10-07 08:23:32.819: D/alsa_ucm(263): acdb_id 263 cap 1 enable 1
10-07 08:23:32.819: D/ACDB-LOADER(263): ACDB -> send_audio_cal, acdb_id = 263, path = 0
10-07 08:23:32.819: D/ACDB-LOADER(263): ACDB -> send_adm_topology
10-07 08:23:32.819: D/ACDB-LOADER(263): ACDB -> ACDB_CMD_GET_AUDPROC_COMMON_TOPOLOGY_ID
10-07 08:23:32.819: D/ACDB-LOADER(263): ACDB -> send_audtable
10-07 08:23:32.819: D/ACDB-LOADER(263): ACDB -> ACDB_CMD_GET_AUDPROC_COMMON_TABLE
10-07 08:23:32.819: D/ACDB-LOADER(263): ACDB -> AUDIO_SET_AUDPROC_CAL
10-07 08:23:32.819: D/ACDB-LOADER(263): ACDB -> send_audvoltable
10-07 08:23:32.819: D/ACDB-LOADER(263): ACDB -> ACDB_CMD_GET_AUDPROC_GAIN_DEP_VOLTBL_STEP_COPP
10-07 08:23:32.819: D/ACDB-LOADER(263): ACDB -> AUDIO_SET_AUDPROC_VOL_CAL
10-07 08:23:32.819: D/ACDB-LOADER(263): ACDB -> AUDIO_SET_AFE_CAL
10-07 08:23:32.819: D/alsa_ucm(263): Setting mixer control: SLIM_0_RX Channels, value: Two
10-07 08:23:32.819: D/alsa_ucm(263): Setting mixer control: RX3 MIX1 INP1, value: RX1
10-07 08:23:32.829: D/alsa_ucm(263): Setting mixer control: RX3 MIX1 INP2, value: RX2
10-07 08:23:32.829: D/alsa_ucm(263): Setting mixer control: LINEOUT1 Volume, value: 100
10-07 08:23:32.829: D/alsa_ucm(263): Setting mixer control: RX3 Digital Volume, value: 68
10-07 08:23:32.829: D/alsa_ucm(263): Set mixer controls for HiFi enable 1
10-07 08:23:32.829: D/alsa_ucm(263): Setting mixer control: SLIMBUS_0_RX Audio Mixer MultiMedia1, value: 1
10-07 08:23:32.829: D/ALSADevice(263): close: handle 0x41af4100 h 0x0
10-07 08:23:32.829: D/ALSADevice(263): open: handle 0x41af4100
10-07 08:23:32.829: E/ALSADevice(263): Music case
10-07 08:23:32.829: D/ALSADevice(263): Device value returned is hw:0,0
10-07 08:23:32.829: D/ALSADevice(263): setHardwareParams: reqBuffSize 2048 channels 2 sampleRate 48000
10-07 08:23:32.839: D/ALSADevice(263): setHardwareParams: buffer_size 16384, period_size 2048, period_cnt 8
It looks like the hardware wants a 128ms buffer regardless of the sample rate, unfortunately there isn’t a lot that can be done here. One method to try and hide the latency is by delaying the visuals to reduce the gap between the two, this won’t help much for audio on input actions but may help the overall feel of the game.
Other games might be using native APIs like SoundPool, while limited in functionality I believe provide lower latency. For FMOD our final output is a stream so we require AudioTrack to push our data out, even with our buffering quite low (512 samples * 2 in this case) the OS latency eclipses it.
Sorry I don’t have better news, if there were a way to reduce latency on Android I’d be more than happy to implement the necessary changes to get it.
Other Android Devices such as LG G6 and G5, Samsung Galaxy S7 also have this latency issue.
Only Google Pixel phone has no latency.
This link below is my test.
I’m also researching this issue, but DSP Buffer length and DSP Buffer count is not an answer.
FMOD should consider an easier solution to figure out this issue, I think.
Please login first to submit.