Android audioRecord to wav without save as File (Kotlin)

问题描述 投票:0回答:0

我正在使用 AudioRecord 录制音频。我需要的是以可播放格式 (wav) 将录制的音频保存为一个数组/变量。 我需要使用 AudioRecord,因为在获取音频的同时我还运行了一个语音识别器。所以 MediaRecorder 是别无选择的。 我实际上得到了一个可行的解决方案。唯一的问题是音频被写入文件。另外,我将 wav 标头添加到 pcm 的功能需要一个文件并将其再次存储在一个文件中。

我在寻找什么:在不将音频保存到文件的情况下完成所有这些。最后,我希望将音频放入数组或类似的东西中,以将此音频发送到 Flutter 并在那里使用它。

我的工作解决方案(with 将音频保存到文件):

private fun record() {
            val sampleRate = 16000
            val frameLength = 512
            val bufferSize = (sampleRate / 2).coerceAtLeast(minBufferSize)
            var audioRecord: AudioRecord? = null
            var buffer = ShortArray(frameLength)
            var bufferByte: ByteArray

            var fileName =  Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath + "/audio" + ".pcm"
       
            audioRecord = AudioRecord(
                    MediaRecorder.AudioSource.MIC,
                    sampleRate,
                    AudioFormat.CHANNEL_IN_MONO,
                    AudioFormat.ENCODING_PCM_16BIT,
                    bufferSize)
            audioRecord.startRecording()

            var outputStream: FileOutputStream?
            try {
                outputStream = FileOutputStream(fileName)
            } catch (e: FileNotFoundException) {
                return
            }
            while (!stop.get()) {
                var readBufferShortLength = audioRecord.read(buffer, 0, buffer.size)

                bufferByte = getBytes(buffer)
                try {
                    outputStream!!.write(bufferByte, 0, bufferByte.size)
                    // clean up file writing operations
                } catch (e: IOException) {
                    e.printStackTrace()
                }
             }
             outputStream.flush()
             outputStream.close()
          }

对于语音识别,它需要一个 ShortArray。要添加 wav 标头,它需要 ByteArray。 将 ShortArray 转换为 ByteArray:

fun shortToByte(shortArray: ShortArray): ByteArray {
        val buffer = ByteBuffer.allocate(shortArray.size * 2)
        buffer.order(ByteOrder.LITTLE_ENDIAN)
        buffer.asShortBuffer().put(shortArray)
        val bytes = buffer.array()
        return bytes
    }

转换添加wav标头:

@Throws(IOException::class)
    private fun rawToWave(rawFile: File, waveFile: File, sampleRate: Int) {
        val rawData = ByteArray(rawFile.length().toInt())
        var input: DataInputStream? = null
        try {
            input = DataInputStream(FileInputStream(rawFile))
            input.read(rawData)
        } finally {
            input?.close()
        }
        var output: DataOutputStream? = null
        try {
            output = DataOutputStream(FileOutputStream(waveFile))
            // WAVE header
            // see http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
            writeString(output, "RIFF") // chunk id
            writeInt(output, 36 + rawData.size) // chunk size
            writeString(output, "WAVE") // format
            writeString(output, "fmt ") // subchunk 1 id
            writeInt(output, 16) // subchunk 1 size
            writeShort(output, 1.toShort()) // audio format (1 = PCM)
            writeShort(output, 1.toShort()) // number of channels
            writeInt(output, sampleRate) // sample rate
            writeInt(output, sampleRate * 2) // byte rate     --------- Here changen maybe
            writeShort(output, 2.toShort()) // block align
            writeShort(output, 16.toShort()) // bits per sample
            writeString(output, "data") // subchunk 2 id
            writeInt(output, rawData.size) // subchunk 2 size
            // Audio data (conversion big endian -> little endian)
            val shorts = ShortArray(rawData.size / 2)
            ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts)
            val bytes: ByteBuffer = ByteBuffer.allocate(shorts.size * 2)
            for (s in shorts) {
                bytes.putShort(s)
            }
            output.write(fullyReadFileToBytes(rawFile))
        } finally {
            output?.close()
        }
    }

    @Throws(IOException::class)
    fun fullyReadFileToBytes(f: File): ByteArray? {
        val size = f.length().toInt()
        val bytes = ByteArray(size)
        val tmpBuff = ByteArray(size)
        val fis = FileInputStream(f)
        try {
            var read = fis.read(bytes, 0, size)
            if (read < size) {
                var remain = size - read
                while (remain > 0) {
                    read = fis.read(tmpBuff, 0, remain)
                    System.arraycopy(tmpBuff, 0, bytes, size - remain, read)
                    remain -= read
                }
            }
        } catch (e: IOException) {
            throw e
        } finally {
            fis.close()
        }
        return bytes
    }

    @Throws(IOException::class)
    private fun writeInt(output: DataOutputStream, value: Int) {
        output.write(value shr 0)
        output.write(value shr 8)
        output.write(value shr 16)
        output.write(value shr 24)
    }

    @Throws(IOException::class)
    private fun writeShort(output: DataOutputStream, value: Short) {
        var v = value.toInt()
        output.write(v shr 0)
        output.write(v shr 8)
    }

    @Throws(IOException::class)
    private fun writeString(output: DataOutputStream, value: String) {
        for (i in 0 until value.length) {
            output.write(value[i].code)     //  ------ Here changen maybe
        }
    }

非常感谢您的支持。

kotlin audio wav record audiorecord
© www.soinside.com 2019 - 2024. All rights reserved.