KMP IOS convert PCM float 32 bit to PCM int 16 bit

Here we have the method that converts audio in AVAudioPCMBuffer in PCM float 32 bit mono format to audio in ByteArray in PCM int 16 bit mono format:

fun convertMonoPCMFloat32ToMonoPCMInt16(inputBuffer: AVAudioPCMBuffer, outputSampleRate: Double): ByteArray {
    val floatChannelData = inputBuffer.floatChannelData!!
    val frameLength = inputBuffer.frameLength.toInt()
    val channelCount = inputBuffer.format.channelCount
    val inputSampleRate = inputBuffer.format.sampleRate

    val resampleRatio = inputSampleRate / outputSampleRate
    val outputFrameLength = (frameLength.toDouble() / resampleRatio).toInt()
    val outputSize = outputFrameLength * channelCount.toInt()
    val outputBuffer = ByteArray(outputSize * 2) // 2 bytes per Int16 sample

    var outputIndex = 0
    for (outputFrame in 0 until outputFrameLength) {
        val inputFrameFloat = outputFrame * resampleRatio
        val inputFrame = inputFrameFloat.toInt()
        val fraction = inputFrameFloat - inputFrame

        for (channel in 0 until channelCount.toInt()) {
            // Linear interpolation for resampling
            val sample1 = floatChannelData[channel]!![inputFrame]
            val sample2 = if (inputFrame + 1 < frameLength) floatChannelData[channel]!![inputFrame + 1] else sample1
            val interpolatedSample = (1 - fraction) * sample1 + fraction * sample2

            // Convert to Int16
            val int16Sample = (interpolatedSample * Short.MAX_VALUE).toInt()
                .coerceIn(Short.MIN_VALUE.toInt(), Short.MAX_VALUE.toInt()).toShort()

            outputBuffer[outputIndex++] = int16Sample.toByte()
            outputBuffer[outputIndex++] = (int16Sample.toInt() shr 8).toByte()
        }
    }

    return outputBuffer
}

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 🤝