Jamoma API  0.6.0.a19
CABufferList.cpp
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 #include "CABufferList.h"
42 #include "CAByteOrder.h"
43 
44 void CABufferList::AllocateBuffers(UInt32 nBytes)
45 {
46  if (nBytes <= GetNumBytes()) return;
47 
48  if (mNumberBuffers > 1)
49  // align successive buffers for Altivec and to take alternating
50  // cache line hits by spacing them by odd multiples of 16
51  nBytes = ((nBytes + 15) & ~15) | 16;
52  UInt32 memorySize = nBytes * mNumberBuffers;
53  Byte *newMemory = new Byte[memorySize], *p = newMemory;
54  memset(newMemory, 0, memorySize); // get page faults now, not later
55 
56  AudioBuffer *buf = mBuffers;
57  for (UInt32 i = mNumberBuffers; i--; ++buf) {
58  if (buf->mData != NULL && buf->mDataByteSize > 0)
59  // preserve existing buffer contents
60  memcpy(p, buf->mData, buf->mDataByteSize);
61  buf->mDataByteSize = nBytes;
62  buf->mData = p;
63  p += nBytes;
64  }
65  Byte *oldMemory = mBufferMemory;
66  mBufferMemory = newMemory;
67  delete[] oldMemory;
68 }
69 
70 void CABufferList::AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inSrcList, CABufferList *inSetPtrList)
71 {
72  if (mNumberBuffers != inSrcList->mNumberBuffers) return;
73  if (mNumberBuffers != inSetPtrList->mNumberBuffers) return;
74  if (nBytes <= GetNumBytes()) {
75  CopyAllFrom(inSrcList, inSetPtrList);
76  return;
77  }
78  inSetPtrList->VerifyNotTrashingOwnedBuffer();
79  UInt32 fromByteSize = inSrcList->GetNumBytes();
80 
81  if (mNumberBuffers > 1)
82  // align successive buffers for Altivec and to take alternating
83  // cache line hits by spacing them by odd multiples of 16
84  nBytes = ((nBytes + 15) & ~15) | 16;
85  UInt32 memorySize = nBytes * mNumberBuffers;
86  Byte *newMemory = new Byte[memorySize], *p = newMemory;
87  memset(newMemory, 0, memorySize); // make buffer "hot"
88 
89  AudioBuffer *buf = mBuffers;
90  AudioBuffer *ptrBuf = inSetPtrList->mBuffers;
91  AudioBuffer *srcBuf = inSrcList->mBuffers;
92  for (UInt32 i = mNumberBuffers; i--; ++buf, ++ptrBuf, ++srcBuf) {
93  if (srcBuf->mData != NULL && srcBuf->mDataByteSize > 0)
94  // preserve existing buffer contents
95  memmove(p, srcBuf->mData, srcBuf->mDataByteSize);
96  buf->mDataByteSize = nBytes;
97  buf->mData = p;
98  ptrBuf->mDataByteSize = srcBuf->mDataByteSize;
99  ptrBuf->mData = p;
100  p += nBytes;
101  }
102  Byte *oldMemory = mBufferMemory;
103  mBufferMemory = newMemory;
104  if (inSrcList != inSetPtrList)
105  inSrcList->BytesConsumed(fromByteSize);
106  delete[] oldMemory;
107 }
108 
109 void CABufferList::DeallocateBuffers()
110 {
111  AudioBuffer *buf = mBuffers;
112  for (UInt32 i = mNumberBuffers; i--; ++buf) {
113  buf->mData = NULL;
114  buf->mDataByteSize = 0;
115  }
116  if (mBufferMemory != NULL) {
117  delete[] mBufferMemory;
118  mBufferMemory = NULL;
119  }
120 
121 }
122 
123 static void show(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label, const char *fmtstr=NULL)
124 {
125  printf("%s %p (%d fr%s):\n", label ? label : "AudioBufferList", &abl, framesToPrint, fmtstr ? fmtstr : "");
126  const AudioBuffer *buf = abl.mBuffers;
127  for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++buf) {
128  printf(" [%2d] %5dbytes %dch @ %p", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData);
129  if (framesToPrint && buf->mData != NULL) {
130  printf(":");
131  Byte *p = (Byte *)buf->mData;
132  for (int j = framesToPrint * buf->mNumberChannels; --j >= 0; )
133  switch (wordSize) {
134  case 0: // native float
135  printf(" %6.3f", *(Float32 *)p);
136  p += sizeof(Float32);
137  break;
138  // positive: big endian
139  case 1:
140  case -1:
141  printf(" %02X", *p);
142  p += 1;
143  break;
144  case 2:
145  printf(" %04X", CFSwapInt16BigToHost(*(UInt16 *)p));
146  p += 2;
147  break;
148  case 3:
149  printf(" %06X", (p[0] << 16) | (p[1] << 8) | p[2]);
150  p += 3;
151  break;
152  case 4:
153  printf(" %08X", (unsigned int)CFSwapInt32BigToHost(*(UInt32 *)p));
154  p += 4;
155  break;
156  case 10:
157  printf(" %6.3f", CASwapFloat32BigToHost(*(Float32 *)p));
158  p += sizeof(Float32);
159  break;
160  case -2:
161  printf(" %04X", CFSwapInt16LittleToHost(*(UInt16 *)p));
162  p += 2;
163  break;
164  case -3:
165  printf(" %06X", (p[2] << 16) | (p[1] << 8) | p[0]);
166  p += 3;
167  break;
168  case -4:
169  printf(" %08X", (unsigned int)CFSwapInt32LittleToHost(*(UInt32 *)p));
170  p += 4;
171  break;
172  case -10:
173  printf(" %6.3f", CASwapFloat32LittleToHost(*(Float32 *)p));
174  p += sizeof(Float32);
175  break;
176  }
177  }
178  printf("\n");
179  }
180 }
181 
182 void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, const AudioStreamBasicDescription &asbd, const char *label)
183 {
184  CAStreamBasicDescription fmt(asbd);
185  int wordSize = 1;
186  char fmtstr[80] = { 0 };
187 
188  if (fmt.mFormatID == kAudioFormatLinearPCM) {
189  if (fmt.mFormatFlags & kLinearPCMFormatFlagIsFloat) {
190  if (fmt.mBitsPerChannel == 32) {
191  if (fmt.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) {
192  wordSize = 10;
193  strcpy(fmtstr, ", BEF");
194  } else {
195  wordSize = -10;
196  strcpy(fmtstr, ", LEF");
197  }
198  }
199  } else {
200  wordSize = fmt.SampleWordSize();
201  if (wordSize > 0) {
202 #if CA_PREFER_FIXED_POINT
203  int fracbits = (asbd.mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
204  if (fracbits > 0)
205  sprintf(fmtstr, ", %d.%d-bit", (int)asbd.mBitsPerChannel - fracbits, fracbits);
206  else
207 #endif
208  sprintf(fmtstr, ", %d-bit", (int)asbd.mBitsPerChannel);
209 
210  if (!(fmt.mFormatFlags & kLinearPCMFormatFlagIsBigEndian)) {
211  wordSize = -wordSize;
212  strcat(fmtstr, " LEI");
213  } else {
214  strcat(fmtstr, " BEI");
215  }
216  }
217  }
218  }
219  show(abl, framesToPrint, wordSize, label, fmtstr);
220 }
221 
222 void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label)
223 {
224  show(abl, framesToPrint, wordSize, label);
225 }
226 
227 extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize)
228 {
229  show(*abl, framesToPrint, wordSize, NULL);
230 }
231 
232 // if the return result is odd, there was a null buffer.
233 extern "C" int CrashIfClientProvidedBogusAudioBufferList(const AudioBufferList *abl, bool nullok)
234 {
235  const AudioBuffer *buf = abl->mBuffers, *bufend = buf + abl->mNumberBuffers;
236  int sum = 0; // defeat attempts by the compiler to optimize away the code that touches the buffers
237  int anyNull = 0;
238  for ( ; buf < bufend; ++buf) {
239  const int *p = (const int *)buf->mData;
240  if (p == NULL) {
241  anyNull = 1;
242  if (nullok) continue;
243  }
244  unsigned datasize = buf->mDataByteSize;
245  if (datasize >= sizeof(int)) {
246  sum += p[0];
247  sum += p[datasize / sizeof(int) - 1];
248  }
249  }
250  return anyNull | (sum & ~1);
251 }
252