1 /* 2 Copyright (C) 2016 Apple Inc. All Rights Reserved. 3 See LICENSE.txt for this sample’s licensing information 4 5 Abstract: 6 Part of Core Audio Public Utility Classes 7 */ 8 9 #ifndef __CABufferList_h__ 10 #define __CABufferList_h__ 11 12 #include <stddef.h> 13 #include "CAStreamBasicDescription.h" 14 #include "CAXException.h" 15 16 void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, const AudioStreamBasicDescription &fmt, const char *label=NULL); 17 void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label=NULL); 18 extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize); 19 extern "C" int CrashIfClientProvidedBogusAudioBufferList(const AudioBufferList *abl, bool nullOK=false); 20 21 /* ____________________________________________________________________________ 22 // CABufferList - variable length buffer list 23 24 This class is designed for use in non-simplistic cases. For AudioUnits, AUBufferList 25 is preferred. 26 27 CABufferList can be used in one of two ways: 28 - as mutable pointers into non-owned memory 29 - as an immutable array of buffers (owns its own memory). 30 31 All buffers are assumed to have the same format (number of channels, word size), so that 32 we can assume their mDataByteSizes are all the same. 33 ____________________________________________________________________________ */ 34 class CABufferList { 35 public: new(size_t,int nBuffers)36 void * operator new(size_t /*size*/, int nBuffers) { 37 return ::operator new(sizeof(CABufferList) + (nBuffers-1) * sizeof(AudioBuffer)); 38 } New(const char * name,const CAStreamBasicDescription & format)39 static CABufferList * New(const char *name, const CAStreamBasicDescription &format) 40 { 41 UInt32 numBuffers = format.NumberChannelStreams(), channelsPerBuffer = format.NumberInterleavedChannels(); 42 return new(numBuffers) CABufferList(name, numBuffers, channelsPerBuffer); 43 } New(const CAStreamBasicDescription & format)44 static CABufferList * New(const CAStreamBasicDescription &format) { return New("", format); } 45 46 static CABufferList * New(UInt32 numBuffers, UInt32 channelsPerBuffer, const char *name="") { 47 return new(numBuffers) CABufferList(name, numBuffers, channelsPerBuffer); 48 } 49 50 protected: CABufferList(const char * name,UInt32 numBuffers,UInt32 channelsPerBuffer)51 CABufferList(const char *name, UInt32 numBuffers, UInt32 channelsPerBuffer) : 52 mName(name), 53 mBufferMemory(NULL), 54 mBufferCapacity(0) 55 { 56 //XAssert(numBuffers > 0 /*&& channelsPerBuffer > 0*/); 57 mABL.mNumberBuffers = numBuffers; 58 AudioBuffer *buf = mABL.mBuffers; 59 for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) { 60 buf->mNumberChannels = channelsPerBuffer; 61 buf->mDataByteSize = 0; 62 buf->mData = NULL; 63 } 64 } 65 66 public: ~CABufferList()67 ~CABufferList() 68 { 69 if (mBufferMemory) 70 delete[] mBufferMemory; 71 } 72 Name()73 const char * Name() { return mName; } 74 GetBufferList()75 const AudioBufferList & GetBufferList() const { return mABL; } 76 GetModifiableBufferList()77 AudioBufferList & GetModifiableBufferList() { return _GetBufferList(); } 78 GetNumberBuffers()79 UInt32 GetNumberBuffers() const { return mABL.mNumberBuffers; } 80 GetNumBytes()81 UInt32 GetNumBytes() const 82 { 83 return mABL.mBuffers[0].mDataByteSize; 84 } 85 SetBytes(UInt32 nBytes,void * data)86 void SetBytes(UInt32 nBytes, void *data) 87 { 88 VerifyNotTrashingOwnedBuffer(); 89 XAssert(mABL.mNumberBuffers == 1); 90 mABL.mBuffers[0].mDataByteSize = nBytes; 91 mABL.mBuffers[0].mData = data; 92 } 93 CopyAllFrom(CABufferList * srcbl,CABufferList * ptrbl)94 void CopyAllFrom(CABufferList *srcbl, CABufferList *ptrbl) 95 // copies bytes from srcbl 96 // make ptrbl reflect the length copied 97 // note that srcbl may be same as ptrbl! 98 { 99 // Note that this buffer *can* own memory and its pointers/lengths are not 100 // altered; only its buffer contents, which are copied from srcbl. 101 // The pointers/lengths in ptrbl are updated to reflect the addresses/lengths 102 // of the copied data, and srcbl's contents are consumed. 103 ptrbl->VerifyNotTrashingOwnedBuffer(); 104 UInt32 nBytes = srcbl->GetNumBytes(); 105 AudioBuffer *mybuf = mABL.mBuffers, *srcbuf = srcbl->mABL.mBuffers, 106 *ptrbuf = ptrbl->mABL.mBuffers; 107 for (UInt32 i = mABL.mNumberBuffers; i--; ++mybuf, ++srcbuf, ++ptrbuf) { 108 memmove(mybuf->mData, srcbuf->mData, srcbuf->mDataByteSize); 109 ptrbuf->mData = mybuf->mData; 110 ptrbuf->mDataByteSize = srcbuf->mDataByteSize; 111 } 112 if (srcbl != ptrbl) 113 srcbl->BytesConsumed(nBytes); 114 } 115 116 // copies data from another buffer list. CopyDataFrom(const AudioBufferList & other)117 void CopyDataFrom(const AudioBufferList &other) 118 { 119 for (unsigned i = 0; i < other.mNumberBuffers; ++i) { 120 XAssert(mBufferCapacity == 0 || other.mBuffers[i].mDataByteSize <= mBufferCapacity); 121 memcpy(mABL.mBuffers[i].mData, other.mBuffers[i].mData, 122 mABL.mBuffers[i].mDataByteSize = other.mBuffers[i].mDataByteSize); 123 } 124 } 125 AppendFrom(CABufferList * blp,UInt32 nBytes)126 void AppendFrom(CABufferList *blp, UInt32 nBytes) 127 { 128 // this may mutate a buffer that owns memory. 129 AudioBuffer *mybuf = mABL.mBuffers, *srcbuf = blp->mABL.mBuffers; 130 for (UInt32 i = mABL.mNumberBuffers; i--; ++mybuf, ++srcbuf) { 131 XAssert(nBytes <= srcbuf->mDataByteSize); 132 XAssert(mBufferCapacity == 0 || mybuf->mDataByteSize + nBytes <= mBufferCapacity); 133 memcpy((Byte *)mybuf->mData + mybuf->mDataByteSize, srcbuf->mData, nBytes); 134 mybuf->mDataByteSize += nBytes; 135 } 136 blp->BytesConsumed(nBytes); 137 } 138 PadWithZeroes(UInt32 desiredBufferSize)139 void PadWithZeroes(UInt32 desiredBufferSize) 140 // for cases where an algorithm (e.g. SRC) requires some 141 // padding to create silence following end-of-file 142 { 143 XAssert(mBufferCapacity == 0 || desiredBufferSize <= mBufferCapacity); 144 if (GetNumBytes() > desiredBufferSize) return; 145 AudioBuffer *buf = mABL.mBuffers; 146 for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) { 147 memset((Byte *)buf->mData + buf->mDataByteSize, 0, desiredBufferSize - buf->mDataByteSize); 148 buf->mDataByteSize = desiredBufferSize; 149 } 150 } 151 SetToZeroes(UInt32 nBytes)152 void SetToZeroes(UInt32 nBytes) 153 { 154 XAssert(mBufferCapacity == 0 || nBytes <= mBufferCapacity); 155 AudioBuffer *buf = mABL.mBuffers; 156 for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) { 157 memset((Byte *)buf->mData, 0, nBytes); 158 buf->mDataByteSize = nBytes; 159 } 160 } 161 Reset()162 void Reset() 163 { 164 DeallocateBuffers(); 165 } 166 SameDataAs(const CABufferList * anotherBufferList)167 Boolean SameDataAs(const CABufferList* anotherBufferList) 168 { 169 // check to see if two buffer lists point to the same memory. 170 if (mABL.mNumberBuffers != anotherBufferList->mABL.mNumberBuffers) return false; 171 172 for (UInt32 i = 0; i < mABL.mNumberBuffers; ++i) { 173 if (mABL.mBuffers[i].mData != anotherBufferList->mABL.mBuffers[i].mData) return false; 174 } 175 return true; 176 } 177 BytesConsumed(UInt32 nBytes)178 void BytesConsumed(UInt32 nBytes) 179 // advance buffer pointers, decrease buffer sizes 180 { 181 VerifyNotTrashingOwnedBuffer(); 182 AudioBuffer *buf = mABL.mBuffers; 183 for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) { 184 XAssert(nBytes <= buf->mDataByteSize); 185 buf->mData = (Byte *)buf->mData + nBytes; 186 buf->mDataByteSize -= nBytes; 187 } 188 } 189 SetFrom(const AudioBufferList * abl)190 void SetFrom(const AudioBufferList *abl) 191 { 192 VerifyNotTrashingOwnedBuffer(); 193 memcpy(&_GetBufferList(), abl, (char *)&abl->mBuffers[abl->mNumberBuffers] - (char *)abl); 194 } 195 SetFrom(const CABufferList * blp)196 void SetFrom(const CABufferList *blp) 197 { 198 SetFrom(&blp->GetBufferList()); 199 } 200 SetFrom(const AudioBufferList * abl,UInt32 nBytes)201 void SetFrom(const AudioBufferList *abl, UInt32 nBytes) 202 { 203 VerifyNotTrashingOwnedBuffer(); 204 AudioBuffer *mybuf = mABL.mBuffers; 205 const AudioBuffer *srcbuf = abl->mBuffers; 206 for (UInt32 i = mABL.mNumberBuffers; i--; ++mybuf, ++srcbuf) { 207 mybuf->mNumberChannels = srcbuf->mNumberChannels; 208 mybuf->mDataByteSize = nBytes; 209 mybuf->mData = srcbuf->mData; 210 } 211 } 212 SetFrom(const CABufferList * blp,UInt32 nBytes)213 void SetFrom(const CABufferList *blp, UInt32 nBytes) 214 { 215 SetFrom(&blp->GetBufferList(), nBytes); 216 } 217 ToAudioBufferList(AudioBufferList * abl)218 AudioBufferList * ToAudioBufferList(AudioBufferList *abl) const 219 { 220 memcpy(abl, &GetBufferList(), (char *)&abl->mBuffers[mABL.mNumberBuffers] - (char *)abl); 221 return abl; 222 } 223 224 void AllocateBuffers(UInt32 nBytes); 225 void AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inCopyFromList, CABufferList *inSetPtrList); 226 227 void DeallocateBuffers(); 228 229 void UseExternalBuffer(Byte *ptr, UInt32 nBytes); 230 AdvanceBufferPointers(UInt32 nBytes)231 void AdvanceBufferPointers(UInt32 nBytes) // $$$ ReducingSize 232 // this is for bufferlists that function simply as 233 // an array of pointers into another bufferlist, being advanced, 234 // as in RenderOutput implementations 235 { 236 VerifyNotTrashingOwnedBuffer(); 237 AudioBuffer *buf = mABL.mBuffers; 238 for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) { 239 buf->mData = (Byte *)buf->mData + nBytes; 240 buf->mDataByteSize -= nBytes; 241 } 242 } 243 SetNumBytes(UInt32 nBytes)244 void SetNumBytes(UInt32 nBytes) 245 { 246 XAssert(mBufferCapacity == 0 || nBytes <= mBufferCapacity); 247 AudioBuffer *buf = mABL.mBuffers; 248 for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) 249 buf->mDataByteSize = nBytes; 250 } 251 252 void Print(const char *label=NULL, int nframes=0, int wordSize=0) const 253 { 254 if (label == NULL) 255 label = mName; 256 printf("%s - ", label); 257 CAShowAudioBufferList(&GetBufferList(), nframes, wordSize); 258 if (mBufferMemory) 259 printf(" owned memory @ 0x%p:\n", mBufferMemory); 260 } 261 GetCapacityBytes()262 UInt32 GetCapacityBytes() const { return mBufferCapacity; } 263 264 template <typename T> GetData(UInt32 inBuffer)265 T* GetData(UInt32 inBuffer) { 266 return static_cast<T*>(mABL.mBuffers[inBuffer].mData); 267 } 268 269 protected: _GetBufferList()270 AudioBufferList & _GetBufferList() { return mABL; } // use with care 271 // if we make this public, then we lose ability to call VerifyNotTrashingOwnedBuffer VerifyNotTrashingOwnedBuffer()272 void VerifyNotTrashingOwnedBuffer() 273 { 274 // This needs to be called from places where we are modifying the buffer pointers. 275 // It's an error to modify the buffer pointers or lengths if we own the buffer memory. 276 XAssert(mBufferMemory == NULL); 277 } 278 279 const char * mName; // for debugging 280 Byte * mBufferMemory; 281 UInt32 mBufferCapacity; // max mDataByteSize of each buffer 282 AudioBufferList mABL; 283 // don't add anything here 284 }; 285 286 #endif // __CABufferList_h__ 287