mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-01 10:38:17 +08:00
83 lines
2.3 KiB
Dart
83 lines
2.3 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:audioplayers/audio_cache.dart';
|
|
import 'package:audioplayers/audioplayers.dart';
|
|
import 'package:synchronized/synchronized.dart';
|
|
|
|
typedef void Stoppable();
|
|
|
|
/// An AudioPool is a provider of AudioPlayers that leaves them pre-loaded to minimize delays.
|
|
///
|
|
/// All AudioPlayers loaded are for the same [sound]. If you want multiple sounds use multiple [AudioPool].
|
|
/// Use this class if you'd like have extremely quick firing, repetitive and simultaneous sounds, like shooting a laser in a fast-paced spaceship game.
|
|
class AudioPool {
|
|
AudioCache cache;
|
|
Map<String, AudioPlayer> currentPlayers = {};
|
|
List<AudioPlayer> availablePlayers = [];
|
|
|
|
String sound;
|
|
bool repeating;
|
|
int minPlayers, maxPlayers;
|
|
|
|
final Lock _lock = Lock();
|
|
|
|
AudioPool(this.sound,
|
|
{this.repeating = false,
|
|
this.maxPlayers = 1,
|
|
this.minPlayers = 1,
|
|
String prefix = 'audio/sfx/'}) {
|
|
cache = AudioCache(prefix: prefix);
|
|
}
|
|
|
|
Future init() async {
|
|
for (int i = 0; i < minPlayers; i++) {
|
|
availablePlayers.add(await _createNewAudioPlayer());
|
|
}
|
|
}
|
|
|
|
Future<Stoppable> start({double volume = 1.0}) async {
|
|
return _lock.synchronized(() async {
|
|
if (availablePlayers.isEmpty) {
|
|
availablePlayers.add(await _createNewAudioPlayer());
|
|
}
|
|
final AudioPlayer player = availablePlayers.removeAt(0);
|
|
currentPlayers[player.playerId] = player;
|
|
await player.setVolume(volume);
|
|
await player.resume();
|
|
|
|
StreamSubscription<void> subscription;
|
|
|
|
final Stoppable stop = () {
|
|
_lock.synchronized(() async {
|
|
final AudioPlayer p = currentPlayers.remove(player.playerId);
|
|
subscription?.cancel();
|
|
await p.stop();
|
|
if (availablePlayers.length >= maxPlayers) {
|
|
await p.release();
|
|
} else {
|
|
availablePlayers.add(p);
|
|
}
|
|
});
|
|
};
|
|
|
|
subscription = player.onPlayerCompletion.listen((_) {
|
|
if (repeating) {
|
|
player.resume();
|
|
} else {
|
|
stop();
|
|
}
|
|
});
|
|
|
|
return stop;
|
|
});
|
|
}
|
|
|
|
Future<AudioPlayer> _createNewAudioPlayer() async {
|
|
final AudioPlayer player = AudioPlayer();
|
|
final String url = (await cache.load(sound)).path;
|
|
await player.setUrl(url);
|
|
await player.setReleaseMode(ReleaseMode.STOP);
|
|
return player;
|
|
}
|
|
}
|