just_audio_engine 1.0.1 copy "just_audio_engine: ^1.0.1" to clipboard
just_audio_engine: ^1.0.1 copied to clipboard

High-performance audio processing pipeline for just_game_engine. Supports all platforms with native backends (AVAudioEngine, XAudio2, OpenAL) and Web Audio API.

example/example.dart

// ignore_for_file: avoid_print

/// just_audio_engine — runnable example
///
/// This file demonstrates every major feature of the package.
/// Run it with:
///   flutter run -t example/example.dart
library;

import 'package:flutter/material.dart';
import 'package:just_audio_engine/just_audio_engine.dart';

void main() => runApp(const AudioExampleApp());

// ─────────────────────────────────────────────────────────────────────────────
// App shell
// ─────────────────────────────────────────────────────────────────────────────

class AudioExampleApp extends StatelessWidget {
  const AudioExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'just_audio_engine example',
      theme: ThemeData.dark(),
      home: const AudioExamplePage(),
    );
  }
}

// ─────────────────────────────────────────────────────────────────────────────
// Main page
// ─────────────────────────────────────────────────────────────────────────────

class AudioExamplePage extends StatefulWidget {
  const AudioExamplePage({super.key});

  @override
  State<AudioExamplePage> createState() => _AudioExamplePageState();
}

class _AudioExamplePageState extends State<AudioExamplePage> {
  // ── Engine instances ──────────────────────────────────────────────────────

  final AudioEngine _engine = AudioEngine();
  late final MusicManager _music;
  late final SoundEffectManager _sfx;

  // Streaming large audio files without loading the whole asset into memory.
  late final AudioStream _stream;

  // Track the last playing SFX so we can stop / update it.
  String? _lastSfxId;

  bool _engineReady = false;

  // ── Lifecycle ─────────────────────────────────────────────────────────────

  @override
  void initState() {
    super.initState();
    _music = MusicManager(_engine);
    _sfx = SoundEffectManager(_engine);
    _init();
  }

  Future<void> _init() async {
    // Initialize once; safe to call multiple times.
    await _engine.initialize();

    // AudioStream needs the backend reference.
    _stream = AudioStream(
      path: 'assets/audio/bgm_loop.mp3',
      channel: AudioChannel.music,
    );
    await _stream.open(_engine.backend, voicePool: _engine.voicePool);

    setState(() => _engineReady = true);
    print('AudioEngine ready: ${_engine.backend.runtimeType}');
  }

  @override
  void dispose() {
    _stream.dispose();
    _engine.dispose();
    super.dispose();
  }

  // ─────────────────────────────────────────────────────────────────────────
  // Feature demos
  // ─────────────────────────────────────────────────────────────────────────

  // 1. Background music via MusicManager ─────────────────────────────────────

  Future<void> _playBgm() async {
    await _music.play(
      'assets/audio/bgm.mp3',
      volume: 0.8,
      loop: true,
      fadeIn: true,
      fadeDuration: const Duration(seconds: 2),
    );
  }

  Future<void> _stopBgm() async {
    await _music.stop(fadeOut: true, fadeDuration: const Duration(seconds: 1));
  }

  // 2. One-shot SFX via SoundEffectManager ───────────────────────────────────

  Future<void> _playSfx() async {
    _lastSfxId = await _sfx.play(
      'assets/audio/hit.wav',
      volume: 0.9,
      pan: 0.0, // -1 (left) … 1 (right)
      pitch: 1.0, // 1.0 = normal, 2.0 = octave up
    );
    print('SFX id: $_lastSfxId');
  }

  void _stopLastSfx() {
    if (_lastSfxId != null) {
      _sfx.stop(_lastSfxId!);
      _lastSfxId = null;
    }
  }

  // 3. DSP effects applied per voice ─────────────────────────────────────────

  Future<void> _playSfxWithEffects() async {
    _lastSfxId = await _engine.playSfx(
      'assets/audio/hit.wav',
      volume: 0.8,
      effects: [
        AudioEffect.reverb(roomSize: 0.7, damping: 0.5, wetLevel: 0.4),
        AudioEffect.lowpass(frequency: 1200, q: 1.0),
        AudioEffect.delay(delayMs: 200, feedback: 0.3, mix: 0.25),
      ],
    );
  }

  // 4. Spatial 3D audio ──────────────────────────────────────────────────────

  Future<void> _playSpatialSfx() async {
    // Position a sound source 10 units to the right of the origin.
    _lastSfxId = await _engine.playSfx(
      'assets/audio/ambient.wav',
      loop: true,
      position3d: const Audio3DPosition(10, 0, 0),
    );

    // Queued — flushed on the next update() tick.
    _engine.setListener3D(
      const Audio3DListener(
        position: Audio3DPosition(0, 0, 0),
        forward: Audio3DPosition(0, 0, -1),
        up: Audio3DPosition(0, 1, 0),
      ),
    );
  }

