我需要有关如何使用audioConverterFillComplexBuffer及其回调的一步一步演练.不,不要告诉我阅读Apple文档.我做他们说的一切,转换总是失败.不,不要告诉我去寻找audioConverterFillComplexBuffer的示例及其正在使用的回调 - 我已经复制了大约十几个这样的例子,无论是行还是修改,转换总是失败.不,输入数据没有任何问题.不,这不是一个端点问题.不,问题不在于我的OS X版本.
问题是我不明白audioConverterFillComplexBuffer是如何工作的,所以我不知道我做错了什么.没有什么能帮助我理解,因为看起来地球上没有人真正了解audioConverterFillComplexBuffer的工作方式.从实际使用它的人(我在他们的代码中窥探货物崇拜编程)到甚至是学习核心音频和/或Apple本身的作者(http://stackoverflow.com/questions/13604612/core-audio-how-can酮分组酮字节时-清楚酮分组4个字节).
这对我来说不仅仅是一个问题,对于想要在Mac平台上编写高性能音频的人来说,这是一个问题.那些显然是错误的Threadbare文档和不起作用的示例并不好玩.
再一次,要明确:我需要一步一步地了解如何使用audioConverterFillComplexBuffer及其回调,整个Mac开发人员社区也是如此.
This is a very old question but I think is still relevant. I've spent a few days fighting this and have finally achieved a successful conversion. I'm certainly no expert but I'll outline my understanding of how it works. Note I'm using Swift, which I'm also just learning.
Here are the main function arguments:
inAudioConverter: AudioConverterRef: This one is simple enough, just pass in a previously created AudioConverterRef.
inInputDataProc: AudioConverterComplexInputDataProc: The very complex callback. We'll come back to this.
inInputDataProcUserData, UnsafeMutableRawPointer?: This is a reference to whatever data you may need to be provided to the callback function. Important because even in swift the callback can't inherit context. E.g. you may need to access an AudioFileID or keep track of the number of packets read so far.
ioOutputDataPacketSize: UnsafeMutablePointer<UInt32>: This one is a little misleading. The name implies it's the packet size but reading the documentation we learn it's the total number of packets expected for the output format. You can calculate this as outPacketCount = frameCount / outStreamDescription.mFramesPerPacket.
outOutputData: UnsafeMutablePointer<AudioBufferList>: This is an audio buffer list which you need to have already initialized with enough space to hold the expected output data. The size can be calculated as byteSize = outPacketCount * outMaxPacketSize.
outPacketDescription: UnsafeMutablePointer<AudioStreamPacketDescription>?: This is optional. If you need packet descriptions, pass in a block of memory the size of outPacketCount * sizeof(AudioStreamPacketDescription).
当转换器运行时,它将重复调用回调函数来请求更多数据进行转换。回调的主要工作只是从源数据中读取请求的数据包。然后转换器会将数据包转换为输出格式并填充输出缓冲区。以下是回调的参数:
inAudioConverter: AudioConverterRef:又是音频转换器。您可能不需要使用这个。
ioNumberDataPackets: UnsafeMutablePointer<UInt32>:要读取的数据包数量。读取后,必须将其设置为实际读取的数据包数量(如果到达末尾,该数量可能会小于请求的数量)。
ioData: UnsafeMutablePointer<AudioBufferList>:除实际数据外已配置的 AudioBufferList。您需要初始化 ioData.mBuffers.mData ,使其具有足够的容量来容纳预期数量的数据包,即ioNumberDataPackets * inMaxPacketSize。设置 ioData.mBuffers.mDataByteSize 的值以匹配。
outDataPacketDescription: UnsafeMutablePointer<UnsafeMutablePointer<AudioStreamPacketDescription>?>?:根据所使用的格式,转换器可能需要跟踪数据包描述。您需要用足够的容量来初始化它,以容纳预期数量的数据包描述。
inUserData: UnsafeMutableRawPointer?:您提供给转换器的用户数据。
因此,首先您需要:
AudioConverterFillComplexBuffer。在每次运行回调时,您需要:
ioData具有足够的容量来存储ioNumberDataPackets源数据。outDataPacketDescription具有足够的容量来存储ioNumberDataPacketsAudioStreamPacketDescriptions。ioNumberDataPackets为实际读取的数据包数量。noErr如果成功则返回。下面是我从 AudioFileID 读取数据的示例:
var converter: AudioConverterRef?
// User data holds an AudioFileID, input max packet size, and a count of packets read
var uData = (fRef, maxPacketSize, UnsafeMutablePointer<Int64>.allocate(capacity: 1))
err = AudioConverterNew(&inStreamDesc, &outStreamDesc, &converter)
err = AudioConverterFillComplexBuffer(converter!, { _, ioNumberDataPackets, ioData, outDataPacketDescription, inUserData in
let uData = inUserData!.load(as: (AudioFileID, UInt32, UnsafeMutablePointer<Int64>).self)
ioData.pointee.mBuffers.mDataByteSize = uData.1
ioData.pointee.mBuffers.mData = UnsafeMutableRawPointer.allocate(byteCount: Int(uData.1), alignment: 1)
outDataPacketDescription?.pointee = UnsafeMutablePointer<AudioStreamPacketDescription>.allocate(capacity: Int(ioNumberDataPackets.pointee))
let err = AudioFileReadPacketData(uData.0, false, &ioData.pointee.mBuffers.mDataByteSize, outDataPacketDescription?.pointee, uData.2.pointee, ioNumberDataPackets, ioData.pointee.mBuffers.mData)
uData.2.pointee += Int64(ioNumberDataPackets.pointee)
return err
}, &uData, &numPackets, &bufferList, nil)
Run Code Online (Sandbox Code Playgroud)
再说一次,我不是专家,这只是我通过反复试验学到的东西。
| 归档时间: |
|
| 查看次数: |
992 次 |
| 最近记录: |