summaryrefslogtreecommitdiff
path: root/LoopbackApp/app/src/main/java/org/drrickorang/loopback/WaveDataRingBuffer.java
diff options
context:
space:
mode:
Diffstat (limited to 'LoopbackApp/app/src/main/java/org/drrickorang/loopback/WaveDataRingBuffer.java')
-rw-r--r--LoopbackApp/app/src/main/java/org/drrickorang/loopback/WaveDataRingBuffer.java169
1 files changed, 123 insertions, 46 deletions
diff --git a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/WaveDataRingBuffer.java b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/WaveDataRingBuffer.java
index 935c805..ee47238 100644
--- a/LoopbackApp/app/src/main/java/org/drrickorang/loopback/WaveDataRingBuffer.java
+++ b/LoopbackApp/app/src/main/java/org/drrickorang/loopback/WaveDataRingBuffer.java
@@ -16,14 +16,20 @@
package org.drrickorang.loopback;
+import java.util.Arrays;
+
/**
- * Maintains a recording of wave data of last n seconds
+ * Maintains two ring buffers for recording wav data
+ * At any one time one buffer is available for writing to file while one is recording incoming data
*/
public class WaveDataRingBuffer {
- private final double[] mWaveRecord;
- private volatile int index = 0; // between 0 and mWaveRecord.length - 1
- private boolean arrayFull = false; // true after index has wrapped
+ public interface ReadableWaveDeck {
+ boolean writeToFile(AudioFileOutput audioFile);
+ }
+
+ private WaveDeck mLoadedDeck;
+ private WaveDeck mShelvedDeck;
public WaveDataRingBuffer(int size) {
if (size < Constant.SAMPLING_RATE_MIN * Constant.BUFFER_TEST_DURATION_SECONDS_MIN) {
@@ -31,66 +37,137 @@ public class WaveDataRingBuffer {
} else if (size > Constant.SAMPLING_RATE_MAX * Constant.BUFFER_TEST_DURATION_SECONDS_MAX) {
size = Constant.SAMPLING_RATE_MAX * Constant.BUFFER_TEST_DURATION_SECONDS_MAX;
}
+ mLoadedDeck = new WaveDeck(size);
+ mShelvedDeck = new WaveDeck(size);
+ }
- mWaveRecord = new double[size];
+ public synchronized void writeWaveData(double[] data, int srcPos, int length) {
+ mLoadedDeck.writeWaveData(data, srcPos, length);
+ }
+
+ public synchronized double[] getWaveRecord() {
+ return mLoadedDeck.getWaveRecord();
+ }
+
+ private void SwapDecks() {
+ WaveDeck temp = mShelvedDeck;
+ mShelvedDeck = mLoadedDeck;
+ mLoadedDeck = temp;
+ }
+
+ /**
+ * Returns currently writing buffer as writeToFile interface, load erased shelved deck for write
+ * If shelved deck is still being read returns null
+ **/
+ public synchronized ReadableWaveDeck getWaveDeck() {
+ if (!mShelvedDeck.isBeingRead()) {
+ SwapDecks();
+ mShelvedDeck.readyForRead();
+ mLoadedDeck.reset();
+ return mShelvedDeck;
+ } else {
+ return null;
+ }
}
/**
- * Write length number of doubles from data into ring buffer from starting srcPos
+ * Maintains a recording of wave data of last n seconds
*/
- public synchronized void writeWaveData(double[] data, int srcPos, int length) {
- if (length > data.length - srcPos) {
- // requested to write more data than available
- // bad request leave data un-affected
- return;
+ public class WaveDeck implements ReadableWaveDeck {
+
+ private double[] mWaveRecord;
+ private volatile int mIndex = 0; // between 0 and mWaveRecord.length - 1
+ private boolean mArrayFull = false; // true after mIndex has wrapped
+ private boolean mIsBeingRead = false;
+
+ public WaveDeck(int size) {
+ mWaveRecord = new double[size];
}
- if (length >= mWaveRecord.length) {
- // requested write would fill or exceed ring buffer capacity
- // fill ring buffer with last segment of requested write
- System.arraycopy(data, srcPos + (length - mWaveRecord.length), mWaveRecord, 0,
- mWaveRecord.length);
- index = 0;
- } else if (mWaveRecord.length - index > length) {
- // write requested data from current offset
- System.arraycopy(data, srcPos, mWaveRecord, index, length);
- index += length;
- } else {
- // write to available buffer then wrap and overwrite previous records
- if (!arrayFull) {
- arrayFull = true;
+ /**
+ * Write length number of doubles from data into ring buffer from starting srcPos
+ */
+ public void writeWaveData(double[] data, int srcPos, int length) {
+ if (length > data.length - srcPos) {
+ // requested to write more data than available
+ // bad request leave data un-affected
+ return;
}
- int availBuff = mWaveRecord.length - index;
+ if (length >= mWaveRecord.length) {
+ // requested write would fill or exceed ring buffer capacity
+ // fill ring buffer with last segment of requested write
+ System.arraycopy(data, srcPos + (length - mWaveRecord.length), mWaveRecord, 0,
+ mWaveRecord.length);
+ mIndex = 0;
+ } else if (mWaveRecord.length - mIndex > length) {
+ // write requested data from current offset
+ System.arraycopy(data, srcPos, mWaveRecord, mIndex, length);
+ mIndex += length;
+ } else {
+ // write to available buffer then wrap and overwrite previous records
+ if (!mArrayFull) {
+ mArrayFull = true;
+ }
+
+ int availBuff = mWaveRecord.length - mIndex;
+
+ System.arraycopy(data, srcPos, mWaveRecord, mIndex, availBuff);
+ System.arraycopy(data, srcPos + availBuff, mWaveRecord, 0, length - availBuff);
+
+ mIndex = length - availBuff;
+
+ }
- System.arraycopy(data, srcPos, mWaveRecord, index, availBuff);
- System.arraycopy(data, srcPos + availBuff, mWaveRecord, 0, length - availBuff);
+ }
- index = length - availBuff;
+ /**
+ * Returns a private copy of recorded wave data
+ *
+ * @return double array of wave recording, rearranged with oldest sample at first index
+ */
+ public double[] getWaveRecord() {
+ double outputBuffer[] = new double[mWaveRecord.length];
+
+ if (!mArrayFull) {
+ //return partially filled sample with trailing zeroes
+ System.arraycopy(mWaveRecord, 0, outputBuffer, 0, mIndex);
+ Arrays.fill(outputBuffer, mIndex+1, outputBuffer.length-1, 0);
+ } else {
+ //copy buffer to contiguous sample and return unwrapped array
+ System.arraycopy(mWaveRecord, mIndex, outputBuffer, 0, mWaveRecord.length - mIndex);
+ System.arraycopy(mWaveRecord, 0, outputBuffer, mWaveRecord.length - mIndex, mIndex);
+ }
+ return outputBuffer;
}
- }
+ /** Make buffer available for new recording **/
+ public void reset() {
+ mIndex = 0;
+ mArrayFull = false;
+ }
- /**
- * Returns a private copy of recorded wave data
- *
- * @return double array of wave recording, rearranged with oldest sample at first index
- */
- public synchronized double[] getWaveRecord() {
- double outputBuffer[] = new double[mWaveRecord.length];
+ public boolean isBeingRead() {
+ return mIsBeingRead;
+ }
- if (!arrayFull) {
- //return partially filled sample with trailing zeroes
- System.arraycopy(mWaveRecord, 0, outputBuffer, 0, index);
- } else {
- //copy buffer to contiguous sample and return unwrapped array
- System.arraycopy(mWaveRecord, index, outputBuffer, 0, mWaveRecord.length - index);
- System.arraycopy(mWaveRecord, 0, outputBuffer, mWaveRecord.length - index, index);
+ private void readyForRead() {
+ mIsBeingRead = true;
}
- return outputBuffer;
+ @Override
+ public boolean writeToFile(AudioFileOutput audioFile) {
+ boolean successfulWrite;
+ if (mArrayFull) {
+ successfulWrite = audioFile.writeRingBufferData(mWaveRecord, mIndex, mIndex);
+ } else {
+ // Write only filled part of array to file
+ successfulWrite = audioFile.writeRingBufferData(mWaveRecord, 0, mIndex);
+ }
+ mIsBeingRead = false;
+ return successfulWrite;
+ }
}
-
}