Saving FloatArray audio buffer to a wav file on Android

1k Views Asked by At

I'm having issues finding a solution to saving a FloatArray buffer of audio data produced from TarsosDSP on Android, using Kotlin. The goal is to have a buffer of 1 second of audio, that is continuously updated with new buffer data, and older data discarded. I wish to save this buffer when requested.

I've tried to find a solution using the TarsosDSP library, but it want to write a continuous stream to a wav file; I need it limited to only one second, and have saved on demand. This WavFileWriter looked promising -> https://github.com/philburk/jsyn/blob/master/src/com/jsyn/util/WaveFileWriter.java but as I had added it to my android project, javax was needed. I didn't know until looking up what javax was, and it was not supported in android. Trying to find a library that could solve this issue turned up with little results.

private val SAMPLE_RATE = 16000
private val BUFFER_SIZE = 1024
private val SECONDS = 1.0
private val sampleFileName: String = "audio_sample.wav"
private var audioBuffer = FloatArray(SAMPLE_RATE * SECONDS.toInt())

private var dispatcher =
        AudioDispatcherFactory.fromDefaultMicrophone(SAMPLE_RATE, BUFFER_SIZE, 128)
init {

blankProcessor = object : AudioProcessor {
   override fun processingFinished() {}

   override fun process(audioEvent: AudioEvent): Boolean {
      var buffer = audioEvent.floatBuffer
      val insertPoint = audioBuffer.lastIndex - buffer.lastIndex
      Arrays.copyOfRange(audioBuffer, insertPoint, audioBuffer.size)
                    .copyInto(audioBuffer, 0)
      buffer.copyInto(audioBuffer, insertPoint)
      return true
    }
}

dispatcher.addAudioProcessor(blankProcessor)

audioThread = Thread(dispatcher, "Audio Thread")
}


private fun writeWavFile() {
   val file = File(context.cacheDir.absolutePath + "/" + sampleFileName)
   // missing wav write code
}
1

There are 1 best solutions below

0
On

TarsosDSP offers the WriterProcessor class, for writing audio to file:

https://github.com/JorenSix/TarsosDSP/blob/c26e5004e203ee79be1ec25c2603b1f11b69d276/src/core/be/tarsos/dsp/writer/WriterProcessor.java

Here's your modified example:

private var dispatcher =
        AudioDispatcherFactory.fromDefaultMicrophone(SAMPLE_RATE, BUFFER_SIZE, 128)

init {

blankProcessor = object : AudioProcessor {
   override fun processingFinished() {}

   override fun process(audioEvent: AudioEvent): Boolean {
      var buffer = audioEvent.floatBuffer
      val insertPoint = audioBuffer.lastIndex - buffer.lastIndex
      Arrays.copyOfRange(audioBuffer, insertPoint, audioBuffer.size)
                    .copyInto(audioBuffer, 0)
      buffer.copyInto(audioBuffer, insertPoint)
      return true
    }
}

dispatcher.addAudioProcessor(blankProcessor)

// The important bit

val outputFile = File(context.filesDir, "file_name")
val randomAccessFile = RandomAccessFile(outputFile, "rw")
val fileWriter = WriterProcessor(audioFormat, randomAccessFile)

dispatcher.addAudioProcessor(fileWriter)

audioThread = Thread(dispatcher, "Audio Thread")
}