AudioBufferList *
AllocateABL(UInt32 channelsPerFrame, UInt32 bytesPerFrame, bool interleaved, UInt32 capacityFrames)
{
AudioBufferList *bufferList = NULL;
UInt32 numBuffers = interleaved ? 1 : channelsPerFrame;
UInt32 channelsPerBuffer = interleaved ? channelsPerFrame : 1;
bufferList = static_cast<AudioBufferList *>(calloc(1, offsetof(AudioBufferList, mBuffers) + (sizeof(AudioBuffer) * numBuffers)));
bufferList->mNumberBuffers = numBuffers;
for(UInt32 bufferIndex = 0; bufferIndex < bufferList->mNumberBuffers; ++bufferIndex) {
bufferList->mBuffers[bufferIndex].mData = static_cast<void *>(calloc(capacityFrames, bytesPerFrame));
bufferList->mBuffers[bufferIndex].mDataByteSize = capacityFrames * bytesPerFrame;
bufferList->mBuffers[bufferIndex].mNumberChannels = channelsPerBuffer;
}
return bufferList;
}
On Sat, Feb 25, 2012 at 5:06 AM, Michael Tyson
<email@hidden> wrote:
Ah - I've just done a little more thinking about this, and there are two extra points to be made (which could well bore anyone reading who finds this extremely obvious, so my apologies to those ;-)) I persist in discussing the on-stack option because it's easier to write and maintain than having to pre-allocate then manage space outside the realtime thread.
1. The whole packing/alignment issue doesn't actually make any difference to the correctness of the code - the worst case is that some extra bytes will be appended to one or both of the nested structures. That means that when we access buffers.bufferList.mBuffers[1], at the worst, we're actually addressing some added bytes before the 'secondBuffer' member. If we ignore secondBuffer, which that code does, then this makes no difference.
2. The packed attribute actually doesn't make much difference in this case: It will never modify the size of the nested structures within the packed struct, so there's still no guarantee that there's not some extra space at the end of AudioBufferList, before the AudioBuffer. But that doesn't really matter.
Of course, if one has an aesthetic objection, one could still just allocate space on the stack with something like:
char bufferListSpace[sizeof(AudioBufferList)+sizeof(AudioBuffer)];
AudioBufferList *bufferList = (AudioBufferList*)bufferListSpace;
Maybe I should've suggested that first =)
> I forgot to add the 'packed' attribute to the anonymous struct in that code, which, unless I'm mistaken, should resolve the problem by ensuring the two structures are packed together - but you're probably right; it's less error-prone to do it on the heap (just a little more work, in certain circumstances where you need to avoid allocating memory, because you then need to allocate it in advance).
>
> Sorry for the misleading code snippet =)
>
> So, unless I'm mistaken about this working (please correct me if I am!), it should've been:
>
> struct { AudioBufferList bufferList; AudioBuffer secondBuffer; } __attribute__((packed)) buffers;
> buffers.bufferList.mNumberBuffers = 2;
> for ( int i=0; i<buffers.bufferList.mNumberBuffers; i++ ) {
> buffers.bufferList.mBuffers[i].mNumberOfChannels = 1;
> buffers.bufferList.mBuffers[i].mDataByteSize = kBufferSize * sizeof(float);
> buffers.bufferList.mBuffers[i].mData = malloc(kBufferSize * sizeof(float));
> }
>
>> Michael,
>>
>> I hate to sound rude, but that is awful code. Declaring a pair of variables as separate fields in a structure on the stack and then depending upon the compiler to make them concatenated into a single array is very bad code. The behavior is very dependent upon the alignment and packing settings at compile time. It might work for you now, but any number of architecture changes or compiler revisions could cause your fragile construct to fail without warning. Note that if the C Language standard guarantees that separate variables declared in proximity on the stack are guaranteed to work like you're using them, then please point to the specification because it would be news to me.
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (
email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to
email@hidden