From e792b44d99676a363bc5e6e6d5c42881e756f956 Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Sun, 30 Jan 2022 12:14:35 -0700 Subject: WaveRecorder: fix hang in StreamingThread (#106) The read() could hang forever waiting for data when the WaveRecorder was stopped. Now it terminates the thread. Also fix bug in AudioFifo when partially full. It would not read any data! Fixes #105 --- src/main/java/com/jsyn/io/AudioFifo.java | 48 +++++++++++++++++++------------- 1 file changed, 29 insertions(+), 19 deletions(-) (limited to 'src/main/java/com/jsyn/io') diff --git a/src/main/java/com/jsyn/io/AudioFifo.java b/src/main/java/com/jsyn/io/AudioFifo.java index 0c563e4..b7321c6 100644 --- a/src/main/java/com/jsyn/io/AudioFifo.java +++ b/src/main/java/com/jsyn/io/AudioFifo.java @@ -37,6 +37,7 @@ public class AudioFifo implements AudioInputStream, AudioOutputStream { private int sizeMask; private boolean writeWaitEnabled = true; private boolean readWaitEnabled = true; + private volatile boolean mOpen = true; final Lock lock = new ReentrantLock(); final Condition notFull = lock.newCondition(); final Condition notEmpty = lock.newCondition(); @@ -69,7 +70,12 @@ public class AudioFifo implements AudioInputStream, AudioOutputStream { @Override public void close() { - // TODO Maybe we should tell any thread that is waiting that the FIFO is closed. + // Tell any thread that is waiting that the FIFO is closed. + mOpen = false; + lock.lock(); + notEmpty.signal(); + notFull.signal(); + lock.unlock(); } @Override @@ -78,20 +84,22 @@ public class AudioFifo implements AudioInputStream, AudioOutputStream { if (readWaitEnabled) { lock.lock(); try { - while (available() < 1) { + while (mOpen && available() < 1) { try { notEmpty.await(); } catch (InterruptedException e) { return Double.NaN; } } - value = readOneInternal(); + if (mOpen) { + value = readOneInternal(); + } } finally { lock.unlock(); } } else { - if (readIndex != writeIndex) { + if (mOpen && readIndex != writeIndex) { value = readOneInternal(); } } @@ -116,7 +124,7 @@ public class AudioFifo implements AudioInputStream, AudioOutputStream { if (writeWaitEnabled) { lock.lock(); try { - while (available() == buffer.length) + while (mOpen && available() == buffer.length) { try { notFull.await(); @@ -124,7 +132,9 @@ public class AudioFifo implements AudioInputStream, AudioOutputStream { return; // Silently fail } } - writeOneInternal(value); + if (mOpen) { + writeOneInternal(value); + } } finally { lock.unlock(); } @@ -154,20 +164,20 @@ public class AudioFifo implements AudioInputStream, AudioOutputStream { @Override public int read(double[] buffer, int start, int count) { - if (readWaitEnabled) { - for (int i = 0; i < count; i++) { - buffer[i + start] = read(); - } - } else { - if (available() < count) { - count = available(); - } else { - for (int i = 0; i < count; i++) { - buffer[i + start] = read(); - } - } + if (!mOpen) { + return 0; + } + if (!readWaitEnabled) { + count = Math.min(available(), count); + } + int numRead = 0; + for (int i = 0; mOpen && i < count; i++) { + double value = read(); + if (value == Double.NaN) break; + buffer[i + start] = value; + numRead++; } - return count; + return numRead; } @Override -- cgit v1.2.3