how to record .wav format file in android

前端 未结 4 884
甜味超标
甜味超标 2020-12-05 15:39

I would like to record .wav files using android. is there any way to do this?

4条回答
  •  盖世英雄少女心
    2020-12-05 16:24

    You have to use AudioRecord class and write the wav header data by yourself. This code should include all you need.

    WavRecorder(val context: Context) {
        private var recorder: AudioRecord? = null
        private var isRecording = false
    
        private var recordingThread: Thread? = null
    
        fun startRecording(_filename: String? = null, internalStorage: Boolean = false) {
            val filename = _filename ?: "recording-${System.currentTimeMillis()}.wav"
    
            val path = if (internalStorage) context.filesDir?.path + "/$filename"
            else context.externalCacheDir?.path + "/$filename"
    
            recorder = AudioRecord(MediaRecorder.AudioSource.MIC,
                    RECORDER_SAMPLE_RATE, RECORDER_CHANNELS,
                    RECORDER_AUDIO_ENCODING, 512)
    
            recorder?.startRecording()
            isRecording = true
    
            recordingThread = thread(true) {
                writeAudioDataToFile(path)
            }
        }
    
    
        fun stopRecording() {
            recorder?.run {
                isRecording = false;
                stop()
                release()
                recordingThread = null
                recorder = null
            }
        }
    
        private fun short2byte(sData: ShortArray): ByteArray {
            val arrSize = sData.size
            val bytes = ByteArray(arrSize * 2)
            for (i in 0 until arrSize) {
                bytes[i * 2] = (sData[i] and 0x00FF).toByte()
                bytes[i * 2 + 1] = (sData[i].toInt() shr 8).toByte()
                sData[i] = 0
            }
            return bytes
        }
    
        private fun writeAudioDataToFile(path: String) {
            val sData = ShortArray(BufferElements2Rec)
            var os: FileOutputStream? = null
            try {
                os = FileOutputStream(path)
            } catch (e: FileNotFoundException) {
                e.printStackTrace()
            }
    
            val data = arrayListOf()
    
            for (byte in wavFileHeader()) {
                data.add(byte)
            }
    
            while (isRecording) {
                // gets the voice output from microphone to byte format
                recorder?.read(sData, 0, BufferElements2Rec)
                try {
                    val bData = short2byte(sData)
                    for (byte in bData)
                        data.add(byte)
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
    
            updateHeaderInformation(data)
    
            os?.write(data.toByteArray())
    
            try {
                os?.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    
    
        /**
         * Constructs header for wav file format
         */
        private fun wavFileHeader(): ByteArray {
            val headerSize = 44
            val header = ByteArray(headerSize)
    
            header[0] = 'R'.toByte() // RIFF/WAVE header
            header[1] = 'I'.toByte()
            header[2] = 'F'.toByte()
            header[3] = 'F'.toByte()
    
            header[4] = (0 and 0xff).toByte() // Size of the overall file, 0 because unknown
            header[5] = (0 shr 8 and 0xff).toByte()
            header[6] = (0 shr 16 and 0xff).toByte()
            header[7] = (0 shr 24 and 0xff).toByte()
    
            header[8] = 'W'.toByte()
            header[9] = 'A'.toByte()
            header[10] = 'V'.toByte()
            header[11] = 'E'.toByte()
    
            header[12] = 'f'.toByte() // 'fmt ' chunk
            header[13] = 'm'.toByte()
            header[14] = 't'.toByte()
            header[15] = ' '.toByte()
    
            header[16] = 16 // Length of format data
            header[17] = 0
            header[18] = 0
            header[19] = 0
    
            header[20] = 1 // Type of format (1 is PCM)
            header[21] = 0
    
            header[22] = NUMBER_CHANNELS.toByte()
            header[23] = 0
    
            header[24] = (RECORDER_SAMPLE_RATE and 0xff).toByte() // Sampling rate
            header[25] = (RECORDER_SAMPLE_RATE shr 8 and 0xff).toByte()
            header[26] = (RECORDER_SAMPLE_RATE shr 16 and 0xff).toByte()
            header[27] = (RECORDER_SAMPLE_RATE shr 24 and 0xff).toByte()
    
            header[28] = (BYTE_RATE and 0xff).toByte() // Byte rate = (Sample Rate * BitsPerSample * Channels) / 8
            header[29] = (BYTE_RATE shr 8 and 0xff).toByte()
            header[30] = (BYTE_RATE shr 16 and 0xff).toByte()
            header[31] = (BYTE_RATE shr 24 and 0xff).toByte()
    
            header[32] = (NUMBER_CHANNELS * BITS_PER_SAMPLE / 8).toByte() //  16 Bits stereo
            header[33] = 0
    
            header[34] = BITS_PER_SAMPLE.toByte() // Bits per sample
            header[35] = 0
    
            header[36] = 'd'.toByte()
            header[37] = 'a'.toByte()
            header[38] = 't'.toByte()
            header[39] = 'a'.toByte()
    
            header[40] = (0 and 0xff).toByte() // Size of the data section.
            header[41] = (0 shr 8 and 0xff).toByte()
            header[42] = (0 shr 16 and 0xff).toByte()
            header[43] = (0 shr 24 and 0xff).toByte()
    
            return header
        }
    
        private fun updateHeaderInformation(data: ArrayList) {
            val fileSize = data.size
            val contentSize = fileSize - 44
    
            data[4] = (fileSize and 0xff).toByte() // Size of the overall file
            data[5] = (fileSize shr 8 and 0xff).toByte()
            data[6] = (fileSize shr 16 and 0xff).toByte()
            data[7] = (fileSize shr 24 and 0xff).toByte()
    
            data[40] = (contentSize and 0xff).toByte() // Size of the data section.
            data[41] = (contentSize shr 8 and 0xff).toByte()
            data[42] = (contentSize shr 16 and 0xff).toByte()
            data[43] = (contentSize shr 24 and 0xff).toByte()
        }
    
        companion object {
            const val RECORDER_SAMPLE_RATE = 8000
            const val RECORDER_CHANNELS: Int = android.media.AudioFormat.CHANNEL_IN_MONO
            const val RECORDER_AUDIO_ENCODING: Int = android.media.AudioFormat.ENCODING_PCM_16BIT
            const val BITS_PER_SAMPLE: Short = 16
            const val NUMBER_CHANNELS: Short = 1
            const val BYTE_RATE = RECORDER_SAMPLE_RATE * NUMBER_CHANNELS * 16 / 8
    
            var BufferElements2Rec = 1024
        }
    }
    

提交回复
热议问题