1 /* Copyright: � Copyright 2005 Apple Computer, Inc. All rights reserved. 2 3 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. 4 ("Apple") in consideration of your agreement to the following terms, and your 5 use, installation, modification or redistribution of this Apple software 6 constitutes acceptance of these terms. If you do not agree with these terms, 7 please do not use, install, modify or redistribute this Apple software. 8 9 In consideration of your agreement to abide by the following terms, and subject 10 to these terms, Apple grants you a personal, non-exclusive license, under Apple�s 11 copyrights in this original Apple software (the "Apple Software"), to use, 12 reproduce, modify and redistribute the Apple Software, with or without 13 modifications, in source and/or binary forms; provided that if you redistribute 14 the Apple Software in its entirety and without modifications, you must retain 15 this notice and the following text and disclaimers in all such redistributions of 16 the Apple Software. Neither the name, trademarks, service marks or logos of 17 Apple Computer, Inc. may be used to endorse or promote products derived from the 18 Apple Software without specific prior written permission from Apple. Except as 19 expressly stated in this notice, no other rights or licenses, express or implied, 20 are granted by Apple herein, including but not limited to any patent rights that 21 may be infringed by your derivative works or by other works in which the Apple 22 Software may be incorporated. 23 24 The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO 25 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED 26 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN 28 COMBINATION WITH YOUR PRODUCTS. 29 30 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR 31 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 32 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION 34 OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT 35 (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN 36 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 */ 38 /*============================================================================= 39 CABufferList.h 40 41 =============================================================================*/ 42 43 #ifndef __CABufferList_h__ 44 #define __CABufferList_h__ 45 46 #include <stddef.h> 47 #include "CAStreamBasicDescription.h" 48 #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) 49 #include <CoreServices/CoreServices.h> 50 #else 51 #include <AssertMacros.h> 52 #endif 53 54 extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize); 55 // wordSize: 0 = float32, else integer word size, negative if little-endian 56 57 /* ____________________________________________________________________________ 58 // CABufferList - variable length buffer list 59 60 This class is designed for use in non-simplistic cases. For AudioUnits, AUBufferList 61 is preferred. 62 63 CABufferList can be used in one of two ways: 64 - as mutable pointers into non-owned memory 65 - as an immutable array of buffers (owns its own memory). 66 67 All buffers are assumed to have the same format (number of channels, word size), so that 68 we can assume their mDataByteSizes are all the same. 69 ____________________________________________________________________________ */ 70 class CABufferList { 71 public: new(size_t,int nBuffers)72 void * operator new(size_t /*size*/, int nBuffers) { 73 return ::operator new(sizeof(CABufferList) + (nBuffers-1) * sizeof(AudioBuffer)); 74 } New(const char * name,const CAStreamBasicDescription & format)75 static CABufferList * New(const char *name, const CAStreamBasicDescription &format) 76 { 77 UInt32 numBuffers = format.NumberChannelStreams(), channelsPerBuffer = format.NumberInterleavedChannels(); 78 return new(numBuffers) CABufferList(name, numBuffers, channelsPerBuffer); 79 } 80 81 protected: CABufferList(const char * name,UInt32 numBuffers,UInt32 channelsPerBuffer)82 CABufferList(const char *name, UInt32 numBuffers, UInt32 channelsPerBuffer) : 83 mName(name), 84 mBufferMemory(NULL) 85 { 86 check(numBuffers > 0 /*&& channelsPerBuffer > 0*/); 87 mNumberBuffers = numBuffers; 88 AudioBuffer *buf = mBuffers; 89 for (UInt32 i = mNumberBuffers; i--; ++buf) { 90 buf->mNumberChannels = channelsPerBuffer; 91 buf->mDataByteSize = 0; 92 buf->mData = NULL; 93 } 94 } 95 96 public: ~CABufferList()97 ~CABufferList() 98 { 99 if (mBufferMemory) 100 delete[] mBufferMemory; 101 } 102 Name()103 const char * Name() { return mName; } 104 GetBufferList()105 const AudioBufferList & GetBufferList() const { return *(AudioBufferList *)&mNumberBuffers; } 106 GetModifiableBufferList()107 AudioBufferList & GetModifiableBufferList() 108 { 109 VerifyNotTrashingOwnedBuffer(); 110 return _GetBufferList(); 111 } 112 GetNumBytes()113 UInt32 GetNumBytes() const 114 { 115 return mBuffers[0].mDataByteSize; 116 } 117 SetBytes(UInt32 nBytes,void * data)118 void SetBytes(UInt32 nBytes, void *data) 119 { 120 VerifyNotTrashingOwnedBuffer(); 121 check(mNumberBuffers == 1); 122 mBuffers[0].mDataByteSize = nBytes; 123 mBuffers[0].mData = data; 124 } 125 CopyAllFrom(CABufferList * srcbl,CABufferList * ptrbl)126 void CopyAllFrom(CABufferList *srcbl, CABufferList *ptrbl) 127 // copies bytes from srcbl 128 // make ptrbl reflect the length copied 129 // note that srcbl may be same as ptrbl! 130 { 131 // Note that this buffer *can* own memory and its pointers/lengths are not 132 // altered; only its buffer contents, which are copied from srcbl. 133 // The pointers/lengths in ptrbl are updated to reflect the addresses/lengths 134 // of the copied data, and srcbl's contents are consumed. 135 ptrbl->VerifyNotTrashingOwnedBuffer(); 136 UInt32 nBytes = srcbl->GetNumBytes(); 137 AudioBuffer *mybuf = mBuffers, *srcbuf = srcbl->mBuffers, 138 *ptrbuf = ptrbl->mBuffers; 139 for (UInt32 i = mNumberBuffers; i--; ++mybuf, ++srcbuf, ++ptrbuf) { 140 memmove(mybuf->mData, srcbuf->mData, srcbuf->mDataByteSize); 141 ptrbuf->mData = mybuf->mData; 142 ptrbuf->mDataByteSize = srcbuf->mDataByteSize; 143 } 144 if (srcbl != ptrbl) 145 srcbl->BytesConsumed(nBytes); 146 } 147 AppendFrom(CABufferList * blp,UInt32 nBytes)148 void AppendFrom(CABufferList *blp, UInt32 nBytes) 149 { 150 VerifyNotTrashingOwnedBuffer(); 151 AudioBuffer *mybuf = mBuffers, *srcbuf = blp->mBuffers; 152 for (UInt32 i = mNumberBuffers; i--; ++mybuf, ++srcbuf) { 153 check(nBytes <= srcbuf->mDataByteSize); 154 memcpy((Byte *)mybuf->mData + mybuf->mDataByteSize, srcbuf->mData, nBytes); 155 mybuf->mDataByteSize += nBytes; 156 } 157 blp->BytesConsumed(nBytes); 158 } 159 PadWithZeroes(UInt32 desiredBufferSize)160 void PadWithZeroes(UInt32 desiredBufferSize) 161 // for cases where an algorithm (e.g. SRC) requires some 162 // padding to create silence following end-of-file 163 { 164 VerifyNotTrashingOwnedBuffer(); 165 if (GetNumBytes() > desiredBufferSize) return; 166 AudioBuffer *buf = mBuffers; 167 for (UInt32 i = mNumberBuffers; i--; ++buf) { 168 memset((Byte *)buf->mData + buf->mDataByteSize, 0, desiredBufferSize - buf->mDataByteSize); 169 buf->mDataByteSize = desiredBufferSize; 170 } 171 } 172 SetToZeroes(UInt32 nBytes)173 void SetToZeroes(UInt32 nBytes) 174 { 175 VerifyNotTrashingOwnedBuffer(); 176 AudioBuffer *buf = mBuffers; 177 for (UInt32 i = mNumberBuffers; i--; ++buf) { 178 memset((Byte *)buf->mData, 0, nBytes); 179 buf->mDataByteSize = nBytes; 180 } 181 } 182 Reset()183 void Reset() 184 { 185 DeallocateBuffers(); 186 } 187 SameDataAs(const CABufferList * anotherBufferList)188 Boolean SameDataAs(const CABufferList* anotherBufferList) 189 { 190 // check to see if two buffer lists point to the same memory. 191 if (mNumberBuffers != anotherBufferList->mNumberBuffers) return false; 192 193 for (UInt32 i = 0; i < mNumberBuffers; ++i) { 194 if (mBuffers[i].mData != anotherBufferList->mBuffers[i].mData) return false; 195 } 196 return true; 197 } 198 BytesConsumed(UInt32 nBytes)199 void BytesConsumed(UInt32 nBytes) 200 // advance buffer pointers, decrease buffer sizes 201 { 202 VerifyNotTrashingOwnedBuffer(); 203 AudioBuffer *buf = mBuffers; 204 for (UInt32 i = mNumberBuffers; i--; ++buf) { 205 check(nBytes <= buf->mDataByteSize); 206 buf->mData = (Byte *)buf->mData + nBytes; 207 buf->mDataByteSize -= nBytes; 208 } 209 } 210 SetFrom(const AudioBufferList * abl)211 void SetFrom(const AudioBufferList *abl) 212 { 213 VerifyNotTrashingOwnedBuffer(); 214 memcpy(&_GetBufferList(), abl, (char *)&abl->mBuffers[abl->mNumberBuffers] - (char *)abl); 215 } 216 SetFrom(const CABufferList * blp)217 void SetFrom(const CABufferList *blp) 218 { 219 SetFrom(&blp->GetBufferList()); 220 } 221 SetFrom(const AudioBufferList * abl,UInt32 nBytes)222 void SetFrom(const AudioBufferList *abl, UInt32 nBytes) 223 { 224 VerifyNotTrashingOwnedBuffer(); 225 AudioBuffer *mybuf = mBuffers; 226 const AudioBuffer *srcbuf = abl->mBuffers; 227 for (UInt32 i = mNumberBuffers; i--; ++mybuf, ++srcbuf) { 228 mybuf->mNumberChannels = srcbuf->mNumberChannels; 229 mybuf->mDataByteSize = nBytes; 230 mybuf->mData = srcbuf->mData; 231 } 232 } 233 SetFrom(const CABufferList * blp,UInt32 nBytes)234 void SetFrom(const CABufferList *blp, UInt32 nBytes) 235 { 236 SetFrom(&blp->GetBufferList(), nBytes); 237 } 238 ToAudioBufferList(AudioBufferList * abl)239 AudioBufferList * ToAudioBufferList(AudioBufferList *abl) const 240 { 241 memcpy(abl, &GetBufferList(), (char *)&abl->mBuffers[mNumberBuffers] - (char *)abl); 242 return abl; 243 } 244 245 void AllocateBuffers(UInt32 nBytes); 246 void AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inCopyFromList, CABufferList *inSetPtrList); 247 248 void DeallocateBuffers(); 249 250 void UseExternalBuffer(Byte *ptr, UInt32 nBytes); 251 AdvanceBufferPointers(UInt32 nBytes)252 void AdvanceBufferPointers(UInt32 nBytes) 253 // this is for bufferlists that function simply as 254 // an array of pointers into another bufferlist, being advanced, 255 // as in RenderOutput implementations 256 { 257 VerifyNotTrashingOwnedBuffer(); 258 AudioBuffer *buf = mBuffers; 259 for (UInt32 i = mNumberBuffers; i--; ++buf) { 260 buf->mData = (Byte *)buf->mData + nBytes; 261 buf->mDataByteSize -= nBytes; 262 } 263 } 264 SetNumBytes(UInt32 nBytes)265 void SetNumBytes(UInt32 nBytes) 266 { 267 VerifyNotTrashingOwnedBuffer(); 268 AudioBuffer *buf = mBuffers; 269 for (UInt32 i = mNumberBuffers; i--; ++buf) 270 buf->mDataByteSize = nBytes; 271 } 272 273 void Print(const char *label=NULL, int nframes=0, int wordSize=0) const 274 { 275 if (label == NULL) 276 label = mName; 277 printf("%s - ", label); 278 CAShowAudioBufferList(&GetBufferList(), nframes, wordSize); 279 if (mBufferMemory) 280 printf(" owned memory @ 0x%p:\n", mBufferMemory); 281 } 282 283 protected: _GetBufferList()284 AudioBufferList & _GetBufferList() { return *(AudioBufferList *)&mNumberBuffers; } // use with care 285 // if we make this public, then we lose ability to call VerifyNotTrashingOwnedBuffer VerifyNotTrashingOwnedBuffer()286 void VerifyNotTrashingOwnedBuffer() 287 { 288 // This needs to be called from places where we are modifying the buffer list. 289 // It's an error to modify the buffer pointers or lengths if we own the buffer memory. 290 check(mBufferMemory == NULL); 291 } 292 293 const char * mName; // for debugging 294 Byte * mBufferMemory; 295 // the rest must exactly mirror the structure of AudioBufferList 296 UInt32 mNumberBuffers; 297 AudioBuffer mBuffers[1]; 298 }; 299 300 #endif // __CABufferList_h__ 301