playSoundOnTargetChannels method
Plays the given Sound on one of the specified target channels.
sound: The Sound object to play.targetChannels: A list of preferred channel IDs. The sound will be played on the first available channel from this list. Ifnull, all channels are considered.loop: Whether the sound should loop. Defaults tofalse.loopStart: The start time in samples for looping, ifloopistrue. Converted to seconds internally using the sound's sample rate. RequiresloopEndto also be set.loopEnd: The end time in samples for looping, ifloopistrue. Converted to seconds internally using the sound's sample rate. RequiresloopStartto also be set.
Returns the channel ID on which the sound is playing, or -1 if the sound could not be played (e.g., sound not ready, retrigger delay not met, or no suitable channel found).
Implementation
int playSoundOnTargetChannels(
Sound sound, {
List<int>? targetChannels,
bool loop = false,
double? loopStart,
double? loopEnd,
}) {
if (audioContext.state == 'suspended') {
audioContext.resume();
}
if (sound.state != LoadingState.ready) {
return -1;
}
if (sound.lastTimePlayed != null) {
final timeSinceLastPlayed = DateTime.now().difference(sound.lastTimePlayed!);
if (timeSinceLastPlayed < sound.retriggerDelay) {
return -1;
}
}
var channelId = obtainFreeChannel(targetChannels);
if (channelId == -1) {
warn("All audio channels are in use. Consider to increase channel count.");
return -1;
}
var channel = _channels[channelId];
if (channel.state != ChannelState.stopped && channel.sourceNode != null) {
channel.sourceNode!.onended = null;
try {
channel
..sourceNode!.stop(0)
..state = ChannelState.stopped;
} catch (e) {
//
}
}
channel
..sound = sound
..loop = loop
..sourceNode = audioContext.createBufferSource()
..sourceNode!.buffer = sound.buffer
..sourceNode!.playbackRate.value = channel.rate
..sourceNode!.loop = loop
..sourceNode!.connect(channel.pannerNode);
if (channel.sourceNode!.loop) {
if (loopStart != null && loopEnd != null && loopEnd > loopStart) {
double hz = sound.buffer?.sampleRate ?? 44100;
loopStart = loopStart / hz;
loopEnd = loopEnd / hz;
} else {
loopStart = 0;
loopEnd = channel.sourceNode!.buffer!.duration;
}
channel.sourceNode!
..loopStart = loopStart
..loopEnd = loopEnd;
}
channel.sourceNode!.onended =
(Event event) {
channel
..sourceNode = null
..state = ChannelState.stopped;
}.toJS;
channel
..offset = 0
..startTime = audioContext.currentTime
..sourceNode?.start(0)
..state = ChannelState.playing;
sound.lastTimePlayed = DateTime.now();
return channelId;
}