Author Topic: mp3 Playback Latency  (Read 578 times)

jimtompkins

  • Posts: 15
mp3 Playback Latency
« on: 17 Oct '22 - 16:53 »
Hi,

I'm trying to integrate BASS into a Flutter app for iOS (and eventually Android).  See https://github.com/JimTompkins/flutter_bass for the repo.  The example app has 4 buttons: init BASS, get the version, load a sample from an mp3 file, and play the sample.

I measured the playback latency by using another phone to record while I click the "play" button.  I'm measuring about 135ms from button push to playback starting.   This includes the time for the Flutter code to detect the button push and call the BASS_ChannelPlay function as well as what's happening inside BASS.  For comparison, I'm able to achieve about 70ms using a Flutter package called soundpool, and about 20ms on Android.

My code is pretty simple:
Code: [Select]
BASS_Init(-1, 44100, 0, 0, 0);
...
cowbellSample = BASS_SampleLoad(0, fileName, 0, 0, 1, 0);
...
cowbellChannel = BASS_SampleGetChannel(cowbellSample, 0);
...
result = BASS_ChannelPlay(cowbellChannel);

How can I reduce this playback latency?  By using a different audio file format?

Thanks for any hints!

Ian @ un4seen

  • Administrator
  • Posts: 25460
Re: mp3 Playback Latency
« Reply #1 on: 17 Oct '22 - 17:57 »
BASS_SampleLoad pre-decodes the entire file to memory, so that it's ready to play. That means the file format won't make any difference to BASS_ChannelPlay, but MP3 encoding does introduce some silence before the sound in the data. Some MP3 encoders (eg. LAME) will put the length of that in the file's header, and BASS will then use that information to remove it. Do you know what encoder your test file was created with? To confirm whether the MP3 format is making a difference, you could try a WAV file for comparison.

If it turns out that all formats seem delayed, you could try enabling non-stop output via the BASS_CONFIG_DEV_NONSTOP option (before BASS_Init):

Code: [Select]
BASS_SetConfig(BASS_CONFIG_DEV_NONSTOP, 1);

Please see the BASS_CONFIG_DEV_NONSTOP documentation for details.

jimtompkins

  • Posts: 15
Re: mp3 Playback Latency
« Reply #2 on: 17 Oct '22 - 18:54 »
Thanks Ian.

I don't know what encoder my test file was created with.  Is there a way to tell from the metadata?

I tried a .ogg file with no real difference, but it was created by saving the .mp3 as .ogg in Audacity.... I will try a .wav next.

I then tried the NONSTOP config option and this reduced it to around 100ms, so a good improvement but still above my target.

Any other ideas?

Jim

jimtompkins

  • Posts: 15
Re: mp3 Playback Latency
« Reply #3 on: 17 Oct '22 - 21:43 »
I also tried setting UPDATEPERIOD to 5ms and BUFFER to 10ms but did not notice any improvement.

I also tried setting NORAMP to 2 but it complains that BASS_CONFIG_NORAMP is undefined.

Ian @ un4seen

  • Administrator
  • Posts: 25460
Re: mp3 Playback Latency
« Reply #4 on: 18 Oct '22 - 13:18 »
I tried a .ogg file with no real difference, but it was created by saving the .mp3 as .ogg in Audacity.... I will try a .wav next.

You can check for a gap/silence at the start of the waveform in Audacity. OGG encoding won't introduce extra silence, so the decoded data will be approximately (OGG isn't lossless) the same as you see in Audacity.

Any other ideas?

If you call BASS_GetInfo, what "latency" and "minbuf" values do you see?

saga

  • Posts: 2662
Re: mp3 Playback Latency
« Reply #5 on: 18 Oct '22 - 18:18 »
Just to be clear, is that BASS_Init call part of the button press function? If it is, can you move it out? If BASS_SampleLoad is also part of that button call and it's feasible to do so, it should be moved out as well.

jimtompkins

  • Posts: 15
Re: mp3 Playback Latency
« Reply #6 on: 18 Oct '22 - 18:26 »
I have 4 buttons:
1) BASS init.  This calls init and also sets BASS_CONFIG_DEV_NONSTOP to 1, BASS_CONFIG_UPDATEPERIOD to 5, and BASS_CONFIG_BUFFER to 10.
2) get version
3) load the audio file using BASS_SampleLoad and BASS_SampleGetChannel
4) play using BASS_ChannelPlay

I'm measuring the delay from pressing the play button (the sound of finger hitting phone) to hearing the playback sound.

I printed out the latency (13) and minbuf (0) from BASS_GetInfo at the end of the "init" button actions.  13ms would be great but I'm still measuring latency of ~100ms +/-.

The freq member of BASS_INFO is 44100.  The audio file I'm testing with is at 48kHz.  Could that difference be introducing a delay in starting the playback?

I tried setting the BASS_ATTRIB_BUFFER to 0.0 for the channel I'm using but that didn't  make any difference.

