From 3089cd2b15e64e1b357ba9e99251e83200d95bd3 Mon Sep 17 00:00:00 2001 From: James Ball Date: Sat, 14 May 2022 15:31:26 +0100 Subject: [PATCH] Massively improve audio stability on Mac --- .gitignore | 1 + .../sh/ball/audio/engine/JavaAudioEngine.java | 49 +++++++++---------- src/main/java/sh/ball/gui/Gui.java | 1 - 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/.gitignore b/.gitignore index 458f25d..e2e4278 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /.idea osci-render.iml *.osci +*.log # ignore temporary files *~ diff --git a/src/main/java/sh/ball/audio/engine/JavaAudioEngine.java b/src/main/java/sh/ball/audio/engine/JavaAudioEngine.java index 7937b99..8e43e71 100644 --- a/src/main/java/sh/ball/audio/engine/JavaAudioEngine.java +++ b/src/main/java/sh/ball/audio/engine/JavaAudioEngine.java @@ -47,51 +47,48 @@ public class JavaAudioEngine implements AudioEngine { // connects to a device that can support the format above (i.e. default audio device) this.source = AudioSystem.getSourceDataLine(format); - source.open(format); int bufferSize = calculateBufferSize(device, UNSTABLE_LATENCY_MS); - int remainingBufferSpace = source.getBufferSize() - bufferSize; byte[] buffer = new byte[bufferSize * 2]; + source.open(format, buffer.length); + source.start(); while (!stopped) { if (makeMoreStable || makeLessStable) { int newLatency = makeMoreStable ? STABLE_LATENCY_MS : UNSTABLE_LATENCY_MS; bufferSize = calculateBufferSize(device, newLatency); - remainingBufferSpace = source.getBufferSize() - bufferSize; buffer = new byte[bufferSize * 2]; isStable = makeMoreStable; makeMoreStable = false; makeLessStable = false; } - int delta = source.available() - remainingBufferSpace; - if (delta > 0) { - int requiredSamples = (delta + bufferSize) / FRAME_SIZE; - if (requiredSamples * NUM_CHANNELS > buffer.length / 2) { - buffer = new byte[requiredSamples * NUM_CHANNELS * 2]; - } + int requiredSamples = bufferSize / FRAME_SIZE; - for (int i = 0; i < requiredSamples; i++) { - try { - Vector2 channels = channelGenerator.call(); - // converting doubles from Vector2 into shorts and then bytes so - // that the byte buffer supports them - short left = (short) (channels.getX() * Short.MAX_VALUE); - short right = (short) (channels.getY() * Short.MAX_VALUE); - buffer[i * 4] = (byte) left; - buffer[i * 4 + 1] = (byte) (left >> 8); - buffer[i * 4 + 2] = (byte) right; - buffer[i * 4 + 3] = (byte) (right >> 8); - } catch (Exception e) { - e.printStackTrace(); - } - } - - source.write(buffer, 0, requiredSamples * FRAME_SIZE); + if (requiredSamples * NUM_CHANNELS > buffer.length / 2) { + buffer = new byte[requiredSamples * NUM_CHANNELS * 2]; } + + for (int i = 0; i < requiredSamples; i++) { + try { + Vector2 channels = channelGenerator.call(); + // converting doubles from Vector2 into shorts and then bytes so + // that the byte buffer supports them + short left = (short) (channels.getX() * Short.MAX_VALUE); + short right = (short) (channels.getY() * Short.MAX_VALUE); + buffer[i * 4] = (byte) left; + buffer[i * 4 + 1] = (byte) (left >> 8); + buffer[i * 4 + 2] = (byte) right; + buffer[i * 4 + 3] = (byte) (right >> 8); + } catch (Exception e) { + e.printStackTrace(); + } + } + + source.write(buffer, 0, requiredSamples * FRAME_SIZE); } source.stop(); this.device = null; diff --git a/src/main/java/sh/ball/gui/Gui.java b/src/main/java/sh/ball/gui/Gui.java index 86dbfef..a808b17 100644 --- a/src/main/java/sh/ball/gui/Gui.java +++ b/src/main/java/sh/ball/gui/Gui.java @@ -39,7 +39,6 @@ public class Gui extends Application { @Override public void start(Stage stage) throws Exception { - Thread.currentThread().setPriority(Thread.MAX_PRIORITY); System.setProperty("prism.lcdtext", "false"); FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/main.fxml"));