Frery
(Frery Carino)
1
Hello, everyone here.I don't recognize the (AudioBuffer) syntax below.
public struct AudioBufferList {
public var mNumberBuffers: UInt32
public var mBuffers: (AudioBuffer) // this is a variable length array of mNumberBuffers elements
public init()
public init(mNumberBuffers: UInt32, mBuffers: (AudioBuffer))
}
So, can anyone tell me or explain, what is the final grammar of '(AudioBuffer)'?
How can i create a AudioBufferList instance, and visit the subscript of 'mBuffers'?
Here is my user scenario:
I'm using VideoToolBox to catch the audio buffer by using 'AudioComponentDescription' & 'AudioUnit' , so i need to create a call back to handle the input buffer.
Here is the code:
// MARK: CallBack
func handleInputBuffer(inRefCon: UnsafeMutableRawPointer,
ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>,
inTimeStamp: UnsafePointer<AudioTimeStamp>,
inBusNumber: UInt32,
inNumberFrames: UInt32,
ioData: UnsafeMutablePointer<AudioBufferList>) -> OSStatus {
let source: MTAudioCapture = Unmanaged.fromOpaque(inRefCon).takeUnretainedValue()
// var buffers = AudioBufferList(mNumberBuffers: 1,
// mBuffers: AudioBuffer(mNumberChannels: 1, mDataByteSize: 1, mData: nil))
let bufferList = UnsafeMutableAudioBufferListPointer(ioData)
let status: OSStatus = AudioUnitRender(source.componentInstance!, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData)
if source.muted! {
for buffer in bufferList {
memset(buffer.mData, 0, Int(buffer.mDataByteSize))
}
}
if status != noErr {
if source.delegate != nil {
source.delegate?.captureOutput(capture: source, audioData: Data(bytes: bufferList[0].mData!, count: Int(bufferList[0].mDataByteSize)))
}
}
return status
}
is that right? I'm so confused.
Any message here are welcomed.
Thank you!
It's kind of a sad story.
Chapter 1. The underlying C struct ends with a member mBuffers of type AudioBuffer[1]. This actually represents a variable number of AudioBuffers at the end of the struct, which is normally written AudioBuffer[] in C, but some ancient C compilers don't like that syntax, so by convention it's specified with 1 element. (If you think about it, this introduces some shenanigans when trying to compute sizeof the struct, but that's a little piece of madness-on-the-side.)
Chapter 2. In Swift, a fixed-size C array is imported as a tuple with the corresponding number of elements: in this case, therefore, a tuple of one AudioBuffer, aka (AudioBuffer). However, Swift doesn't actually have any tuples of 1 elements, so it's mostly just treated as a single AudioBuffer inline in the struct. (In past versions of the compiler, parenthesizing a type like this did result in some odd error messages, but I suspect that doesn't happen any more.)
Chapter 3. This makes the whole thing extremely treacherous. This should be an array of structs at the end, but it's actually a struct with a single sub-struct at the end. If you try to reference the contents of the AudioBufferList directly, you'll likely end up in big trouble.
Chapter 4. To … ahem … work around this, the Swift version of the SDK introduces this UnsafeMutableAudioBufferListPointer data type to turn a pointer to the incorrect Swift struct into a pointer to something you can actually use. This is hugely confusing, as you can imagine.
4 Likes
Frery
(Frery Carino)
3
@QuinceyMorris Thank you for your reply and detail description.
Yeah, i realized that is so confusing. But i still will try above code to handle input audio buffer. I hope it can work well.
Correction: mBuffer is a variable-length array of AudioBuffer's, not pointers to AudioBuffer. For pointers C declaration would look like AudioBuffer * mBuffers[1];
Thanks for the correction. I talked myself into the wrong thing while typing the post, now corrected.