From 64b1ece9b7f32643526b36939e2d98a8042c3ebd Mon Sep 17 00:00:00 2001 From: James Ball Date: Sun, 13 Nov 2022 11:36:31 +0000 Subject: [PATCH] Various UI clean-ups related to no input devices or faulty devices --- .../java/sh/ball/audio/ShapeAudioPlayer.java | 40 ++++++++++--------- .../sh/ball/audio/engine/JavaAudioEngine.java | 10 +++-- .../gui/controller/GeneralController.java | 5 ++- .../ball/gui/controller/MainController.java | 19 ++++++--- src/main/resources/fxml/main.fxml | 8 +++- 5 files changed, 51 insertions(+), 31 deletions(-) diff --git a/src/main/java/sh/ball/audio/ShapeAudioPlayer.java b/src/main/java/sh/ball/audio/ShapeAudioPlayer.java index cad3e5a..63d99cb 100644 --- a/src/main/java/sh/ball/audio/ShapeAudioPlayer.java +++ b/src/main/java/sh/ball/audio/ShapeAudioPlayer.java @@ -13,7 +13,6 @@ import sh.ball.audio.engine.AudioInputListener; import sh.ball.audio.engine.AudioSample; import sh.ball.audio.midi.MidiCommunicator; import sh.ball.audio.midi.MidiNote; -import sh.ball.engine.Vector3; import sh.ball.shapes.Shape; import sh.ball.shapes.Vector2; @@ -92,6 +91,7 @@ public class ShapeAudioPlayer implements AudioPlayer> { private double[] micSamples; private boolean lineInEnabled = false; private boolean inputConnected = false; + private Runnable inputDisconnected; private AudioDevice device; @@ -162,33 +162,35 @@ public class ShapeAudioPlayer implements AudioPlayer> { } } + public void setInputDisconnected(Runnable inputDisconnected) { + this.inputDisconnected = inputDisconnected; + } + + private void fetchMicSamples() { + try { + double[] newSamples = micSampleQueue.poll(1, TimeUnit.SECONDS); + inputConnected = newSamples != null; + if (inputConnected) { + micSamples = newSamples; + } else if (inputDisconnected != null) { + inputDisconnected.run(); + } + } catch (InterruptedException e) { + logger.log(Level.SEVERE, "Failed to get mic samples", e); + } + } + private Vector2 generateChannels() { Vector2 channels = new Vector2(); if (inputConnected) { if (micSamples == null) { - try { - double[] newSamples = micSampleQueue.poll(1, TimeUnit.SECONDS); - inputConnected = newSamples != null; - if (newSamples != null) { - micSamples = newSamples; - } - } catch (InterruptedException e) { - logger.log(Level.SEVERE, "Failed to get mic samples", e); - } + fetchMicSamples(); } channels = new Vector2(micSamples[micSampleIndex++], micSamples[micSampleIndex++]); if (micSampleIndex >= micSamples.length - 1) { - try { - double[] newSamples = micSampleQueue.poll(1, TimeUnit.SECONDS); - inputConnected = newSamples != null; - if (newSamples != null) { - micSamples = newSamples; - } - } catch (InterruptedException e) { - logger.log(Level.SEVERE, "Failed to get mic samples", e); - } + fetchMicSamples(); micSampleIndex = 0; } } diff --git a/src/main/java/sh/ball/audio/engine/JavaAudioEngine.java b/src/main/java/sh/ball/audio/engine/JavaAudioEngine.java index 0f925d0..f448676 100644 --- a/src/main/java/sh/ball/audio/engine/JavaAudioEngine.java +++ b/src/main/java/sh/ball/audio/engine/JavaAudioEngine.java @@ -150,7 +150,7 @@ public class JavaAudioEngine implements AudioEngine { for (Mixer.Info info : inputDeviceInfos) { Stream.of(192000, 96000, 48000, 44100).forEach(rate -> - Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12).forEach(channels -> { + Stream.of(1, 2).forEach(channels -> { try { AudioFormat format = new AudioFormat((float) rate, BIT_DEPTH, channels, SIGNED_SAMPLE, BIG_ENDIAN); AudioSystem.getTargetDataLine(format, info); @@ -228,7 +228,11 @@ public class JavaAudioEngine implements AudioEngine { while (!stopped) { float resampleFactor = (float) sampleRate / (float) device.sampleRate(); - double[] out = new double[channelScalar * (int) (resampleFactor * buffer.length / 2)]; + int outLength = channelScalar * (int) (resampleFactor * buffer.length / 2); + if (outLength % 2 != 0) { + outLength--; + } + double[] out = new double[outLength]; microphone.read(buffer, 0, buffer.length); for (int i = 0; i < buffer.length - 3; i += 4) { @@ -247,7 +251,7 @@ public class JavaAudioEngine implements AudioEngine { r.process(resampleFactor, floatSrcLeft, 0, floatSrcLeft.length, true, floatOutLeft, 0, out.length / 2); r.process(resampleFactor, floatSrcRight, 0, floatSrcRight.length, true, floatOutRight, 0, out.length / 2); - for (int i = 0; i < out.length - 1; i += 2) { + for (int i = 0; i < out.length; i += 2) { out[i] = floatOutLeft[i / 2]; out[i + 1] = floatOutRight[i / 2]; } diff --git a/src/main/java/sh/ball/gui/controller/GeneralController.java b/src/main/java/sh/ball/gui/controller/GeneralController.java index c3d2333..dcdf2db 100644 --- a/src/main/java/sh/ball/gui/controller/GeneralController.java +++ b/src/main/java/sh/ball/gui/controller/GeneralController.java @@ -329,7 +329,10 @@ public class GeneralController implements Initializable, SubController { } @Override - public void micNotAvailable() {} + public void micNotAvailable() { + lineInToggle.setDisable(true); + lineInToggle.setContent("M19 11c0 1.19-.34 2.3-.9 3.28l-1.23-1.23c.27-.62.43-1.31.43-2.05H19m-4 .16L9 5.18V5a3 3 0 0 1 3-3a3 3 0 0 1 3 3v6.16M4.27 3L21 19.73L19.73 21l-4.19-4.19c-.77.46-1.63.77-2.54.91V21h-2v-3.28c-3.28-.49-6-3.31-6-6.72h1.7c0 3 2.54 5.1 5.3 5.1c.81 0 1.6-.19 2.31-.52l-1.66-1.66L12 14a3 3 0 0 1-3-3v-.72L3 4.27L4.27 3Z"); + } public void setFrameSourceName(String name) { this.frameSourceName = name; diff --git a/src/main/java/sh/ball/gui/controller/MainController.java b/src/main/java/sh/ball/gui/controller/MainController.java index 696e35f..53dd79c 100644 --- a/src/main/java/sh/ball/gui/controller/MainController.java +++ b/src/main/java/sh/ball/gui/controller/MainController.java @@ -1565,13 +1565,9 @@ public class MainController implements Initializable, FrequencyListener, MidiLis audioPlayer.addListener(audioPlayer); audioPlayer.inputConnected(); new Thread(() -> audioPlayer.listen(defaultInputDevice)).start(); + audioPlayer.setInputDisconnected(() -> Platform.runLater(this::setMicNotAvailable)); } else { - subControllers().forEach(SubController::micNotAvailable); - micSelected().forEach(prop -> { - if (prop != null) { - prop.setValue(false); - } - }); + setMicNotAvailable(); } updateRecentFiles(); @@ -1588,6 +1584,17 @@ public class MainController implements Initializable, FrequencyListener, MidiLis new Thread(() -> sendAudioDataToWebSocket(webSocketServer)).start(); } + private void setMicNotAvailable() { + Platform.runLater(() -> { + subControllers().forEach(SubController::micNotAvailable); + micSelected().forEach(prop -> { + if (prop != null) { + prop.setValue(false); + } + }); + }); + } + public void setRecentFiles(Callable> recentFiles) { this.recentFiles = recentFiles; } diff --git a/src/main/resources/fxml/main.fxml b/src/main/resources/fxml/main.fxml index ff970db..c2023bb 100644 --- a/src/main/resources/fxml/main.fxml +++ b/src/main/resources/fxml/main.fxml @@ -49,7 +49,7 @@ @@ -59,7 +59,11 @@