Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Relevant replacement documents include:
AUPublic/Utility/AUBuffer.cpp
/* |
<codex> |
<abstract>AUBuffer.h</abstract> |
<\codex> |
*/ |
#include "AUBuffer.h" |
#include <stdlib.h> |
AUBufferList::~AUBufferList() |
{ |
Deallocate(); |
if (mPtrs) |
free(mPtrs); |
} |
// a * b + c |
static UInt32 SafeMultiplyAddUInt32(UInt32 a, UInt32 b, UInt32 c) |
{ |
if (a == 0 || b == 0) return c; // prevent zero divide |
if (a > (0xFFFFFFFF - c) / b) |
throw std::bad_alloc(); |
return a * b + c; |
} |
void AUBufferList::Allocate(const CAStreamBasicDescription &format, UInt32 nFrames) |
{ |
UInt32 nStreams; |
if (format.IsInterleaved()) { |
nStreams = 1; |
} else { |
nStreams = format.mChannelsPerFrame; |
} |
// careful -- the I/O thread could be running! |
if (nStreams > mAllocatedStreams) { |
mPtrs = (AudioBufferList *)CA_realloc(mPtrs, SafeMultiplyAddUInt32(nStreams, sizeof(AudioBuffer), offsetof(AudioBufferList, mBuffers))); |
mAllocatedStreams = nStreams; |
} |
UInt32 bytesPerStream = SafeMultiplyAddUInt32(nFrames, format.mBytesPerFrame, 0xF) & ~0xF; |
UInt32 nBytes = SafeMultiplyAddUInt32(nStreams, bytesPerStream, 0); |
if (nBytes > mAllocatedBytes) { |
if (mExternalMemory) { |
mExternalMemory = false; |
mMemory = NULL; |
} |
mMemory = (Byte *)CA_realloc(mMemory, nBytes); |
mAllocatedBytes = nBytes; |
} |
mAllocatedFrames = nFrames; |
mPtrState = kPtrsInvalid; |
} |
void AUBufferList::Deallocate() |
{ |
mAllocatedStreams = 0; |
mAllocatedFrames = 0; |
mAllocatedBytes = 0; |
// this causes a world of hurt if someone upstream disconnects during I/O (SysSoundGraph) |
/* if (mPtrs) { |
printf("deallocating bufferlist %08X\n", int(mPtrs)); |
free(mPtrs); |
mPtrs = NULL; |
} */ |
if (mMemory) { |
if (mExternalMemory) |
mExternalMemory = false; |
else |
free(mMemory); |
mMemory = NULL; |
} |
mPtrState = kPtrsInvalid; |
} |
AudioBufferList & AUBufferList::PrepareBuffer(const CAStreamBasicDescription &format, UInt32 nFrames) |
{ |
if (nFrames > mAllocatedFrames) |
COMPONENT_THROW(kAudioUnitErr_TooManyFramesToProcess); |
UInt32 nStreams; |
UInt32 channelsPerStream; |
if (format.IsInterleaved()) { |
nStreams = 1; |
channelsPerStream = format.mChannelsPerFrame; |
} else { |
nStreams = format.mChannelsPerFrame; |
channelsPerStream = 1; |
if (nStreams > mAllocatedStreams) |
COMPONENT_THROW(kAudioUnitErr_FormatNotSupported); |
} |
AudioBufferList *abl = mPtrs; |
abl->mNumberBuffers = nStreams; |
AudioBuffer *buf = abl->mBuffers; |
Byte *mem = mMemory; |
UInt32 streamInterval = (mAllocatedFrames * format.mBytesPerFrame + 0xF) & ~0xF; |
UInt32 bytesPerBuffer = nFrames * format.mBytesPerFrame; |
for ( ; nStreams--; ++buf) { |
buf->mNumberChannels = channelsPerStream; |
buf->mData = mem; |
buf->mDataByteSize = bytesPerBuffer; |
mem += streamInterval; |
} |
if (UInt32(mem - mMemory) > mAllocatedBytes) |
COMPONENT_THROW(kAudioUnitErr_TooManyFramesToProcess); |
mPtrState = kPtrsToMyMemory; |
return *mPtrs; |
} |
AudioBufferList & AUBufferList::PrepareNullBuffer(const CAStreamBasicDescription &format, UInt32 nFrames) |
{ |
UInt32 nStreams; |
UInt32 channelsPerStream; |
if (format.IsInterleaved()) { |
nStreams = 1; |
channelsPerStream = format.mChannelsPerFrame; |
} else { |
nStreams = format.mChannelsPerFrame; |
channelsPerStream = 1; |
if (nStreams > mAllocatedStreams) |
COMPONENT_THROW(kAudioUnitErr_FormatNotSupported); |
} |
AudioBufferList *abl = mPtrs; |
abl->mNumberBuffers = nStreams; |
AudioBuffer *buf = abl->mBuffers; |
UInt32 bytesPerBuffer = nFrames * format.mBytesPerFrame; |
for ( ; nStreams--; ++buf) { |
buf->mNumberChannels = channelsPerStream; |
buf->mData = NULL; |
buf->mDataByteSize = bytesPerBuffer; |
} |
mPtrState = kPtrsToExternalMemory; |
return *mPtrs; |
} |
// this should NOT be called while I/O is in process |
void AUBufferList::UseExternalBuffer(const CAStreamBasicDescription &format, const AudioUnitExternalBuffer &buf) |
{ |
UInt32 alignedSize = buf.size & ~0xF; |
if (mMemory != NULL && alignedSize >= mAllocatedBytes) { |
// don't accept the buffer if we already have one and it's big enough |
// if we don't already have one, we don't need one |
Byte *oldMemory = mMemory; |
mMemory = buf.buffer; |
mAllocatedBytes = alignedSize; |
// from Allocate(): nBytes = nStreams * nFrames * format.mBytesPerFrame; |
// thus: nFrames = nBytes / (nStreams * format.mBytesPerFrame) |
mAllocatedFrames = mAllocatedBytes / (format.NumberChannelStreams() * format.mBytesPerFrame); |
mExternalMemory = true; |
free(oldMemory); |
} |
} |
#if DEBUG |
void AUBufferList::PrintBuffer(const char *label, int subscript, const AudioBufferList &abl, UInt32 nFrames, bool asFloats) |
{ |
printf(" %s [%d] 0x%08lX:\n", label, subscript, long(&abl)); |
const AudioBuffer *buf = abl.mBuffers; |
for (UInt32 i = 0; i < abl.mNumberBuffers; ++buf, ++i) { |
printf(" [%2d] %5dbytes %dch @ %p: ", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData); |
if (buf->mData != NULL) { |
UInt32 nSamples = nFrames * buf->mNumberChannels; |
for (UInt32 j = 0; j < nSamples; ++j) { |
if (nSamples > 16 && (j % 16) == 0) |
printf("\n\t"); |
if (asFloats) |
printf(" %6.3f", ((float *)buf->mData)[j]); |
else |
printf(" %08X", (unsigned)((UInt32 *)buf->mData)[j]); |
} |
} |
printf("\n"); |
} |
} |
#endif |
Copyright © 2012 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2012-10-08