From 426b478fe18360baead702b72f6a18aa621658b4 Mon Sep 17 00:00:00 2001 From: xufuji456 Date: Tue, 22 Mar 2022 18:07:32 +0800 Subject: [PATCH] Feature: convert pcm to wav format --- .../controller/AudioRecordController.kt | 3 + .../com/frank/androidmedia/util/WavHeader.kt | 81 +++++++++++++++++++ .../com/frank/androidmedia/util/WavUtil.kt | 64 +++++++++++++++ .../com/frank/ffmpeg/activity/BaseActivity.kt | 6 +- 4 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 AndroidMedia/src/main/java/com/frank/androidmedia/util/WavHeader.kt create mode 100644 AndroidMedia/src/main/java/com/frank/androidmedia/util/WavUtil.kt diff --git a/AndroidMedia/src/main/java/com/frank/androidmedia/controller/AudioRecordController.kt b/AndroidMedia/src/main/java/com/frank/androidmedia/controller/AudioRecordController.kt index 8db8da8..ff08970 100644 --- a/AndroidMedia/src/main/java/com/frank/androidmedia/controller/AudioRecordController.kt +++ b/AndroidMedia/src/main/java/com/frank/androidmedia/controller/AudioRecordController.kt @@ -87,6 +87,9 @@ open class AudioRecordController { e.printStackTrace() } } + // convert pcm to wav + val wavPath = File(mPath).parent + "/test.wav" + WavUtil.makePCMToWAVFile(mPath, wavPath, true) } } diff --git a/AndroidMedia/src/main/java/com/frank/androidmedia/util/WavHeader.kt b/AndroidMedia/src/main/java/com/frank/androidmedia/util/WavHeader.kt new file mode 100644 index 0000000..f8043f1 --- /dev/null +++ b/AndroidMedia/src/main/java/com/frank/androidmedia/util/WavHeader.kt @@ -0,0 +1,81 @@ +package com.frank.androidmedia.util + +import java.io.ByteArrayOutputStream +import java.io.IOException + +/** + * The header of wave format + * @author frank + * @date 2022/3/22 + */ +internal class WavHeader { + var riffID = charArrayOf('R', 'I', 'F', 'F') + @JvmField + var riffSize = 0 + var riffType = charArrayOf('W', 'A', 'V', 'E') + var formatID = charArrayOf('f', 'm', 't', ' ') + @JvmField + var formatSize = 0 + @JvmField + var formatTag: Short = 0 + @JvmField + var numChannels: Short = 0 + @JvmField + var sampleRate = 0 + @JvmField + var avgBytesPerSec = 0 + @JvmField + var blockAlign: Short = 0 + @JvmField + var bitsPerSample: Short = 0 + var dataID = charArrayOf('d', 'a', 't', 'a') + @JvmField + var dataSize = 0 + + @get:Throws(IOException::class) + val header: ByteArray + get() { + val bos = ByteArrayOutputStream() + writeChar(bos, riffID) + writeInt(bos, riffSize) + writeChar(bos, riffType) + writeChar(bos, formatID) + writeInt(bos, formatSize) + writeShort(bos, formatTag.toInt()) + writeShort(bos, numChannels.toInt()) + writeInt(bos, sampleRate) + writeInt(bos, avgBytesPerSec) + writeShort(bos, blockAlign.toInt()) + writeShort(bos, bitsPerSample.toInt()) + writeChar(bos, dataID) + writeInt(bos, dataSize) + bos.flush() + val r = bos.toByteArray() + bos.close() + return r + } + + @Throws(IOException::class) + private fun writeShort(bos: ByteArrayOutputStream, s: Int) { + val data = ByteArray(2) + data[1] = (s shl 16 shr 24).toByte() + data[0] = (s shl 24 shr 24).toByte() + bos.write(data) + } + + @Throws(IOException::class) + private fun writeInt(bos: ByteArrayOutputStream, n: Int) { + val buf = ByteArray(4) + buf[3] = (n shr 24).toByte() + buf[2] = (n shl 8 shr 24).toByte() + buf[1] = (n shl 16 shr 24).toByte() + buf[0] = (n shl 24 shr 24).toByte() + bos.write(buf) + } + + private fun writeChar(bos: ByteArrayOutputStream, id: CharArray) { + for (c in id) { + bos.write(c.toInt()) + } + } +} \ No newline at end of file diff --git a/AndroidMedia/src/main/java/com/frank/androidmedia/util/WavUtil.kt b/AndroidMedia/src/main/java/com/frank/androidmedia/util/WavUtil.kt new file mode 100644 index 0000000..58de8db --- /dev/null +++ b/AndroidMedia/src/main/java/com/frank/androidmedia/util/WavUtil.kt @@ -0,0 +1,64 @@ +package com.frank.androidmedia.util + +import android.util.Log +import java.io.* + +/** + * Convert pcm to wav + * + * @author frank + * @date 2022/3/22 + */ +object WavUtil { + + fun makePCMToWAVFile(pcmPath: String?, wavPath: String?, deletePcmFile: Boolean): Boolean { + val buffer: ByteArray + val file = File(pcmPath) + if (!file.exists()) { + return false + } + val len = file.length().toInt() + val header = WavHeader() + header.riffSize = len + (44 - 8) + header.formatSize = 16 + header.bitsPerSample = 16 + header.numChannels = 2 + header.formatTag = 0x0001 + header.sampleRate = 44100 + header.blockAlign = (header.numChannels * header.bitsPerSample / 8).toShort() + header.avgBytesPerSec = header.blockAlign * header.sampleRate + header.dataSize = len + val h: ByteArray = try { + header.header + } catch (e1: IOException) { + Log.e("WavUtil", e1.message) + return false + } + if (h.size != 44) return false + val dstFile = File(wavPath) + if (dstFile.exists()) dstFile.delete() + try { + buffer = ByteArray(1024 * 4) + val inStream: InputStream + val ouStream: OutputStream + ouStream = BufferedOutputStream(FileOutputStream(wavPath)) + ouStream.write(h, 0, h.size) + inStream = BufferedInputStream(FileInputStream(file)) + var size = inStream.read(buffer) + while (size != -1) { + ouStream.write(buffer) + size = inStream.read(buffer) + } + inStream.close() + ouStream.close() + } catch (e: IOException) { + Log.e("WavUtil", e.message) + return false + } + if (deletePcmFile) { + file.delete() + } + Log.i("WavUtil", "makePCMToWAVFile success...") + return true + } +} \ No newline at end of file diff --git a/app/src/main/java/com/frank/ffmpeg/activity/BaseActivity.kt b/app/src/main/java/com/frank/ffmpeg/activity/BaseActivity.kt index a799b2c..ffcc711 100644 --- a/app/src/main/java/com/frank/ffmpeg/activity/BaseActivity.kt +++ b/app/src/main/java/com/frank/ffmpeg/activity/BaseActivity.kt @@ -125,7 +125,11 @@ abstract class BaseActivity : AppCompatActivity(), View.OnClickListener { private val TAG = BaseActivity::class.java.simpleName private const val REQUEST_CODE = 1234 - private val permissions = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO) + private val permissions = arrayOf( + Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.CAMERA, + Manifest.permission.RECORD_AUDIO) } }