package kha.audio2; import kha.arrays.Float32Array; @:headerCode("#include ") @:headerClassCode("volatile float kinc_volume; volatile int kinc_position; volatile int kinc_paused; volatile int kinc_stopped; volatile int kinc_looping;") class AudioChannel implements kha.audio1.AudioChannel { public var data: Float32Array = null; #if cpp var myVolume(get, set): Float; inline function get_myVolume(): Float { return untyped __cpp__("kinc_volume"); } inline function set_myVolume(value: Float): Float { untyped __cpp__("KINC_ATOMIC_EXCHANGE_FLOAT(&kinc_volume, (float){0})", value); return value; } var myPosition(get, set): Int; inline function get_myPosition(): Int { return untyped __cpp__("kinc_position"); } inline function set_myPosition(value: Int): Int { untyped __cpp__("KINC_ATOMIC_EXCHANGE_32(&kinc_position, {0})", value); return value; } var paused(get, set): Bool; inline function get_paused(): Bool { return untyped __cpp__("kinc_paused != 0"); } inline function set_paused(value: Bool): Bool { untyped __cpp__("KINC_ATOMIC_EXCHANGE_32(&kinc_paused, {0} ? 1 : 0)", value); return value; } var stopped(get, set): Bool; inline function get_stopped(): Bool { return untyped __cpp__("kinc_stopped != 0"); } inline function set_stopped(value: Bool): Bool { untyped __cpp__("KINC_ATOMIC_EXCHANGE_32(&kinc_stopped, {0} ? 1 : 0)", value); return value; } var looping(get, set): Bool; inline function get_looping(): Bool { return untyped __cpp__("kinc_looping != 0"); } inline function set_looping(value: Bool): Bool { untyped __cpp__("KINC_ATOMIC_EXCHANGE_32(&kinc_looping, {0} ? 1 : 0)", value); return value; } #else var myVolume: Float; var myPosition: Int; var paused: Bool; var stopped: Bool; var looping: Bool; #end public function new(looping: Bool) { this.looping = looping; stopped = false; paused = false; myPosition = 0; myVolume = 1; } public function nextSamples(requestedSamples: Float32Array, requestedLength: Int, sampleRate: Int): Void { if (paused || stopped) { for (i in 0...requestedLength) { requestedSamples[i] = 0; } return; } var requestedSamplesIndex = 0; while (requestedSamplesIndex < requestedLength) { for (i in 0...min(data.length - myPosition, requestedLength - requestedSamplesIndex)) { requestedSamples[requestedSamplesIndex++] = data[myPosition++]; } if (myPosition >= data.length) { myPosition = 0; if (!looping) { stopped = true; break; } } } while (requestedSamplesIndex < requestedLength) { requestedSamples[requestedSamplesIndex++] = 0; } } public function play(): Void { paused = false; stopped = false; kha.audio1.Audio._playAgain(this); } public function pause(): Void { paused = true; } public function stop(): Void { myPosition = 0; stopped = true; } public var length(get, null): Float; // Seconds function get_length(): Float { return data.length / kha.audio2.Audio.samplesPerSecond / 2; // 44.1 khz in stereo } public var position(get, set): Float; // Seconds function get_position(): Float { return myPosition / kha.audio2.Audio.samplesPerSecond / 2; } function set_position(value: Float): Float { myPosition = Math.round(value * kha.audio2.Audio.samplesPerSecond * 2); myPosition = max(min(myPosition, data.length), 0); return value; } public var volume(get, set): Float; function get_volume(): Float { return myVolume; } function set_volume(value: Float): Float { return myVolume = value; } public var finished(get, null): Bool; function get_finished(): Bool { return stopped; } static inline function max(a: Int, b: Int) { return a > b ? a : b; } static inline function min(a: Int, b: Int) { return a < b ? a : b; } }