Thanks for any further hints.

teq

  • Posts: 80
Re: mp3 Playback Latency
« Reply #7 on: 18 Oct '22 - 18:59 »
Hi,

I'm trying to integrate BASS into a Flutter app for iOS (and eventually Android).  See https://github.com/JimTompkins/flutter_bass for the repo.  The example app has 4 buttons: init BASS, get the version, load a sample from an mp3 file, and play the sample.

I measured the playback latency by using another phone to record while I click the "play" button.  I'm measuring about 135ms from button push to playback starting.   This includes the time for the Flutter code to detect the button push and call the BASS_ChannelPlay function as well as what's happening inside BASS.  For comparison, I'm able to achieve about 70ms using a Flutter package called soundpool, and about 20ms on Android.

My code is pretty simple:
Code: [Select]
BASS_Init(-1, 44100, 0, 0, 0);
...
cowbellSample = BASS_SampleLoad(0, fileName, 0, 0, 1, 0);
...
cowbellChannel = BASS_SampleGetChannel(cowbellSample, 0);
...
result = BASS_ChannelPlay(cowbellChannel);

How can I reduce this playback latency?  By using a different audio file format?

Thanks for any hints!
I just barely looked into the source and may be you had this latency due to creating temp file for each mp3? I tried to run your source but got errors(the latest one was about pod file not found).
Here some links, hope it will help
https://stackoverflow.com/questions/61084761/unable-to-load-asset-error-when-loading-an-mp3-file-flutter
https://stackoverflow.com/questions/67604560/flutter-unable-to-load-text-from-assets

jimtompkins

  • Posts: 15
Re: mp3 Playback Latency
« Reply #8 on: 19 Oct '22 - 13:41 »
Thank you for taking a look.  I'm loading the audio file from the root bundle and saving it to a temp file, and then calling BASS.SampleLoad all when the "Load sample" button is presses.  The latency I'm measuring is from hitting the "Play" button until the sound starts playing.

Re the podfile issue, I think you could regenerate it using these steps:
- open your terminal at root level of your project.
- cd ios.
- rm -rf Podfile.lock
- pod install --repo-update .
- flutter clean.
- flutter run



Ian @ un4seen

  • Administrator
  • Posts: 25460
Re: mp3 Playback Latency
« Reply #9 on: 20 Oct '22 - 16:23 »
I printed out the latency (13) and minbuf (0) from BASS_GetInfo at the end of the "init" button actions.  13ms would be great but I'm still measuring latency of ~100ms +/-.