  // 5. Move a 3D source while it plays ──────────────────────────────────────

  // Now sync — queued and flushed in the next update() tick.
  void _moveSource(double x) {
    if (_lastSfxId != null) {
      _engine.updateSfxPosition(_lastSfxId!, Audio3DPosition(x, 0, 0));
    }
  }

  // 6. AudioStream – chunk-streamed playback ─────────────────────────────────

  Future<void> _playStream() async {
    await _stream.play(volume: 0.7, loop: true);
  }

  Future<void> _fadeStream() async {
    await _stream.fade(0.0, const Duration(seconds: 3));
    await _stream.stop();
  }

  // 7. Channel volumes ───────────────────────────────────────────────────────

  void _setChannelVolumes() {
    _engine.setMasterVolume(1.0);
    _engine.setChannelVolume(AudioChannel.music, 0.7);
    _engine.setChannelVolume(AudioChannel.sfx, 1.0);
    _engine.setChannelVolume(AudioChannel.voice, 0.9);
    _engine.setChannelVolume(AudioChannel.ambient, 0.5);
  }

  // 8. Mute / Unmute ─────────────────────────────────────────────────────────

  void _toggleMute() {
    _engine.toggleMute();
    setState(() {});
    print('Muted: ${_engine.isMuted}');
  }

  // ─────────────────────────────────────────────────────────────────────────
  // UI
  // ─────────────────────────────────────────────────────────────────────────

  @override
  Widget build(BuildContext context) {
    if (!_engineReady) {
      return const Scaffold(body: Center(child: CircularProgressIndicator()));
    }

    return Scaffold(
      appBar: AppBar(
        title: const Text('just_audio_engine example'),
        actions: [
          IconButton(
            icon: Icon(_engine.isMuted ? Icons.volume_off : Icons.volume_up),
            onPressed: _toggleMute,
          ),
        ],
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          _Section(
            title: '1 — Background Music',
            children: [
              _Btn('Play BGM (fade-in)', onPressed: _playBgm),
              _Btn('Stop BGM (fade-out)', onPressed: _stopBgm),
              _Btn('Pause', onPressed: _music.pause),
              _Btn('Resume', onPressed: _music.resume),
            ],
          ),
          _Section(
            title: '2 — Sound Effects',
            children: [
              _Btn('Play SFX', onPressed: _playSfx),
              _Btn('Stop last SFX', onPressed: _stopLastSfx),
              _Btn('Stop all SFX', onPressed: _engine.stopAllSfx),
            ],
          ),
          _Section(
            title: '3 — DSP Effects (reverb + lowpass + delay)',
            children: [
              _Btn('Play SFX with effects', onPressed: _playSfxWithEffects),
            ],
          ),
          _Section(
            title: '4 — Spatial 3D Audio',
            children: [
              _Btn('Play spatial SFX (x=10)', onPressed: _playSpatialSfx),
              _Btn(
                'Move source → left  (x=-10)',
                onPressed: () => _moveSource(-10),
              ),
              _Btn(
                'Move source → right (x= 10)',
                onPressed: () => _moveSource(10),
              ),
            ],
          ),
          _Section(
            title: '5 — Streaming (AudioStream)',
            children: [
              _Btn('Start stream', onPressed: _playStream),
              _Btn('Fade out & stop', onPressed: _fadeStream),
            ],
          ),
          _Section(
            title: '6 — Channel Volumes',
            children: [
              _Btn(
                'Apply demo volumes',
                onPressed: () {
                  _setChannelVolumes();
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('Channel volumes applied')),
                  );
                },
              ),
            ],
          ),
        ],
      ),
    );
  }
}

// ─────────────────────────────────────────────────────────────────────────────
// Small helpers
// ─────────────────────────────────────────────────────────────────────────────

class _Section extends StatelessWidget {
  const _Section({required this.title, required this.children});

  final String title;
  final List<Widget> children;

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const SizedBox(height: 16),
        Text(
          title,
          style: Theme.of(
            context,
          ).textTheme.titleSmall?.copyWith(color: Colors.tealAccent),
        ),
        const SizedBox(height: 8),
        Wrap(spacing: 8, runSpacing: 8, children: children),
        const Divider(height: 24),
      ],
    );
  }
}

class _Btn extends StatelessWidget {
  const _Btn(this.label, {required this.onPressed});

  final String label;
  final VoidCallback onPressed;

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(onPressed: onPressed, child: Text(label));
  }
}
1
likes
150
points
166
downloads

Documentation

API reference

Publisher

verified publisherjustunknown.com

Weekly Downloads

High-performance audio processing pipeline for just_game_engine. Supports all platforms with native backends (AVAudioEngine, XAudio2, OpenAL) and Web Audio API.

Repository (GitHub)
View/report issues
Contributing

License

BSD-3-Clause (license)

Dependencies

flutter, just_memory, web

More

Packages that depend on just_audio_engine

Packages that implement just_audio_engine