Transcode AVAudioPCMBuffer to lower sample-rate (but be compatible with iOS8)

I am working on an app that needs to record the users voice and have it available during recording. So I installed a tap and am now receiving an AVAudioPCMBuffer. The problem is that now I need to transcode it to a lower sample rate as well as a lower PCM Format and 1 channel would also be enough.


Just chaning the format on that tap doesn't work, cause it's settings seem to need to be the same as the ones from the hardware.

I did some research and found AVAudioConverter, got really excited... but then I found out that it is only supported on iOS9 😟


What would be the solution to transcode my content to PCMFormatInt16, 8000hz with 1 channel using iOS8?


Any help is very much appreciated!!!

I would think you can use the services of the kAudioUnitSubType_AUConverter if you want or the AudioConverter directly as AVAudioConverter is just a wrapper around the AudioConverter API (AudioConverter.h) which is available on iOS 8. So, I would look at those options.

Thanks for helping!

I have to admit that I am a total noob when it comes to audio stuff. Would be super great if you could help me out a bit here 🙂


So I went ahead an made an instance of an AudioConverter


let bus = 0

let inputFormat = audioEngine.inputNode!.inputFormatForBus(bus)
let outputFormat = AVAudioFormat(commonFormat: AVAudioCommonFormat.PCMFormatInt16, sampleRate: 8000.0, channels: 1, interleaved: false)

var audioConverterRef = AudioConverterRef()
let status = AudioConverterNew(inputFormat.streamDescription, outputFormat.streamDescription, &audioConverterRef)


That's working so far (status is noErr). Now I have a valid AudioConverter where I'd think that it would convert bytes that I give him in the format of inputFormat into outputFormat.


Now I install a tap on my inputNode and in the callback I do the following:


// I have those two params available inside my callback
(inputBuffer: AVAudioPCMBuffer, time:AVAudioTime)

// Now I'll get the underlying data ...
let inputAudioBufferList = inputBuffer.audioBufferList
let inputAudioBuffer = inputAudioBufferList[0]
let inputData = inputAudioBuffer.mBuffers.mData
let inputDataSize = inputAudioBuffer.mBuffers.mDataByteSize
// Here's my first question: Is this the correct way to do that?
// Can I expect that my input Data and size is correct?


// Now I prepare the buffer for the converted output
var outputBufferSize: UInt32 = 1024
var convertedOutputBuffer = UnsafeMutablePointer<Void>.alloc(Int(outputBufferSize))
let convertedOutputBufferSize = withUnsafeMutablePointer(&outputBufferSize, { $0 })


// And now I'll try to convert my input data
let status = AudioConverterConvertBuffer(audioConverterRef, inputDataSize, inputData, convertedOutputBufferSize, &convertedOutputBuffer)

// Problem here if that the status is -50 which means that one of my params isn't correct... But which one?



So it seems as if I am not smart enough to figure out the correct input params for AudioConverterConvertBuffer.


Also... when looking at the API... is this the correct way? What's the thing with kAudioUnitSubType_AUConverter? Where would that come into play?



Any help is very very much appreciated!

Did you manage to solve this?

Transcode AVAudioPCMBuffer to lower sample-rate (but be compatible with iOS8)
 
 
Q