Remove requirement for a render lock by making listener queue thread-safe

pull/35/head
James Ball 2021-06-24 12:02:41 +01:00
rodzic 42c018c422
commit 7dda40130b
3 zmienionych plików z 16 dodań i 35 usunięć

Wyświetl plik

@ -4,8 +4,7 @@ import sh.ball.audio.effect.Effect;
import java.io.*;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.*;
import sh.ball.audio.engine.AudioDevice;
import sh.ball.audio.engine.AudioEngine;
@ -14,8 +13,7 @@ import sh.ball.shapes.Vector2;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.Semaphore;
import javax.sound.sampled.LineUnavailableException;
import java.util.concurrent.locks.ReentrantLock;
public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
@ -33,8 +31,7 @@ public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
private final Callable<AudioEngine> audioEngineBuilder;
private final BlockingQueue<List<Shape>> frameQueue = new ArrayBlockingQueue<>(BUFFER_SIZE);
private final Map<Object, Effect> effects = new HashMap<>();
private final ReentrantLock renderLock = new ReentrantLock();
private final List<Listener> listeners = new ArrayList<>();
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
private AudioEngine audioEngine;
private ByteArrayOutputStream outputStream;
@ -83,13 +80,13 @@ public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
}
private void writeChannels(float leftChannel, float rightChannel) {
int left = (int)(leftChannel * Short.MAX_VALUE);
int right = (int)(rightChannel * Short.MAX_VALUE);
int left = (int) (leftChannel * Short.MAX_VALUE);
int right = (int) (rightChannel * Short.MAX_VALUE);
byte b0 = (byte) left;
byte b1 = (byte)(left >> 8);
byte b1 = (byte) (left >> 8);
byte b2 = (byte) right;
byte b3 = (byte)(right >> 8);
byte b3 = (byte) (right >> 8);
if (recording) {
outputStream.write(b0);
@ -155,7 +152,11 @@ public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
throw new IllegalArgumentException("No AudioDevice provided");
}
audioEngine.play(this::generateChannels, renderLock, device);
try {
audioEngine.play(this::generateChannels, device);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
@ -200,19 +201,9 @@ public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
@Override
public void read(byte[] buffer) throws InterruptedException {
Listener listener = new Listener(buffer);
try {
renderLock.lock();
listeners.add(listener);
} finally {
renderLock.unlock();
}
listeners.add(listener);
listener.waitUntilFull();
try {
renderLock.lock();
listeners.remove(listener);
} finally {
renderLock.unlock();
}
listeners.remove(listener);
}
@Override

Wyświetl plik

@ -4,12 +4,11 @@ import sh.ball.shapes.Vector2;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.locks.ReentrantLock;
public interface AudioEngine {
boolean isPlaying();
void play(Callable<Vector2> channelGenerator, ReentrantLock renderLock, AudioDevice device);
void play(Callable<Vector2> channelGenerator, AudioDevice device) throws Exception;
void stop();

Wyświetl plik

@ -8,7 +8,6 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.locks.ReentrantLock;
public class XtAudioEngine implements AudioEngine {
@ -19,7 +18,6 @@ public class XtAudioEngine implements AudioEngine {
private AudioDevice device;
private boolean playing = false;
private ReentrantLock renderLock;
private Callable<Vector2> channelGenerator;
public XtAudioEngine() {}
@ -27,9 +25,6 @@ public class XtAudioEngine implements AudioEngine {
private int render(XtStream stream, Structs.XtBuffer buffer, Object user) throws Exception {
XtSafeBuffer safe = XtSafeBuffer.get(stream);
safe.lock(buffer);
if (renderLock != null) {
renderLock.lock();
}
Object output = safe.getOutput();
for (int f = 0; f < buffer.frames; f++) {
@ -37,9 +32,6 @@ public class XtAudioEngine implements AudioEngine {
writeChannels(channels, output, f);
}
safe.unlock(buffer);
if (renderLock != null) {
renderLock.unlock();
}
return 0;
}
@ -97,11 +89,10 @@ public class XtAudioEngine implements AudioEngine {
}
@Override
public void play(Callable<Vector2> channelGenerator, ReentrantLock renderLock, AudioDevice device) {
public void play(Callable<Vector2> channelGenerator, AudioDevice device) {
this.playing = true;
this.device = device;
this.channelGenerator = channelGenerator;
this.renderLock = renderLock;
try (XtPlatform platform = XtAudio.init(null, null)) {
XtService service = getService(platform);