Make sure MSVC knows which version of 'floor()' we want
[ardour.git] / libs / appleutility / CoreAudio / PublicUtility / CABufferList.h
1 /*
2      File: CABufferList.h
3  Abstract: Part of CoreAudio Utility Classes
4   Version: 1.1
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) 2014 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:
74         void *  operator new(size_t /*size*/, int nBuffers) {
75                                 return ::operator new(sizeof(CABufferList) + (nBuffers-1) * sizeof(AudioBuffer));
76                         }
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         }
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:
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:
105         ~CABufferList()
106         {
107                 if (mBufferMemory)
108                         delete[] mBufferMemory;
109         }
110
111         const char *                            Name() { return mName; }
112
113         const AudioBufferList &         GetBufferList() const { return mABL; }
114
115         AudioBufferList &                       GetModifiableBufferList() { return _GetBufferList(); }
116
117         UInt32          GetNumberBuffers() const { return mABL.mNumberBuffers; }
118
119         UInt32          GetNumBytes() const
120         {
121                 return mABL.mBuffers[0].mDataByteSize;
122         }
123
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
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.
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
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
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
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
200         void            Reset()
201         {
202                 DeallocateBuffers();
203         }
204
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
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
228         void            SetFrom(const AudioBufferList *abl)
229         {
230                 VerifyNotTrashingOwnedBuffer();
231                 memcpy(&_GetBufferList(), abl, (char *)&abl->mBuffers[abl->mNumberBuffers] - (char *)abl);
232         }
233
234         void            SetFrom(const CABufferList *blp)
235         {
236                 SetFrom(&blp->GetBufferList());
237         }
238
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
251         void            SetFrom(const CABufferList *blp, UInt32 nBytes)
252         {
253                 SetFrom(&blp->GetBufferList(), nBytes);
254         }
255
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
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
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
300         UInt32          GetCapacityBytes() const { return mBufferCapacity; }
301
302         template <typename T>
303         T*                      GetData(UInt32 inBuffer) {
304                 return static_cast<T*>(mABL.mBuffers[inBuffer].mData);
305         }
306
307 protected:
308         AudioBufferList &       _GetBufferList() { return mABL; }       // use with care
309                                                         // if we make this public, then we lose ability to call VerifyNotTrashingOwnedBuffer
310         void                            VerifyNotTrashingOwnedBuffer()
311         {
312                 // This needs to be called from places where we are modifying the buffer pointers.
313                 // It's an error to modify the buffer pointers or lengths if we own the buffer memory.
314                 XAssert(mBufferMemory == NULL);
315         }
316
317         const char *                                            mName;  // for debugging
318         Byte *                                                          mBufferMemory;
319         UInt32                                                          mBufferCapacity;        // max mDataByteSize of each buffer
320         AudioBufferList                                         mABL;
321         // don't add anything here
322 };
323
324 #endif // __CABufferList_h__