skip to Main Content

The app plays some background audio (wav) in an endless loop. Audio playback was flawless using just_audio package, but after switching to audioplayers, all looped audio now contain a short gap of silence before they restart at the beginning. Question now is: How to get rid of the gap?

The code to load and play the files is quite simple:

  Future<void> loadAmbient() async {
    _audioAmbient = AudioPlayer();
    await _audioAmbient!.setSource(AssetSource('audio/ambient.wav'));
    await _audioAmbient!.setReleaseMode(ReleaseMode.loop);
  }

  void playAmbient() async {
    if (PlayerState.playing != _audioAmbient?.state) {
      await _audioAmbient?.seek(Duration.zero);
      _audioAmbient?.resume();
    }
  }

According to the audioplayers docs, this seems to be a known issue:

The Getting Started docs state:

Note: there are caveats when looping audio without gaps. Depending on the file format and platform, when audioplayers uses the native implementation of the "looping" feature, there will be gaps between plays, witch might not be noticeable for non-continuous SFX but will definitely be noticeable for looping songs. Please check out the Gapless Loop section on our Troubleshooting Guide for more details.

Following the link to the [Trouble Shooting Guide] (https://github.com/bluefireteam/audioplayers/blob/main/troubleshooting.md) reveals:

Gapless Looping

Depending on the file format and platform, when audioplayers uses the native implementation of the "looping" feature, there will be gaps between plays, witch might not be noticeable for non-continuous SFX but will definitely be noticeable for looping songs.

TODO(luan): break down alternatives here, low latency mode, audio pool, gapless_audioplayer, ocarina, etc

Interesting is the Depending on the file format and platform, ... part, which sounds as if gap-less loops could somehow be doable. Question is, how?

Any ideas how to get audio to loop flawless (i.e. without gap) are very much appreciated. Thank you.

2

Answers


  1. You can pass this parameter

    _audioAmbient = AudioPlayer(mode: PlayerMode.LOW_LATENCY);
    

    if not solved u can try something new like https://pub.dev/packages/ocarina

    Login or Signup to reply.
  2. I fixed it this way:
    Created 2 players, set asset path to both of them and created the method that starts second player before first is completed

    import 'package:just_audio/just_audio.dart' as audio;
    
    audio.AudioPlayer player1 = audio.AudioPlayer();
    audio.AudioPlayer player2 = audio.AudioPlayer();
    bool isFirstPlayerActive = true;
    StreamSubscription? subscription;
    
      audio.AudioPlayer getActivePlayer() {
        return isFirstPlayerActive ? player1 : player2;
      }
    
      void setPlayerAsset(String asset) async {
        if (isFirstPlayerActive) {
          await player1.setAsset("assets/$asset");
          await player2.setAsset("assets/$asset");
        } else {
          await player2.setAsset("assets/$asset");
          await player1.setAsset("assets/$asset");
        }
        subscription?.cancel();
        _loopPlayer(getActivePlayer(), isFirstPlayerActive ? player2 : player1);
      }
    
    
      audio.AudioPlayer getActivePlayer() {
        return isFirstPlayerActive ? player1 : player2;
      }
      
      void _loopPlayer(audio.AudioPlayer player1, audio.AudioPlayer player2) async {
          Duration? duration = await player1.durationFuture;
          subscription = player1.positionStream.listen((event) {
            if (duration != null &&
                event.inMilliseconds >= duration.inMilliseconds - 110) {
              log('finished');
              player2.play();
              isFirstPlayerActive = !isFirstPlayerActive;
              StreamSubscription? tempSubscription;
              tempSubscription = player1.playerStateStream.listen((event) {
                if (event.processingState == audio.ProcessingState.completed) {
                  log('completed');
                  player1.seek(const Duration(seconds: 0));
                  player1.pause();
                  tempSubscription?.cancel();
                }
              });
              subscription?.cancel();
              _loopPlayer(player2, player1);
            }
          });
      
      }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search