/*============================================================================= AUOutputBL.h $Log: AUOutputBL.cpp,v $ Revision 1.4 2004/08/24 22:39:54 bills protect Print in release builds Revision 1.3 2004/08/20 18:56:56 bills add a Print method Revision 1.2 2004/07/09 02:50:31 bills fix handling of mDataByteSize Revision 1.1 2004/03/16 20:24:10 bills new class created 15 Mar 2004, William Stewart Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved $NoKeywords: $ =============================================================================*/ #include "AUOutputBL.h" /* struct AudioBufferList { UInt32 mNumberBuffers; AudioBuffer mBuffers[1]; }; struct AudioBuffer { UInt32 mNumberChannels; // number of interleaved channels in the buffer UInt32 mDataByteSize; // the size of the buffer pointed to by mData void* mData; // the pointer to the buffer }; */ AUOutputBL::AUOutputBL (const CAStreamBasicDescription &inDesc, UInt32 inDefaultNumFrames) : mFormat (inDesc), mBufferMemory(NULL), mBufferList (NULL), mNumberBuffers (0), // keep this here, so can ensure integrity of ABL mBufferSize (0), mFrames(inDefaultNumFrames) { mNumberBuffers = mFormat.IsInterleaved() ? 1 : mFormat.NumberChannels(); mBufferList = reinterpret_cast(new Byte[sizeof(UInt32) + (mNumberBuffers * sizeof(AudioBuffer))]); } AUOutputBL::~AUOutputBL() { if (mBufferMemory) delete[] mBufferMemory; if (mBufferList) delete [] mBufferList; } void AUOutputBL::Prepare (UInt32 inNumFrames, bool inWantNullBufferIfAllocated) { UInt32 channelsPerBuffer = mFormat.IsInterleaved() ? mFormat.NumberChannels() : 1; if (mBufferMemory == NULL || inWantNullBufferIfAllocated) { mBufferList->mNumberBuffers = mNumberBuffers; AudioBuffer *buf = &mBufferList->mBuffers[0]; for (UInt32 i = 0; i < mNumberBuffers; ++i, ++buf) { buf->mNumberChannels = channelsPerBuffer; buf->mDataByteSize = mFormat.FramesToBytes (inNumFrames); buf->mData = NULL; } } else { UInt32 nBytes = mFormat.FramesToBytes (inNumFrames); if ((nBytes * mNumberBuffers) > AllocatedBytes()) throw OSStatus(-10874);//(kAudioUnitErr_TooManyFramesToProcess); mBufferList->mNumberBuffers = mNumberBuffers; AudioBuffer *buf = &mBufferList->mBuffers[0]; Byte* p = mBufferMemory; for (UInt32 i = 0; i < mNumberBuffers; ++i, ++buf) { buf->mNumberChannels = channelsPerBuffer; buf->mDataByteSize = nBytes; buf->mData = p; p += mBufferSize; } } } void AUOutputBL::Allocate (UInt32 inNumFrames) { if (inNumFrames) { UInt32 nBytes = mFormat.FramesToBytes (inNumFrames); if (nBytes <= AllocatedBytes()) return; // align successive buffers for Altivec and to take alternating // cache line hits by spacing them by odd multiples of 16 if (mNumberBuffers > 1) nBytes = (nBytes + (0x10 - (nBytes & 0xF))) | 0x10; mBufferSize = nBytes; UInt32 memorySize = mBufferSize * mNumberBuffers; Byte *newMemory = new Byte[memorySize]; memset(newMemory, 0, memorySize); // make buffer "hot" Byte *oldMemory = mBufferMemory; mBufferMemory = newMemory; delete[] oldMemory; mFrames = inNumFrames; } else { if (mBufferMemory) { delete [] mBufferMemory; mBufferMemory = NULL; } mBufferSize = 0; mFrames = 0; } } #if DEBUG void AUOutputBL::Print() { printf ("AUOutputBL::Print\n"); mFormat.Print(); printf ("Num Buffers:%ld, mFrames:%ld, allocatedMemory:%c\n", mBufferList->mNumberBuffers, mFrames, (mBufferMemory != NULL ? 'T' : 'F')); AudioBuffer *buf = &mBufferList->mBuffers[0]; for (UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i, ++buf) printf ("\tBuffer:%ld, Size:%ld, Chans:%ld, Buffer:%X\n", i, buf->mDataByteSize, buf->mNumberChannels, int(buf->mData)); } #endif