Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

section_loop

Player-agnostic A–B section looping for audio apps.

Repeat a named region of a track — a chorus, a drill, a phrase of speech — on whatever player you already use. The package holds no player of its own: you feed it position updates and it tells your player when to seek or pause.

Built for AudioMark, a practice player for dancers, and extracted so the looping logic can be reused and tested on its own.

Install

dependencies:
  section_loop: ^0.1.0

Usage

import 'package:section_loop/section_loop.dart';

final engine = SectionLoopEngine(
  onSeek: player.seek,
  onPause: player.pause,
  onPlay: player.play, // optional: resumes a paused player when looping
);

engine.section = LoopSection(
  name: 'Chorus',
  start: const Duration(seconds: 48),
  end: const Duration(seconds: 72),
);

player.positionStream.listen((position) {
  engine.handlePosition(position, trackDuration: player.duration);
});

Set engine.section = null (or call clear()) to let the track play through.

Play the section once instead of repeating

engine.behavior = SectionEndBehavior.pauseAtEnd;

Persist sections per track

LoopSection round-trips through JSON, so sections can be stored alongside whatever else you keep for a track:

final stored = jsonEncode(section.toJson());
final restored = LoopSection.fromJson(jsonDecode(stored) as Map<String, Object?>);

Two bugs this handles for you

Both are easy to hit and tedious to diagnose, so they are handled here and covered by tests.

A range covering the whole track is not treated as a section. Looping one means seeking at the final moment of playback, which suppresses the player's completion event — so a queue above it silently stops advancing. Ranges that reach both ends of the track are ignored. The margin is configurable through edgeTolerance.

Positions arriving while a seek is in flight are ignored. Players keep emitting the pre-seek position for a few frames after seek() is called. Acting on those queues up another seek, and playback never escapes the boundary. The engine drops positions until its own seek completes.

Player support

Anything you can seek, pause, and subscribe to positions on — just_audio, audioplayers, a platform player behind a method channel, or a fake in a test. The package is pure Dart and depends on no player.

License

MIT

About

Player-agnostic A-B section looping for audio apps. Loop a named part of a track on any player, with the seek-storm and queue-stall bugs handled.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages