package com.cookbook.audio;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.TimeUtils;
public class SoundInstance {
private SoundData data;
private long id;
private Vector2 position;
private long startTime;
private Vector2 tmp;
public SoundInstance(SoundData data) {
this(data, new Vector2(0.0f, 0.0f));
}
public SoundInstance(SoundData data, Vector2 position) {
this.data = data;
this.id = -1;
this.position = position;
this.startTime = -1;
this.tmp = new Vector2();
play();
}
public Vector2 getPosition() {
return position;
}
public void setPosition(Vector2 position) {
this.position.set(position);
}
public boolean update(Listener listener) {
if (isFinished()) {
return true;
}
// Calculate pan
Vector2 listenerPos = listener.getPosition();
Vector2 listenerDir = listener.getDirection();
tmp.set(position);
tmp.sub(listenerPos);
tmp.nor();
float angle = Math.abs(listenerDir.angleRad() - tmp.angleRad());
boolean isRight = tmp.crs(listenerDir) > 0.0f;
float pan = 0.0f;
if (angle > MathUtils.PI * 0.5f) {
angle -= MathUtils.PI * 0.5f;
pan = Interpolation.linear.apply(isRight ? 1.0f : -1.0f, 0.0f, angle / (MathUtils.PI * 0.5f));
}
else {
pan = Interpolation.linear.apply(0.0f, isRight ? 1.0f : -1.0f, angle / (MathUtils.PI * 0.5f));
}
// Calculate volume
float distance = position.dst(listenerPos);
float falloffStart = data.getFalloffStart();
float volume = MathUtils.clamp(1.0f - (distance - falloffStart) / (data.getMaxDistance() - falloffStart),
0.0f,
1.0f);
// Apply results
data.getSound().setPan(id, pan, volume);
return false;
}
public boolean isFinished() {
return startTime > 0 && TimeUtils.timeSinceMillis(startTime) / 1000.0f > data.getDuration();
}
private void play() {
id = data.getSound().play();
startTime = TimeUtils.millis();
}
}