I have a function for converting a PCM buffer to AAC audio that appears to be correct:
func convertPCMBufferToAAC(pcmBuffer: AVAudioPCMBuffer, sampleRate: Double, channels: AVAudioChannelCount) -> Data? {
let audioFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: sampleRate, channels: channels, interleaved: false)!
let settings: [String: Any] = [
AVFormatIDKey: kAudioFormatMPEG4AAC,
AVSampleRateKey: sampleRate,
AVNumberOfChannelsKey: channels,
AVEncoderBitRateKey: 192000
]
guard let outputFormat = AVAudioFormat(settings: settings),
let converter = AVAudioConverter(from: audioFormat, to: outputFormat) else {
print("convertPCMBufferToAAC: Failed to create AVAudioConverter")
return nil
}
let inputBlock: AVAudioConverterInputBlock = { inNumPackets, outStatus in
outStatus.pointee = .haveData
return pcmBuffer
}
let aacBuffer = AVAudioCompressedBuffer(format: outputFormat, packetCapacity: 512, maximumPacketSize: converter.maximumOutputPacketSize)
var error: NSError?
let status = converter.convert(to: aacBuffer, error: &error, withInputFrom: inputBlock)
if status == .error || error != nil {
print("convertPCMBufferToAAC: Conversion error - (error?.localizedDescription ?? "unknown error")")
return nil
}
let data = Data(bytes: aacBuffer.data, count: Int(aacBuffer.byteLength))
print("convertPCMBufferToAAC: Conversion successful, data size: (data.count) bytes")
return data
}
convertPCMBufferToAAC: Conversion successful, data size: 86945 bytes
checkOutput: Converted PCM to AAC, size: 86945 bytes
However, converting back to a PCM buffer always results in a frame length of 0:
func decodeAACDataToPCM(aacData: Data, sampleRate: Double, channels: AVAudioChannelCount) -> AVAudioPCMBuffer? {
let outputFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: sampleRate, channels: channels, interleaved: false)!
let settings: [String: Any] = [
AVFormatIDKey: kAudioFormatMPEG4AAC,
AVSampleRateKey: sampleRate,
AVNumberOfChannelsKey: channels
]
guard let inputFormat = AVAudioFormat(settings: settings),
let converter = AVAudioConverter(from: inputFormat, to: outputFormat) else {
print("decodeAACDataToPCM: Failed to create AVAudioConverter")
return nil
}
let pcmBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: AVAudioFrameCount(sampleRate * 2))!
let aacBuffer = AVAudioCompressedBuffer(format: inputFormat, packetCapacity: 512, maximumPacketSize: aacData.count)
aacData.withUnsafeBytes { (rawBufferPointer: UnsafeRawBufferPointer) in
guard let rawPointer = rawBufferPointer.baseAddress else { return }
aacBuffer.data.copyMemory(from: rawPointer, byteCount: aacData.count)
}
aacBuffer.byteLength = UInt32(aacData.count)
let inputBlock: AVAudioConverterInputBlock = { inNumPackets, outStatus in
outStatus.pointee = .haveData
return aacBuffer
}
var error: NSError?
let status = converter.convert(to: pcmBuffer, error: &error, withInputFrom: inputBlock)
if status == .error || error != nil {
print("decodeAACDataToPCM: Conversion error - (error?.localizedDescription ?? "unknown error")")
return nil
}
print("decodeAACDataToPCM: Conversion successful, frame length: (pcmBuffer.frameLength)")
print("decodeAACDataToPCM: PCM buffer details - format: (pcmBuffer.format), frameLength: (pcmBuffer.frameLength), capacity: (pcmBuffer.frameCapacity)")
return pcmBuffer
}
checkOutput: Converted AAC back to PCM, frame length: 0
checkOutput: Decoded buffer has zero frame length, skipping playback