The struct is defined in C as:
struct AudioChannelLayout
{
AudioChannelLayoutTag mChannelLayoutTag;
UInt32 mChannelBitmap;
UInt32 mNumberChannelDescriptions;
AudioChannelDescription mChannelDescriptions[1];
};
typedef struct AudioChannelLayout AudioChannelLayout;
So, if you allocate a variable of this type statically in your code, you can use only one element for mChannelDescriptions.
AudioChannelLayout layout;
for( int i = 0; i < (int)layout.mNumberChannelDescriptions; ++i ) {
//This code may crash your app when i being 1 or more.
if( layout.mChannelDescriptions[i].mChannelLabel == kAudioChannelLabel_Left ) {
/*some action*/
}
}
If you want to use more than one channels, you need to allocate it dynamically:
int numChannels = 2;
AudioChannelLayout *layoutPtr = malloc(sizeof(AudioChannelLayout) + (numChannels - 1) * sizeof(AudioChannelDescription));
layoutPtr->mNumberChannelDescriptions = numChannels;
for( int i = 0; i < numChannels; ++i ) {
if( layoutPtr->mChannelDescriptions[i].mChannelLabel == kAudioChannelLabel_Left ) {
/some action*/
}
}
The declaration of the Swift version of AudioChannelLayout is generated by the Swift's C code importer which maps fixed-sized array in a stuct to Swift tuple.
And you need to remember, Swift does not have a single-value tuple, so the declaration is exactly the same as:
struct AudioChannelLayout {
var mChannelLayoutTag: AudioChannelLayoutTag
var mChannelBitmap: UInt32
var mNumberChannelDescriptions: UInt32
var mChannelDescriptions: AudioChannelDescription
}
As you see, mChannelDescriptions is a single AudioChannelDescription, not array, not tuple.
So, you need to translate the `dynamically` C-code into Swift:
let numChannes = 2
let layoutPtr = UnsafeMutablePointer<AudioChannelLayout>(UnsafeMutablePointer<CChar>.alloc(strideof(AudioChannelLayout) + (numChannes - 1) * strideof(AudioChannelDescription)))
layoutPtr.memory.mNumberChannelDescriptions = UInt32(numChannes)
for i in 0..<numChannes {
//Calculate the address of the first mChannelDescriptions
//Caution: this code depends on boundaries and alignments of types contained in AudioChannelLayout
let descPtr = UnsafeMutablePointer<AudioChannelDescription>(UnsafeMutablePointer<CChar>(layoutPtr).advancedBy(sizeof(AudioChannelLayoutTag) + sizeof(UInt32) * 2))
if descPtr[i].mChannelFlags == kAudioChannelLabel_Left {
/*some action*/
}
}
...
AudioBufferList has a similar definition, you can find some discussions about it in the dev forums including archived old forums.