AUPublic/Utility/AUBuffer.h
/* |
Copyright (C) 2016 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
Part of Core Audio AUBase Classes |
*/ |
#ifndef __AUBuffer_h__ |
#define __AUBuffer_h__ |
#include <TargetConditionals.h> |
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) |
#include <AudioUnit/AudioUnit.h> |
#else |
#include <AudioUnit.h> |
#endif |
#include <string.h> |
#include "CAStreamBasicDescription.h" |
#include "CAAutoDisposer.h" |
#include "CADebugMacros.h" |
// make this usable outside the stricter context of AudiUnits |
#ifndef COMPONENT_THROW |
#define COMPONENT_THROW(err) \ |
do { DebugMessage(#err); throw static_cast<OSStatus>(err); } while (0) |
#endif |
/*! @class AUBufferList */ |
class AUBufferList { |
enum EPtrState { |
kPtrsInvalid, |
kPtrsToMyMemory, |
kPtrsToExternalMemory |
}; |
public: |
/*! @ctor AUBufferList */ |
AUBufferList() : mPtrState(kPtrsInvalid), mExternalMemory(false), mPtrs(NULL), mMemory(NULL), |
mAllocatedStreams(0), mAllocatedFrames(0), mAllocatedBytes(0) { } |
/*! @dtor ~AUBufferList */ |
~AUBufferList(); |
/*! @method PrepareBuffer */ |
AudioBufferList & PrepareBuffer(const CAStreamBasicDescription &format, UInt32 nFrames); |
/*! @method PrepareNullBuffer */ |
AudioBufferList & PrepareNullBuffer(const CAStreamBasicDescription &format, UInt32 nFrames); |
/*! @method SetBufferList */ |
AudioBufferList & SetBufferList(const AudioBufferList &abl) { |
if (mAllocatedStreams < abl.mNumberBuffers) |
COMPONENT_THROW(-1); |
mPtrState = kPtrsToExternalMemory; |
memcpy(mPtrs, &abl, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl); |
return *mPtrs; |
} |
/*! @method SetBuffer */ |
void SetBuffer(UInt32 index, const AudioBuffer &ab) { |
if (mPtrState == kPtrsInvalid || index >= mPtrs->mNumberBuffers) |
COMPONENT_THROW(-1); |
mPtrState = kPtrsToExternalMemory; |
mPtrs->mBuffers[index] = ab; |
} |
/*! @method InvalidateBufferList */ |
void InvalidateBufferList() { mPtrState = kPtrsInvalid; } |
/*! @method GetBufferList */ |
AudioBufferList & GetBufferList() const { |
if (mPtrState == kPtrsInvalid) |
COMPONENT_THROW(-1); |
return *mPtrs; |
} |
/*! @method CopyBufferListTo */ |
void CopyBufferListTo(AudioBufferList &abl) const { |
if (mPtrState == kPtrsInvalid) |
COMPONENT_THROW(-1); |
memcpy(&abl, mPtrs, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl); |
} |
/*! @method CopyBufferContentsTo */ |
void CopyBufferContentsTo(AudioBufferList &abl) const { |
if (mPtrState == kPtrsInvalid) |
COMPONENT_THROW(-1); |
const AudioBuffer *srcbuf = mPtrs->mBuffers; |
AudioBuffer *destbuf = abl.mBuffers; |
for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++srcbuf, ++destbuf) { |
if (i >= mPtrs->mNumberBuffers) // duplicate last source to additional outputs [4341137] |
--srcbuf; |
if (destbuf->mData != srcbuf->mData) |
memmove(destbuf->mData, srcbuf->mData, srcbuf->mDataByteSize); |
destbuf->mDataByteSize = srcbuf->mDataByteSize; |
} |
} |
/*! @method Allocate */ |
void Allocate(const CAStreamBasicDescription &format, UInt32 nFrames); |
/*! @method Deallocate */ |
void Deallocate(); |
/*! @method UseExternalBuffer */ |
void UseExternalBuffer(const CAStreamBasicDescription &format, const AudioUnitExternalBuffer &buf); |
// AudioBufferList utilities |
/*! @method ZeroBuffer */ |
static void ZeroBuffer(AudioBufferList &abl) { |
AudioBuffer *buf = abl.mBuffers; |
for (UInt32 i = abl.mNumberBuffers ; i--; ++buf) |
memset(buf->mData, 0, buf->mDataByteSize); |
} |
#if DEBUG |
/*! @method PrintBuffer */ |
static void PrintBuffer(const char *label, int subscript, const AudioBufferList &abl, UInt32 nFrames = 8, bool asFloats = true); |
#endif |
/*! @method GetAllocatedFrames */ |
UInt32 GetAllocatedFrames() const { return mAllocatedFrames; } |
private: |
/*! @ctor AUBufferList */ |
AUBufferList(AUBufferList &) { } // prohibit copy constructor |
/*! @var mPtrState */ |
EPtrState mPtrState; |
/*! @var mExternalMemory */ |
bool mExternalMemory; |
/*! @var mPtrs */ |
AudioBufferList * mPtrs; |
/*! @var mMemory */ |
Byte * mMemory; |
/*! @var mAllocatedStreams */ |
UInt32 mAllocatedStreams; |
/*! @var mAllocatedFrames */ |
UInt32 mAllocatedFrames; |
/*! @var mAllocatedBytes */ |
UInt32 mAllocatedBytes; |
}; |
// Allocates an array of samples (type T), to be optimally aligned for the processor |
/*! @class TAUBuffer */ |
template <class T> |
class TAUBuffer { |
public: |
enum { |
kAlignInterval = 0x10, |
kAlignMask = kAlignInterval - 1 |
}; |
/*! @ctor TAUBuffer.0 */ |
TAUBuffer() : mMemObject(NULL), mAlignedBuffer(NULL), mBufferSizeBytes(0) |
{ |
} |
/*! @ctor TAUBuffer.1 */ |
TAUBuffer(UInt32 numElems, UInt32 numChannels) : mMemObject(NULL), mAlignedBuffer(NULL), |
mBufferSizeBytes(0) |
{ |
Allocate(numElems, numChannels); |
} |
/*! @dtor ~TAUBuffer */ |
~TAUBuffer() |
{ |
Deallocate(); |
} |
/*! @method Allocate */ |
void Allocate(UInt32 numElems) // can also re-allocate |
{ |
UInt32 reqSize = numElems * sizeof(T); |
if (mMemObject != NULL && reqSize == mBufferSizeBytes) |
return; // already allocated |
mBufferSizeBytes = reqSize; |
mMemObject = CA_realloc(mMemObject, reqSize); |
UInt32 misalign = (uintptr_t)mMemObject & kAlignMask; |
if (misalign) { |
mMemObject = CA_realloc(mMemObject, reqSize + kAlignMask); |
mAlignedBuffer = (T *)((char *)mMemObject + kAlignInterval - misalign); |
} else |
mAlignedBuffer = (T *)mMemObject; |
} |
/*! @method Deallocate */ |
void Deallocate() |
{ |
if (mMemObject == NULL) return; // so this method has no effect if we're using |
// an external buffer |
free(mMemObject); |
mMemObject = NULL; |
mAlignedBuffer = NULL; |
mBufferSizeBytes = 0; |
} |
/*! @method AllocateClear */ |
void AllocateClear(UInt32 numElems) // can also re-allocate |
{ |
Allocate(numElems); |
Clear(); |
} |
/*! @method Clear */ |
void Clear() |
{ |
memset(mAlignedBuffer, 0, mBufferSizeBytes); |
} |
// accessors |
/*! @method operator T *()@ */ |
operator T *() { return mAlignedBuffer; } |
private: |
/*! @var mMemObject */ |
void * mMemObject; // null when using an external buffer |
/*! @var mAlignedBuffer */ |
T * mAlignedBuffer; // always valid once allocated |
/*! @var mBufferSizeBytes */ |
UInt32 mBufferSizeBytes; |
}; |
#endif // __AUBuffer_h__ |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-02-19