Were those values with BASS_CONFIG_DEV_NONSTOP enabled? The latency and minbuf values are currently inaccurate/unavailable on iOS when BASS_GetInfo is called before the output device has been started (I'll look into correcting that for the next update). The values will usually be something like latency=30 and minbuf=11. I guess the rest of the latency is mostly in the UI response? Was the "soundpool" comparison that you mentioned in the same app with the same UI?

The freq member of BASS_INFO is 44100.  The audio file I'm testing with is at 48kHz.  Could that difference be introducing a delay in starting the playback?

No, that won't affect it.

I tried setting the BASS_ATTRIB_BUFFER to 0.0 for the channel I'm using but that didn't  make any difference.

BASS_ATTRIB_BUFFER doesn't apply to samples, as they're already entirely decoded in memory (by BASS_SampleLoad).

teq

  • Posts: 80
Re: mp3 Playback Latency
« Reply #10 on: 20 Oct '22 - 17:50 »
Thank you for taking a look.  I'm loading the audio file from the root bundle and saving it to a temp file, and then calling BASS.SampleLoad all when the "Load sample" button is presses.  The latency I'm measuring is from hitting the "Play" button until the sound starts playing.

Re the podfile issue, I think you could regenerate it using these steps:
- open your terminal at root level of your project.
- cd ios.
- rm -rf Podfile.lock
- pod install --repo-update .
- flutter clean.
- flutter run
I really want to try bring BASS to flutter with your project, but it's not working. It has warnings at the start(after pub get) and later.
For example
Quote
No application found for TargetPlatform.ios.
Is your project missing an ios/Runner/Info.plist?
Consider running "flutter create ." to create one.
Then after your advice
Quote
[!] No `Podfile' found in the project directory.

Could you provide working example or steps to make it compilable?

jimtompkins

  • Posts: 15
Re: mp3 Playback Latency
« Reply #11 on: 20 Oct '22 - 19:19 »
Please try now.  I added the example/ios folder to the Github repo.

Thanks!

jimtompkins

  • Posts: 15
Re: mp3 Playback Latency
« Reply #12 on: 20 Oct '22 - 19:58 »
I printed out the latency (13) and minbuf (0) from BASS_GetInfo at the end of the "init" button actions.  13ms would be great but I'm still measuring latency of ~100ms +/-.

Were those values with BASS_CONFIG_DEV_NONSTOP enabled? The latency and minbuf values are currently inaccurate/unavailable on iOS when BASS_GetInfo is called before the output device has been started (I'll look into correcting that for the next update). The values will usually be something like latency=30 and minbuf=11. I guess the rest of the latency is mostly in the UI response? Was the "soundpool" comparison that you mentioned in the same app with the same UI?

I changed the code to call GetInfo after each ChannelPlay.  Now the latency is 31 and the minbuf is 12.  I tried setting BASS_CONFIG_BUFFER to 12 (it was 10 previously) but this didn't make any difference.

The soundpool comparison was a different example app: just one screen with a few buttons.  For soundpool, I also measure the latency by recording the button click and the resulting sound played, so I think it's a reasonable comparison although not exact.

The freq member of BASS_INFO is 44100.  The audio file I'm testing with is at 48kHz.  Could that difference be introducing a delay in starting the playback?

No, that won't affect it.

ok

I tried setting the BASS_ATTRIB_BUFFER to 0.0 for the channel I'm using but that didn't  make any difference.

BASS_ATTRIB_BUFFER doesn't apply to samples, as they're already entirely decoded in memory (by BASS_SampleLoad).

ok

Ian @ un4seen

  • Administrator
  • Posts: 25460
Re: mp3 Playback Latency
« Reply #13 on: 21 Oct '22 - 11:51 »
I tried setting BASS_CONFIG_BUFFER to 12 (it was 10 previously) but this didn't make any difference.

Like BASS_ATTRIB_BUFFER, the BASS_CONFIG_BUFFER option doesn't affect samples (for the same reason), but you can try lowering the BASS_CONFIG_DEV_PERIOD setting to make all playback start a bit more quickly. The default setting is 10. You could try 5.

jimtompkins

  • Posts: 15
Re: mp3 Playback Latency
« Reply #14 on: 21 Oct '22 - 13:34 »
Thanks.  I tried this and also noticed that SetConfig settings don't affect already initialized devices, so I moved the SetConfig calls before the call to Init.  Now it reports the latency = 22 and minbuf = 6.  I think the mean latency has reduced somewhat.

I will add the Flutter package soundpool to my example app for a direct apples-to-apples comparison and report back.

jimtompkins

  • Posts: 15
Re: mp3 Playback Latency
« Reply #15 on: 21 Oct '22 - 15:32 »
I added three buttons to the example app to use the Flutter package soundpool: init, load file and play.

The mean (N=5) latency from button push to sound for soundpool is 238ms vs 115ms for BASS, so BASS has much lower latency.  (see the Github readme for a more detailed description.)

Soundpool is the lowest latency Flutter audio package I've found.  My previous comment about 80ms latency was not an apples-to-apples comparison; it was from a system event to sound output so can't be compared with these numbers.  So now I move on to integrating BASS with my app.

Thanks to everyone for their help in getting me this far.

jimtompkins

  • Posts: 15
Re: mp3 Playback Latency
« Reply #16 on: 4 Nov '22 - 19:11 »
I've recently worked on integrating BASS for Android with Flutter and now have it working and giving good results.

The first version that I got working had a button-push-to-sound-played latency of 267ms compared to 158ms using a Flutter package called flutter_ogg_piano.  I found a couple of things that made a big difference:

  • setting the frequency to 48000 (instead of 44100) reduced the mean latency by 68ms. With the original setting of 44100, this error message showed up when I ran using flutter run --debug --verbose: W/AudioTrack(29616): AUDIO_OUTPUT_FLAG_FAST denied by client; transfer 1, track 44100 Hz, output 48000 Hz.
    With the modified setting of 48000, the message became: [ +6 ms] I/AudioTrack(29616): AUDIO_OUTPUT_FLAG_FAST successful; frameCount 480 -> 480
  • setting BASS_CONFIG_DEV_BUFFER to 10ms reduced the mean latency by 45ms.

You can find the flutter_bass plugin at: https://github.com/JimTompkins/flutter_bass

Ian @ un4seen

  • Administrator
  • Posts: 25460
Re: mp3 Playback Latency
« Reply #17 on: 7 Nov '22 - 12:17 »
Using the device's native rate will usually allow lower latency on Android, so it sounds like your device's native rate is 48000 Hz, but other devices may have a different native rate. BASS_Init will detect and use the native rate by default unless the BASS_DEVICE_FREQ flag is used, but it also needs a JavaVM to do that. BASS will be provided a JavaVM automatically when it's loaded by Java (eg. System.loadLibrary), but perhaps not by Flutter? You can check if BASS has a JavaVM via this option:

Code: [Select]
#define BASS_CONFIG_ANDROID_JAVAVM 63
...
JavaVM *javavm = (JavaVM*)BASS_GetConfigPtr(BASS_CONFIG_ANDROID_JAVAVM);

If that's NULL then BASS doesn't have a JavaVM. In that case, you can use BASS_SetConfigPtr with the same option to provide Flutter's JavaVM (assuming it has one?).