LNXSDK/leenkx/Sources/iron/object/SpeakerObject.hx
2025-01-22 16:18:30 +01:00

109 lines
2.4 KiB
Haxe

package iron.object;
import kha.FastFloat;
import kha.audio1.AudioChannel;
import iron.data.Data;
import iron.data.SceneFormat;
import iron.math.Vec4;
import iron.system.Audio;
class SpeakerObject extends Object {
#if lnx_audio
public var data: TSpeakerData;
public var paused(default, null) = false;
public var sound(default, null): kha.Sound = null;
public var channels(default, null): Array<AudioChannel> = [];
public var volume(default, null) : FastFloat;
public function new(data: TSpeakerData) {
super();
this.data = data;
Scene.active.speakers.push(this);
if (data.sound == "") return;
Data.getSound(data.sound, function(sound: kha.Sound) {
this.sound = sound;
App.notifyOnInit(init);
});
}
function init() {
if (visible && data.play_on_start) play();
}
public function play() {
if (sound == null || data.muted) return;
if (paused) {
for (c in channels) c.play();
paused = false;
return;
}
var channel = Audio.play(sound, data.loop, data.stream);
if (channel != null) {
channels.push(channel);
if (data.attenuation > 0 && channels.length == 1) App.notifyOnUpdate(update);
}
}
public function pause() {
for (c in channels) c.pause();
paused = true;
}
public function stop() {
for (c in channels) c.stop();
channels.splice(0, channels.length);
}
public function setSound(sound: String) {
if (sound == null) return;
data.sound = sound;
Data.getSound(sound, function(sound: kha.Sound) {
this.sound = sound;
});
}
public function setVolume(volume: FastFloat) {
data.volume = volume;
}
function update() {
if (paused) return;
for (c in channels) if (c.finished) channels.remove(c);
if (channels.length == 0) {
App.removeUpdate(update);
return;
}
if (data.attenuation > 0) {
var distance = Vec4.distance(Scene.active.camera.transform.world.getLoc(), transform.world.getLoc());
distance = Math.max(Math.min(data.distance_max, distance), data.distance_reference);
volume = data.distance_reference / (data.distance_reference + data.attenuation * (distance - data.distance_reference));
volume *= data.volume;
}
else {
volume = data.volume;
}
if (volume > data.volume_max) volume = data.volume_max;
else if (volume < data.volume_min) volume = data.volume_min;
for (c in channels) c.volume = volume;
}
public override function remove() {
stop();
if (Scene.active != null) Scene.active.speakers.remove(this);
super.remove();
}
#end
}