package kha.audio2; import kha.js.AEAudioChannel; import kha.audio1.AudioChannel; enum abstract PlayMode(Int) { var Stopped; var Paused; var Playing; } class VirtualStreamChannel implements kha.audio1.AudioChannel { var aeChannel: AEAudioChannel; var mode = PlayMode.Playing; var lastTickTime: Float; var lastPosition: Float; var looping: Bool; public function new(aeChannel: AEAudioChannel, looping: Bool) { this.aeChannel = aeChannel; this.looping = looping; lastTickTime = Scheduler.realTime(); lastPosition = 0; } public function wake(): Void { updatePosition(); aeChannel.position = lastPosition; aeChannel.play(); } function updatePosition(): Void { var now = Scheduler.realTime(); switch (mode) { case Stopped: lastPosition = 0; case Paused: // nothing case Playing: lastPosition += now - lastTickTime; while (lastPosition > length) { lastPosition -= length; } } lastTickTime = now; } public function play(): Void { if (SystemImpl.mobileAudioPlaying) { aeChannel.play(); } else { updatePosition(); mode = Playing; } } public function pause(): Void { if (SystemImpl.mobileAudioPlaying) { aeChannel.pause(); } else { updatePosition(); mode = Paused; } } public function stop(): Void { if (SystemImpl.mobileAudioPlaying) { aeChannel.stop(); } else { updatePosition(); mode = Stopped; } } public var length(get, never): Float; // Seconds function get_length(): Float { return aeChannel.length; } public var position(get, set): Float; // Seconds function get_position(): Float { if (SystemImpl.mobileAudioPlaying) { return aeChannel.position; } else { updatePosition(); return lastPosition; } } function set_position(value: Float): Float { if (SystemImpl.mobileAudioPlaying) { return aeChannel.position = value; } else { updatePosition(); return lastPosition = value; } } public var volume(get, set): Float; function get_volume(): Float { return aeChannel.volume; } function set_volume(value: Float): Float { return aeChannel.volume = value; } public var finished(get, never): Bool; function get_finished(): Bool { if (SystemImpl.mobileAudioPlaying) { return aeChannel.finished; } else { return mode == Stopped || (!looping && position >= length); } } }