kopia lustrzana https://github.com/jameshball/osci-render
Remove requirement for a render lock by making listener queue thread-safe
rodzic
42c018c422
commit
7dda40130b
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue