在 Android 项目中需要根据音频解析的结果从 PCM 编码的原始音频文件中裁剪指定时间段的音频数据,需要计算开始和结束时间对应的文件长度,然后裁剪音频文件,获得只包含指定时间的音频文件。
如下是根据给定的时间点计算它对应的文件大小:
package cn.itmob.audio.process
object AudioUtil {
// 采样频率: 16K
internal val AUDIO_SAMPLE_RATE = 16000
// 采样位数
internal val BIT_PER_SAMPLE: Int = 16
// 声道数量
internal var CHANNEL_COUNT = 1
// 当前采样率等配置下每秒钟音频的字节大小
val sizePerSeconds = AUDIO_SAMPLE_RATE * BIT_PER_SAMPLE * CHANNEL_COUNT / 8
/**
* 根据给定的毫秒为单位的音频时长计算它的视频文件的大小
*/
private fun calculateDurationToSize(millions: Long): Long {
return (sizePerSeconds * (millions / 1000F)).toLong()
}
}
根据计算的起始和结束时间的文件大小裁剪音频文件:
package cn.itmob.audio.process
fun cropAudio(
inputPath: String,
outputPath: String,
startMs: Long,
endMs: Long,
): Boolean {
if (endMs < startMs) return false
try {
val inputFile = File(inputPath)
val inputFileSize = inputFile.length()
val startSize = calculateDurationToSize(startMs)
val endSize = calculateDurationToSize(endMs)
if (inputFileSize < endSize || inputFileSize < startSize) {
return false
}
inputFile.inputStream().use { inputStream ->
File(outputPath).outputStream().use { outputStream ->
inputStream.skip(startSize)
var bytesCopied: Long = 0
val buffer = ByteArray(1024)
var bytes = inputStream.read(buffer)
while (bytes >= 0 && bytesCopied < (endSize - startSize)) {
outputStream.write(buffer, 0, bytes)
bytesCopied += bytes
bytes = inputStream.read(buffer)
}
}
}
return true
} catch (e: IOException) {
e.printStackTrace()
return false
}
}
文中使用的是 PCM 编码的原始音频文件数据,如果是 WAV 格式需要考虑去掉 44 字节的标头(Header)后再计算和裁剪。
代码中包含了怎样计算每秒音频的文件大小,也可以用它根据文件大小计算音频时长。