'(AudioBuffer)' syntax

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

@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.