Author Topic: iOS: Avoiding device dropouts  (Read 73 times)

elan

  • Posts: 53
iOS: Avoiding device dropouts
« on: 6 Jan '21 - 18:44 »
We're running into a case where audio is glitching on iOS (super briefly) when we're doing heavier-than-normal processing in our app. A few details:

- We have an always running mixer.
- We're watching BASS_SYNC_STALL on the mixer.
- We're watching with BASS_SYNC_STALL on each channel into the mixer with BASS_Mixer_ChannelSetSync
- We're not seeing any underflows so it seems like an issue with the lower level audio buffers underflowing (I'd guess, at least).

We're trying to play with different options on the device to adjust buffer size, without much luck.

- BASS_CONFIG_DEV_PERIOD: Affects time interval between buffer updates, and thus buffer size (I'm guessing total buffer = period * 2). For example, when I set it to 20, the latency is reported as 43ms and the period is rounded up to 22ms. If I set it to 50, latency is reported as 75ms and period 43ms. If I set it to 100, latency is reported as 139ms and period 86ms. This seems to be the maximum allowed, as if I move it to 200, the latency/period don't change any more.
- BASS_CONFIG_BUFFER: I think this only affects BASS streams, so given that we're not seeing underflow probably not the issue. Same with BASS_CONFIG_MIXER_BUFFER.

So I guess my questions are: (1) Are these all the knobs we have? (2) Does it make sense that the maximum latency is 139ms? (3) Anything else I can do to diagnose/improve?

Ian @ un4seen

  • Administrator
  • Posts: 23288
Re: iOS: Avoiding device dropouts
« Reply #1 on: 7 Jan '21 - 17:08 »
If you're getting dropouts without any STALL syncs being triggered then that could mean iOS is struggling to generate the device's output mix quickly enough or BASS is struggling to generate its output mix. I think the latter is more likely (the former is likely to have the highest CPU priority). If you monitor the BASS_GetCPU value, does that show a spike when the problem occurs? Does raising BASS_CONFIG_DEV_PERIOD help at all? There will be a limit to how high iOS allows it. Also, do you happen to have disabled buffering on the mixer by setting BASS_ATTRIB_BUFFER to 0 on it? That will give much less margin for any delays in processing, so you should probably enable asynchronous file reading then too (set BASS_ASYNCFILE on the mixer sources).

Mixers are currently single-threaded, which means they mix one source as a time. If your mixer may be playing many sources at a time then you could give the latest BASSmix build a try, which adds a multi-threaded mixing option:

   www.un4seen.com/stuff/bassmix-ios.zip

The new BASS_ATTRIB_MIXER_THREADS option sets the number of threads for a mixer to use. For example, you can tell a mixer to use 2 threads like this:

Code: [Select]
BASS_ChannelSetAttribute(mixer, BASS_ATTRIB_MIXER_THREADS, 2);

elan

  • Posts: 53
Re: iOS: Avoiding device dropouts
« Reply #2 on: 7 Jan '21 - 21:51 »
Raising BASS_CONFIG_DEV_PERIOD may have helped a bit, but the problem remained even after I raised it to the highest level allowed by iOS.

We are using BASS_SetConfig(BASS_CONFIG_MIXER_BUFFER, 200) before creating the mixer stream, which I think answers your question around BASS_ATTRIB_BUFFER. And we did enable BASS_ASYNCFILE on the decode streams.

We're usually only processing a single active stream, except for a few seconds between tracks where we're mixing current + next, so it's probably unlikely the multithreading would help.

Ian @ un4seen

  • Administrator
  • Posts: 23288
Re: iOS: Avoiding device dropouts
« Reply #3 on: 8 Jan '21 - 16:40 »
The BASS_CONFIG_MIXER_BUFFER option won't be affecting this. That just determines how much data is kept from sources, so that it's available for BASS_Mixer_ChannelGetData/Level calls. It isn't a prebuffering option. A mixer won't ever prebuffer data from its sources, ie. the mixer fetches data from sources only as needed. That's why disabling playback buffering on a mixer (BASS_ATTRIB_BUFFER = 0) gives little margin for any processing delays, ie. all sources need to be decoded and mixed within a device update cycle (BASS_CONFIG_DEV_PERIOD).

It is possible to add source prebuffering by using splitter streams with async buffering enabled via the BASS_ATTRIB_SPLIT_ASYNCBUFFER option. The data flow would be: source -> async splitter -> mixer. Please see the BASS_ATTRIB_SPLIT_ASYNCBUFFER documentation for details on that.

Also try monitoring the BASS_GetCPU value and also the mixer's BASS_ATTRIB_CPU value (with BASS_ChannelGetAttribute), to help confirm if the problem is slow/delayed processing, ie. are they spiking when the problem happens?

Another thing to ask is if you really need the mixer, ie. could you use normal playback channels instead? If it's for saving/encoding the mix with BASSenc, make sure you have the BASS_ENCODE_QUEUE flag set on the encoder to avoid delays.