Jamoma API  0.6.0.a19
AUBuffer.h
1 /* Copyright 2007 Apple Inc. All Rights Reserved.
2 
3  Disclaimer: IMPORTANT: This Apple software is supplied to you by
4  Apple Inc. ("Apple") in consideration of your agreement to the
5  following terms, and your use, installation, modification or
6  redistribution of this Apple software constitutes acceptance of these
7  terms. If you do not agree with these terms, please do not use,
8  install, modify or redistribute this Apple software.
9 
10  In consideration of your agreement to abide by the following terms, and
11  subject to these terms, Apple grants you a personal, non-exclusive
12  license, under Apple's copyrights in this original Apple software (the
13  "Apple Software"), to use, reproduce, modify and redistribute the Apple
14  Software, with or without modifications, in source and/or binary forms;
15  provided that if you redistribute the Apple Software in its entirety and
16  without modifications, you must retain this notice and the following
17  text and disclaimers in all such redistributions of the Apple Software.
18  Neither the name, trademarks, service marks or logos of Apple Inc.
19  may be used to endorse or promote products derived from the Apple
20  Software without specific prior written permission from Apple. Except
21  as expressly stated in this notice, no other rights or licenses, express
22  or implied, are granted by Apple herein, including but not limited to
23  any patent rights that may be infringed by your derivative works or by
24  other works in which the Apple Software may be incorporated.
25 
26  The Apple Software is provided by Apple on an "AS IS" basis. APPLE
27  MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
28  THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
29  FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
30  OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
31 
32  IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
33  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
36  MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
37  AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
38  STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
39  POSSIBILITY OF SUCH DAMAGE.
40 */
41 #ifndef __AUBuffer_h__
42 #define __AUBuffer_h__
43 
44 #include <TargetConditionals.h>
45 #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
46  #include <AudioUnit/AudioUnit.h>
47 #else
48  #include <AudioUnit.h>
49 #endif
50 
51 #include <string.h>
52 #include "CAStreamBasicDescription.h"
53 #include "CAAutoDisposer.h"
54 #include "CADebugMacros.h"
55 
56 // make this usable outside the stricter context of AudiUnits
57 #ifndef COMPONENT_THROW
58  #define COMPONENT_THROW(err) \
59  do { DebugMessage(#err); throw static_cast<OSStatus>(err); } while (0)
60 #endif
61 
62 
63  /*! @class AUBufferList */
64 class AUBufferList {
65  enum EPtrState {
66  kPtrsInvalid,
67  kPtrsToMyMemory,
68  kPtrsToExternalMemory
69  };
70 public:
71  /*! @ctor AUBufferList */
72  AUBufferList() : mPtrState(kPtrsInvalid), mExternalMemory(false), mPtrs(NULL), mMemory(NULL),
73  mAllocatedStreams(0), mAllocatedFrames(0), mAllocatedBytes(0) { }
74  /*! @dtor ~AUBufferList */
75  ~AUBufferList();
76 
77  /*! @method PrepareBuffer */
78  AudioBufferList & PrepareBuffer(const CAStreamBasicDescription &format, UInt32 nFrames);
79  /*! @method PrepareNullBuffer */
80  AudioBufferList & PrepareNullBuffer(const CAStreamBasicDescription &format, UInt32 nFrames);
81 
82  /*! @method SetBufferList */
83  AudioBufferList & SetBufferList(const AudioBufferList &abl) {
84  if (mAllocatedStreams < abl.mNumberBuffers)
85  COMPONENT_THROW(-1);
86  mPtrState = kPtrsToExternalMemory;
87  memcpy(mPtrs, &abl, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl);
88  return *mPtrs;
89  }
90 
91  /*! @method SetBuffer */
92  void SetBuffer(UInt32 index, const AudioBuffer &ab) {
93  if (mPtrState == kPtrsInvalid || index >= mPtrs->mNumberBuffers)
94  COMPONENT_THROW(-1);
95  mPtrState = kPtrsToExternalMemory;
96  mPtrs->mBuffers[index] = ab;
97  }
98 
99  /*! @method InvalidateBufferList */
100  void InvalidateBufferList() { mPtrState = kPtrsInvalid; }
101 
102  /*! @method GetBufferList */
103  AudioBufferList & GetBufferList() const {
104  if (mPtrState == kPtrsInvalid)
105  COMPONENT_THROW(-1);
106  return *mPtrs;
107  }
108 
109  /*! @method CopyBufferListTo */
110  void CopyBufferListTo(AudioBufferList &abl) const {
111  if (mPtrState == kPtrsInvalid)
112  COMPONENT_THROW(-1);
113  memcpy(&abl, mPtrs, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl);
114  }
115 
116  /*! @method CopyBufferContentsTo */
117  void CopyBufferContentsTo(AudioBufferList &abl) const {
118  if (mPtrState == kPtrsInvalid)
119  COMPONENT_THROW(-1);
120  const AudioBuffer *srcbuf = mPtrs->mBuffers;
121  AudioBuffer *destbuf = abl.mBuffers;
122 
123  for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++srcbuf, ++destbuf) {
124  if (i >= mPtrs->mNumberBuffers) // duplicate last source to additional outputs [4341137]
125  --srcbuf;
126  if (destbuf->mData != srcbuf->mData)
127  memmove(destbuf->mData, srcbuf->mData, srcbuf->mDataByteSize);
128  destbuf->mDataByteSize = srcbuf->mDataByteSize;
129  }
130  }
131 
132  /*! @method Allocate */
133  void Allocate(const CAStreamBasicDescription &format, UInt32 nFrames);
134  /*! @method Deallocate */
135  void Deallocate();
136 
137  /*! @method UseExternalBuffer */
138  void UseExternalBuffer(const CAStreamBasicDescription &format, const AudioUnitExternalBuffer &buf);
139 
140  // AudioBufferList utilities
141  /*! @method ZeroBuffer */
142  static void ZeroBuffer(AudioBufferList &abl) {
143  AudioBuffer *buf = abl.mBuffers;
144  for (UInt32 i = abl.mNumberBuffers ; i--; ++buf)
145  memset(buf->mData, 0, buf->mDataByteSize);
146  }
147 #if DEBUG
148  /*! @method PrintBuffer */
149  static void PrintBuffer(const char *label, int subscript, const AudioBufferList &abl, UInt32 nFrames = 8, bool asFloats = true);
150 #endif
151 
152  /*! @method GetAllocatedFrames */
153  UInt32 GetAllocatedFrames() const { return mAllocatedFrames; }
154 
155 private:
156  /*! @ctor AUBufferList */
157  AUBufferList(AUBufferList &) { } // prohibit copy constructor
158 
159  /*! @var mPtrState */
160  EPtrState mPtrState;
161  /*! @var mExternalMemory */
162  bool mExternalMemory;
163  /*! @var mPtrs */
164  AudioBufferList * mPtrs;
165  /*! @var mMemory */
166  Byte * mMemory;
167  /*! @var mAllocatedStreams */
168  UInt32 mAllocatedStreams;
169  /*! @var mAllocatedFrames */
170  UInt32 mAllocatedFrames;
171  /*! @var mAllocatedBytes */
172  UInt32 mAllocatedBytes;
173 };
174 
175 
176 // Allocates an array of samples (type T), to be optimally aligned for the processor
177  /*! @class TAUBuffer */
178 template <class T>
179 class TAUBuffer {
180 public:
181  enum {
182  kAlignInterval = 0x10,
183  kAlignMask = kAlignInterval - 1
184  };
185 
186  /*! @ctor TAUBuffer.0 */
187  TAUBuffer() : mMemObject(NULL), mAlignedBuffer(NULL), mBufferSizeBytes(0)
188  {
189  }
190 
191  /*! @ctor TAUBuffer.1 */
192  TAUBuffer(UInt32 numElems, UInt32 numChannels) : mMemObject(NULL), mAlignedBuffer(NULL),
193  mBufferSizeBytes(0)
194  {
195  Allocate(numElems, numChannels);
196  }
197 
198  /*! @dtor ~TAUBuffer */
199  ~TAUBuffer()
200  {
201  Deallocate();
202  }
203 
204  /*! @method Allocate */
205  void Allocate(UInt32 numElems) // can also re-allocate
206  {
207  UInt32 reqSize = numElems * sizeof(T);
208 
209  if (mMemObject != NULL && reqSize == mBufferSizeBytes)
210  return; // already allocated
211 
212  mBufferSizeBytes = reqSize;
213  mMemObject = CA_realloc(mMemObject, reqSize);
214  UInt32 misalign = (uintptr_t)mMemObject & kAlignMask;
215  if (misalign) {
216  mMemObject = CA_realloc(mMemObject, reqSize + kAlignMask);
217  mAlignedBuffer = (T *)((char *)mMemObject + kAlignInterval - misalign);
218  } else
219  mAlignedBuffer = (T *)mMemObject;
220  }
221 
222  /*! @method Deallocate */
223  void Deallocate()
224  {
225  if (mMemObject == NULL) return; // so this method has no effect if we're using
226  // an external buffer
227 
228  free(mMemObject);
229  mMemObject = NULL;
230  mAlignedBuffer = NULL;
231  mBufferSizeBytes = 0;
232  }
233 
234  /*! @method AllocateClear */
235  void AllocateClear(UInt32 numElems) // can also re-allocate
236  {
237  Allocate(numElems);
238  Clear();
239  }
240 
241  /*! @method Clear */
242  void Clear()
243  {
244  memset(mAlignedBuffer, 0, mBufferSizeBytes);
245  }
246 
247  // accessors
248 
249  /*! @method operator T *()@ */
250  operator T *() { return mAlignedBuffer; }
251 
252 private:
253  /*! @var mMemObject */
254  void * mMemObject; // null when using an external buffer
255  /*! @var mAlignedBuffer */
256  T * mAlignedBuffer; // always valid once allocated
257  /*! @var mBufferSizeBytes */
258  UInt32 mBufferSizeBytes;
259 };
260 
261 #endif // __AUBuffer_h__