(swift) 在 AudioStreamPacketDescription 为零时调试 CrashIfClientProvidedBogusAudioBufferList 的方法?

325*_*523 5 core-audio ios swift swift2

CrashIfClientProvidedBogusAudioBufferList一旦我的AudioConverterFillComplexBuffer回调返回,我在尝试时遇到异常 。抛出此异常的可能原因是什么?

供参考,这是我的电话

AudioConverterFillComplexBuffer(audioConverterRef,  
fillComplexCallback,  
&convertInfo,  
&framesToDecode,  
&localPcmBufferList,  
Run Code Online (Sandbox Code Playgroud)

&回调:

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  
}  
Run Code Online (Sandbox Code Playgroud)

这是AudioConvertInfo's结构:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

我似乎找不到任何可靠的文档。我注意到 aspd ( AudioStreamPacketDescription) 返回 nil。这对于确定音频数据缓冲区中的数据包大小不同或音频数据包之间存在非音频数据的情况很重要。此代码将在 aspd.memory = convertInfo.packetDescriptions 上引发异常,但如果代码被注释掉 - 会引发 CrashIfClientProvidedBogusAudioBufferList。我的理论是,如果我弄清楚为什么 AudioStreamPacketDescription 为零,则此回调将正常工作

Vla*_*pko 4

看起来好像AudioStreamPacketDescription is nil不是问题。
\n根据Apple文档,它可以为零,基本上它取决于音频格式:
\n AudioConverterComplexInputDataProc

\n\n
\n

outDataPacketDescription: UnsafeMutablePointer<UnsafeMutablePointer<AudioStreamPacketDescription>>- 如果输入不为 NULL,则音频转换器期望此回调在输出上提供一组 AudioStreamPacketDescription结构,每个数据包对应您在 ioData 参数中提供的音频数据的每个数据包。

\n
\n\n

音频转换器填充复杂缓冲区

\n\n
\n

outPacketDescription: UnsafeMutablePointer<AudioStreamPacketDescription>- 输入时,必须指向能够保存 ioOutputDataPacketSize 参数中指定的数据包描述数量的内存块。(有关可让您确定音频格式是否使用数据包描述的函数,请参阅音频格式服务参考)。如果输出不为 NULL,并且音频转换器 xe2x80x99s 输出格式使用数据包描述,则此参数包含数据包描述数组。

\n
\n\n

真正的问题在于AudioConvertInfo这一行的结构:

\n\n
var packetDescriptions: AudioStreamPacketDescription!  \n
Run Code Online (Sandbox Code Playgroud)\n\n

结构仅保持单一AudioStreamPacketDescription结构。
\n然后你在fillComplexCallback函数中使用它:

\n\n
outDataPacketDescription.memory.memory = convertInfo.packetDescriptions\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,您尝试将单个AudioStreamPacketDescription结构设置为outDataPacketDescription需要AudioStreamPacketDescription结构数组(而不仅仅是单个实例)的参数。

\n\n

这个问题可以通过保留和使用结构数组来解决AudioStreamPacketDescription
\nAudioConvertInfo结构的更新版本:

\n\n
struct AudioConvertInfo {\n    var done: Bool!\n    var numberOfPackets: UInt32!\n    var audioBuffer: AudioBuffer!\n    var audioPlayer: CCPlayer!\n    var packetDescriptions: UnsafeMutablePointer<AudioStreamPacketDescription>!\n\n    init(done: Bool?, numberOfPackets: UInt32?, audioBuffer: AudioBuffer?, packetDescriptions: UnsafeMutablePointer<AudioStreamPacketDescription>!, audioPlayer: CCPlayer!) {\n        self.done = done\n        self.numberOfPackets = numberOfPackets\n        self.audioBuffer = audioBuffer\n        self.packetDescriptions = packetDescriptions\n        self.audioPlayer = audioPlayer\n    }\n}\n\n// Usage:\nconvertInfo = AudioConvertInfo(done: false, numberOfPackets: numberPackets, audioBuffer: AudioBuffer(mNumberChannels: 2, mDataByteSize: numberBytes, mData: &iData), packetDescriptions: packetDescriptions, audioPlayer: self)\n
Run Code Online (Sandbox Code Playgroud)\n\n

功能更新版本fillComplexCallback

\n\n
func fillComplexCallback(inAudioConverter: AudioConverterRef, ioNumberDataPackets: UnsafeMutablePointer<UInt32>, ioData: UnsafeMutablePointer<AudioBufferList>, outDataPacketDescription: UnsafeMutablePointer<UnsafeMutablePointer<AudioStreamPacketDescription>>, inUserData: UnsafeMutablePointer<Void>) -> OSStatus {\n    var convertInfo = UnsafeMutablePointer<AudioConvertInfo>(inUserData).memory\n\n    if convertInfo.done == true {\n        ioNumberDataPackets.memory = 0\n        return 100\n    }\n    ioData.memory.mNumberBuffers = 1\n    let buffer = convertInfo.audioBuffer\n    ioData.memory.mBuffers = buffer\n\n    if outDataPacketDescription != nil {\n        outDataPacketDescription.memory = convertInfo.packetDescriptions\n    }\n\n    ioNumberDataPackets.memory = convertInfo.numberOfPackets\n    convertInfo.done = true\n\n    return 0\n}\n\n// Usage:  \nstatus = AudioConverterFillComplexBuffer(audioConverterRef, fillComplexCallback, &convertInfo!, &framesToDecode, &localPcmBufferList!, nil)\n
Run Code Online (Sandbox Code Playgroud)\n\n

希望它能解决您的问题。

\n