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