This code is for converting audio in ByteArray
in PCM int 16 bit mono format to audio in ABAudioPCMBuffer
in PCM float 32 bit stereo format:
fun convertMonoPCMInt16ToStereoPCMFloat32(
inputData: ByteArray, inputSampleRate: Double, outputSampleRate: Double
): AVAudioPCMBuffer? {
val inputFrameLength = inputData.size / 2 // 2 bytes per Int16 sample
val resampleRatio = outputSampleRate / inputSampleRate
val outputFrameLength = (inputFrameLength * resampleRatio).toInt()
val audioFormat = AVAudioFormat(standardFormatWithSampleRate = outputSampleRate, channels = 2u)
val outputBuffer = AVAudioPCMBuffer(audioFormat, frameCapacity = outputFrameLength.toUInt()) ?: return null
val leftChannel = outputBuffer.floatChannelData!![0]
val rightChannel = outputBuffer.floatChannelData!![1]
for (outputFrame in 0 until outputFrameLength) {
val inputFrameFloat = outputFrame / resampleRatio
val inputFrame = inputFrameFloat.toInt()
val fraction = inputFrameFloat - inputFrame
val sample1 = readInt16Sample(inputData, inputFrame, inputFrameLength)
val sample2 = readInt16Sample(inputData, inputFrame + 1, inputFrameLength)
val interpolatedSample = (1 - fraction) * sample1 + fraction * sample2
// Convert to Float and apply gain control
val floatSample = (interpolatedSample / Short.MAX_VALUE.toFloat()) * 0.7f // Apply -3dB attenuation
// Duplicate to stereo
leftChannel!![outputFrame] = floatSample.toFloat()
rightChannel!![outputFrame] = floatSample.toFloat()
}
outputBuffer.frameLength = outputFrameLength.toUInt()
return outputBuffer
}
private fun readInt16Sample(inputData: ByteArray, index: Int, length: Int): Int {
if (index >= length) return 0
val low = inputData[index * 2].toInt() and 0xFF
val high = inputData[index * 2 + 1].toInt()
return (high shl 8) or low
}
Telegram channel
If you still have any questions, feel free to ask me in the comments under this article or write me at promark33@gmail.com.
If I saved your day, you can support me 🤝