i'm getting a CrashIfClientProvidedBogusAudioBufferList exception when attempting once my 
AudioConverterFillComplexBuffer callback returns. What are the possibile reasons why this exception would be thrown?
for reference, here is my call
AudioConverterFillComplexBuffer(audioConverterRef,  
fillComplexCallback,  
&convertInfo,  
&framesToDecode,  
&localPcmBufferList,  
& the callback:
func fillComplexxCallback(myConverter: AudioConverterRef, packetNumber: UnsafeMutablePointer<UInt32>,   
ioData: UnsafeMutablePointer<AudioBufferList>, aspd: UnsafeMutablePointer<UnsafeMutablePointer<AudioStreamPacketDescription>>,  
userInfo: UnsafeMutablePointer<Void>) -> OSStatus {  
    var convertInfo = UnsafeMutablePointer<AudioConvertInfo>(userInfo).memory  
    if (packetNumber.memory > (convertInfo.audioBuffer.mDataByteSize / convertInfo.numberOfPackets)) {  
        packetNumber.memory = (convertInfo.audioBuffer.mDataByteSize / convertInfo.numberOfPackets)  
    }  
    ioData.memory.mNumberBuffers = 1  
    var buffer = AudioBuffer(mNumberChannels: 2, mDataByteSize: convertInfo.audioBuffer.mDataByteSize, mData: ioData.memory.mBuffers.mData)  
    ioData.memory.mBuffers = buffer  
     /* if the following is uncommented out, a exception is thrown */
    // aspd.memory = convertInfo.packetDescriptions 
    packetNumber.memory = convertInfo.numberOfPackets  
    convertInfo.done = true  
        return 0  
}  
here's AudioConvertInfo's struct:
struct AudioConvertInfo {
    var done: Bool! //conversion of audio is finished
    var numberOfPackets: UInt32!
    var audioBuffer: AudioBuffer!
    var audioPlayer: CCPlayer!
    var packetDescriptions: AudioStreamPacketDescription!
    init(done: Bool?, numberOfPackets: UInt32?, audioBuffer: AudioBuffer?, packetDescriptions: AudioStreamPacketDescription!, audioPlayer: CCPlayer!) {
        self.done = done
        self.numberOfPackets = numberOfPackets
        self.audioBuffer = audioBuffer
        self.packetDescriptions = packetDescriptions
        self.audioPlayer = audioPlayer
    }
}
I can't seem to find any solid documentation around. I've noticed was the aspd (AudioStreamPacketDescription) is returning nil. This is important to determine one packet in a buffer of audio data where the sizes of the packets differ or where there is non-audio data between audio packets. This code will throw an exception on aspd.memory = convertInfo.packetDescriptions , but if the code is commented out - the CrashIfClientProvidedBogusAudioBufferList is thrown. My theory is that this callback will work fine if i figure out why the AudioStreamPacketDescription is nil
Looks like AudioStreamPacketDescription is nil is not a problem.
According to Apple documentation it can be nil, basically it depends on audio format:
AudioConverterComplexInputDataProc
outDataPacketDescription: UnsafeMutablePointer<UnsafeMutablePointer<AudioStreamPacketDescription>>- If not NULL on input, the audio converter expects this callback to provide an array of AudioStreamPacketDescription structures on output, one for each packet of audio data you are providing in the ioData parameter.
AudioConverterFillComplexBuffer
outPacketDescription: UnsafeMutablePointer<AudioStreamPacketDescription>- On input, must point to a block of memory capable of holding the number of packet descriptions specified in the ioOutputDataPacketSize parameter. (See Audio Format Services Reference for functions that let you determine whether an audio format uses packet descriptions). If not NULL on output and if the audio converter’s output format uses packet descriptions, then this parameter contains an array of packet descriptions.
The real problem is placed in AudioConvertInfo structure in this line:
var packetDescriptions: AudioStreamPacketDescription!  
Structure keeps just single AudioStreamPacketDescription structure.
Then you use it in fillComplexCallback function:  
outDataPacketDescription.memory.memory = convertInfo.packetDescriptions
So you are trying to set single AudioStreamPacketDescription structure to parameter outDataPacketDescription that expects array of AudioStreamPacketDescription structures (not just single instance).  
This problem can be fixed by keeping and using array of AudioStreamPacketDescription structures.
Updated version of AudioConvertInfo structure:  
struct AudioConvertInfo {
    var done: Bool!
    var numberOfPackets: UInt32!
    var audioBuffer: AudioBuffer!
    var audioPlayer: CCPlayer!
    var packetDescriptions: UnsafeMutablePointer<AudioStreamPacketDescription>!
    init(done: Bool?, numberOfPackets: UInt32?, audioBuffer: AudioBuffer?, packetDescriptions: UnsafeMutablePointer<AudioStreamPacketDescription>!, audioPlayer: CCPlayer!) {
        self.done = done
        self.numberOfPackets = numberOfPackets
        self.audioBuffer = audioBuffer
        self.packetDescriptions = packetDescriptions
        self.audioPlayer = audioPlayer
    }
}
// Usage:
convertInfo = AudioConvertInfo(done: false, numberOfPackets: numberPackets, audioBuffer: AudioBuffer(mNumberChannels: 2, mDataByteSize: numberBytes, mData: &iData), packetDescriptions: packetDescriptions, audioPlayer: self)
Updated version of fillComplexCallback function:  
func fillComplexCallback(inAudioConverter: AudioConverterRef, ioNumberDataPackets: UnsafeMutablePointer<UInt32>, ioData: UnsafeMutablePointer<AudioBufferList>, outDataPacketDescription: UnsafeMutablePointer<UnsafeMutablePointer<AudioStreamPacketDescription>>, inUserData: UnsafeMutablePointer<Void>) -> OSStatus {
    var convertInfo = UnsafeMutablePointer<AudioConvertInfo>(inUserData).memory
    if convertInfo.done == true {
        ioNumberDataPackets.memory = 0
        return 100
    }
    ioData.memory.mNumberBuffers = 1
    let buffer = convertInfo.audioBuffer
    ioData.memory.mBuffers = buffer
    if outDataPacketDescription != nil {
        outDataPacketDescription.memory = convertInfo.packetDescriptions
    }
    ioNumberDataPackets.memory = convertInfo.numberOfPackets
    convertInfo.done = true
    return 0
}
// Usage:  
status = AudioConverterFillComplexBuffer(audioConverterRef, fillComplexCallback, &convertInfo!, &framesToDecode, &localPcmBufferList!, nil)
Hope it will resolve your issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With