Skip to content

Commit

Permalink
RecorderThread: Use non-blocking reads from AudioRecord
Browse files Browse the repository at this point in the history
On Samsung devices, when a call ends, AudioRecord.read() blocks until
another call becomes active, which prevents recordings from stopping at
the correct time. This behavior does not happen in AOSP.

To work around this, use non-blocking reads with a sleep interval of the
AudioRecord minimum buffer size. This gives the recording loop a chance
to check if recording has been cancelled.

Issue: #143

Signed-off-by: Andrew Gunnerson <chillermillerlong@hotmail.com>
  • Loading branch information
chenxiaolong committed Oct 9, 2022
1 parent 12b318d commit 17fa150
Showing 1 changed file with 9 additions and 4 deletions.
13 changes: 9 additions & 4 deletions app/src/main/java/com/chiller3/bcr/RecorderThread.kt
Expand Up @@ -496,7 +496,7 @@ class RecorderThread(
*
* @param audioRecord [AudioRecord.startRecording] must have been called
* @param encoder [Encoder.start] must have been called
* @param bufSize Size of buffer to use for each [AudioRecord.read] operation
* @param bufSize Minimum buffer size for each [AudioRecord.read] operation
*
* @throws Exception if the audio recorder or encoder encounters an error
*/
Expand All @@ -508,10 +508,14 @@ class RecorderThread(
val buffer = ByteBuffer.allocateDirect(bufSize * 2)
val bufferFrames = buffer.capacity().toLong() / frameSize
val bufferNs = bufferFrames * 1_000_000_000L / audioRecord.sampleRate
Log.d(tag, "Buffer is ${buffer.capacity()} bytes, $bufferFrames frames, ${bufferNs}ns")

while (!isCancelled) {
val begin = System.nanoTime()
val n = audioRecord.read(buffer, buffer.remaining())
// We do a non-blocking read because on Samsung devices, when the call ends, the audio
// device immediately stops producing data and blocks forever until the next call is
// active.
val n = audioRecord.read(buffer, buffer.remaining(), AudioRecord.READ_NON_BLOCKING)
val recordElapsed = System.nanoTime() - begin
var encodeElapsed = 0L

Expand All @@ -520,8 +524,9 @@ class RecorderThread(
isCancelled = true
captureFailed = true
} else if (n == 0) {
Log.e(tag, "Unexpected EOF from AudioRecord")
isCancelled = true
// Wait for half of buffer size
sleep(bufferNs / 1_000_000L / 2)
continue
} else {
buffer.limit(n)

Expand Down

0 comments on commit 17fa150

Please sign in to comment.