Update Source To OpenAL-67

This commit is contained in:
Thomas A 2022-12-10 15:56:58 -08:00
parent ee85e01fbc
commit 19c7b3ed2f
49 changed files with 196 additions and 7416 deletions

View File

@ -1 +0,0 @@
al

View File

@ -12,8 +12,8 @@ _alGetIntegerv
_alGetFloatv
_alGetDoublev
_alGetString
_alSetInteger
_alSetDouble
#_alSetInteger
#_alSetDouble
_alGetError
_alIsExtensionPresent
_alGetProcAddress
@ -75,7 +75,7 @@ _alDistanceModel
_alDopplerFactor
_alDopplerVelocity
_alSpeedOfSound
_alHint
# _alHint
# from alc.h
_alcGetString
@ -108,18 +108,18 @@ _alutLoadWAVMemory
_alutUnloadWAV
# from OSX_EXTENSION
_alcMacOSXRenderingQuality
_alMacOSXRenderChannelCount
_alcMacOSXMixerMaxiumumBusses
_alcMacOSXMixerOutputRate
_alcMacOSXGetRenderingQuality
_alMacOSXGetRenderChannelCount
_alcMacOSXGetMixerMaxiumumBusses
_alcMacOSXGetMixerOutputRate
_alBufferDataStatic
#_alcMacOSXRenderingQuality
#_alMacOSXRenderChannelCount
#_alcMacOSXMixerMaxiumumBusses
#_alcMacOSXMixerOutputRate
#_alcMacOSXGetRenderingQuality
#_alMacOSXGetRenderChannelCount
#_alcMacOSXGetMixerMaxiumumBusses
#_alcMacOSXGetMixerOutputRate
#_alBufferDataStatic
# from APPLE_ENVIRONMENTAL_AUDIO_EXTENSION
_alcASAGetSource
_alcASASetSource
_alcASAGetListener
_alcASASetListener
#_alcASAGetSource
#_alcASASetSource
#_alcASAGetListener
#_alcASASetListener

View File

@ -1,6 +1,8 @@
#ifndef AL_AL_H
#define AL_AL_H
#include <os/availability.h>
#if defined(__cplusplus)
extern "C" {
#endif
@ -30,6 +32,10 @@ extern "C" {
#pragma export on
#endif
#ifndef OPENAL_DEPRECATED
#define OPENAL_DEPRECATED API_DEPRECATED("OpenAL is deprecated in favor of AVAudioEngine", macos(10.4, 10.15), ios(2.0, 13.0))
#endif // OPENAL_DEPRECATED
/*
* The OPENAL, ALAPI, ALAPIENTRY, AL_INVALID, AL_ILLEGAL_ENUM, and
* AL_ILLEGAL_COMMAND macros are deprecated, but are included for
@ -363,40 +369,40 @@ typedef void ALvoid;
/*
* Renderer State management
*/
AL_API void AL_APIENTRY alEnable( ALenum capability );
AL_API void AL_APIENTRY alEnable( ALenum capability ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alDisable( ALenum capability );
AL_API void AL_APIENTRY alDisable( ALenum capability ) OPENAL_DEPRECATED;
AL_API ALboolean AL_APIENTRY alIsEnabled( ALenum capability );
AL_API ALboolean AL_APIENTRY alIsEnabled( ALenum capability ) OPENAL_DEPRECATED;
/*
* State retrieval
*/
AL_API const ALchar* AL_APIENTRY alGetString( ALenum param );
AL_API const ALchar* AL_APIENTRY alGetString( ALenum param ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetBooleanv( ALenum param, ALboolean* data );
AL_API void AL_APIENTRY alGetBooleanv( ALenum param, ALboolean* data ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetIntegerv( ALenum param, ALint* data );
AL_API void AL_APIENTRY alGetIntegerv( ALenum param, ALint* data ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetFloatv( ALenum param, ALfloat* data );
AL_API void AL_APIENTRY alGetFloatv( ALenum param, ALfloat* data ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetDoublev( ALenum param, ALdouble* data );
AL_API void AL_APIENTRY alGetDoublev( ALenum param, ALdouble* data ) OPENAL_DEPRECATED;
AL_API ALboolean AL_APIENTRY alGetBoolean( ALenum param );
AL_API ALboolean AL_APIENTRY alGetBoolean( ALenum param ) OPENAL_DEPRECATED;
AL_API ALint AL_APIENTRY alGetInteger( ALenum param );
AL_API ALint AL_APIENTRY alGetInteger( ALenum param ) OPENAL_DEPRECATED;
AL_API ALfloat AL_APIENTRY alGetFloat( ALenum param );
AL_API ALfloat AL_APIENTRY alGetFloat( ALenum param ) OPENAL_DEPRECATED;
AL_API ALdouble AL_APIENTRY alGetDouble( ALenum param );
AL_API ALdouble AL_APIENTRY alGetDouble( ALenum param ) OPENAL_DEPRECATED;
/*
* Error support.
* Obtain the most recent error generated in the AL state machine.
*/
AL_API ALenum AL_APIENTRY alGetError( void );
AL_API ALenum AL_APIENTRY alGetError( void ) OPENAL_DEPRECATED;
/*
@ -404,11 +410,11 @@ AL_API ALenum AL_APIENTRY alGetError( void );
* Query for the presence of an extension, and obtain any appropriate
* function pointers and enum values.
*/
AL_API ALboolean AL_APIENTRY alIsExtensionPresent( const ALchar* extname );
AL_API ALboolean AL_APIENTRY alIsExtensionPresent( const ALchar* extname ) OPENAL_DEPRECATED;
AL_API void* AL_APIENTRY alGetProcAddress( const ALchar* fname );
AL_API void* AL_APIENTRY alGetProcAddress( const ALchar* fname ) OPENAL_DEPRECATED;
AL_API ALenum AL_APIENTRY alGetEnumValue( const ALchar* ename );
AL_API ALenum AL_APIENTRY alGetEnumValue( const ALchar* ename ) OPENAL_DEPRECATED;
/*
@ -427,32 +433,32 @@ AL_API ALenum AL_APIENTRY alGetEnumValue( const ALchar* ename );
/*
* Set Listener parameters
*/
AL_API void AL_APIENTRY alListenerf( ALenum param, ALfloat value );
AL_API void AL_APIENTRY alListenerf( ALenum param, ALfloat value ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alListener3f( ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 );
AL_API void AL_APIENTRY alListener3f( ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alListenerfv( ALenum param, const ALfloat* values );
AL_API void AL_APIENTRY alListenerfv( ALenum param, const ALfloat* values ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alListeneri( ALenum param, ALint value );
AL_API void AL_APIENTRY alListeneri( ALenum param, ALint value ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alListener3i( ALenum param, ALint value1, ALint value2, ALint value3 );
AL_API void AL_APIENTRY alListener3i( ALenum param, ALint value1, ALint value2, ALint value3 ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alListeneriv( ALenum param, const ALint* values );
AL_API void AL_APIENTRY alListeneriv( ALenum param, const ALint* values ) OPENAL_DEPRECATED;
/*
* Get Listener parameters
*/
AL_API void AL_APIENTRY alGetListenerf( ALenum param, ALfloat* value );
AL_API void AL_APIENTRY alGetListenerf( ALenum param, ALfloat* value ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetListener3f( ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3 );
AL_API void AL_APIENTRY alGetListener3f( ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3 ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetListenerfv( ALenum param, ALfloat* values );
AL_API void AL_APIENTRY alGetListenerfv( ALenum param, ALfloat* values ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetListeneri( ALenum param, ALint* value );
AL_API void AL_APIENTRY alGetListeneri( ALenum param, ALint* value ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetListener3i( ALenum param, ALint *value1, ALint *value2, ALint *value3 );
AL_API void AL_APIENTRY alGetListener3i( ALenum param, ALint *value1, ALint *value2, ALint *value3 ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetListeneriv( ALenum param, ALint* values );
AL_API void AL_APIENTRY alGetListeneriv( ALenum param, ALint* values ) OPENAL_DEPRECATED;
/**
@ -489,43 +495,43 @@ AL_API void AL_APIENTRY alGetListeneriv( ALenum param, ALint* values );
*/
/* Create Source objects */
AL_API void AL_APIENTRY alGenSources( ALsizei n, ALuint* sources );
AL_API void AL_APIENTRY alGenSources( ALsizei n, ALuint* sources ) OPENAL_DEPRECATED;
/* Delete Source objects */
AL_API void AL_APIENTRY alDeleteSources( ALsizei n, const ALuint* sources );
AL_API void AL_APIENTRY alDeleteSources( ALsizei n, const ALuint* sources ) OPENAL_DEPRECATED;
/* Verify a handle is a valid Source */
AL_API ALboolean AL_APIENTRY alIsSource( ALuint sid );
AL_API ALboolean AL_APIENTRY alIsSource( ALuint sid ) OPENAL_DEPRECATED;
/*
* Set Source parameters
*/
AL_API void AL_APIENTRY alSourcef( ALuint sid, ALenum param, ALfloat value );
AL_API void AL_APIENTRY alSourcef( ALuint sid, ALenum param, ALfloat value ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alSource3f( ALuint sid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 );
AL_API void AL_APIENTRY alSource3f( ALuint sid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alSourcefv( ALuint sid, ALenum param, const ALfloat* values );
AL_API void AL_APIENTRY alSourcefv( ALuint sid, ALenum param, const ALfloat* values ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alSourcei( ALuint sid, ALenum param, ALint value );
AL_API void AL_APIENTRY alSourcei( ALuint sid, ALenum param, ALint value ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alSource3i( ALuint sid, ALenum param, ALint value1, ALint value2, ALint value3 );
AL_API void AL_APIENTRY alSource3i( ALuint sid, ALenum param, ALint value1, ALint value2, ALint value3 ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alSourceiv( ALuint sid, ALenum param, const ALint* values );
AL_API void AL_APIENTRY alSourceiv( ALuint sid, ALenum param, const ALint* values ) OPENAL_DEPRECATED;
/*
* Get Source parameters
*/
AL_API void AL_APIENTRY alGetSourcef( ALuint sid, ALenum param, ALfloat* value );
AL_API void AL_APIENTRY alGetSourcef( ALuint sid, ALenum param, ALfloat* value ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetSource3f( ALuint sid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3);
AL_API void AL_APIENTRY alGetSource3f( ALuint sid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetSourcefv( ALuint sid, ALenum param, ALfloat* values );
AL_API void AL_APIENTRY alGetSourcefv( ALuint sid, ALenum param, ALfloat* values ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetSourcei( ALuint sid, ALenum param, ALint* value );
AL_API void AL_APIENTRY alGetSourcei( ALuint sid, ALenum param, ALint* value ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetSource3i( ALuint sid, ALenum param, ALint* value1, ALint* value2, ALint* value3);
AL_API void AL_APIENTRY alGetSource3i( ALuint sid, ALenum param, ALint* value1, ALint* value2, ALint* value3) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetSourceiv( ALuint sid, ALenum param, ALint* values );
AL_API void AL_APIENTRY alGetSourceiv( ALuint sid, ALenum param, ALint* values ) OPENAL_DEPRECATED;
/*
@ -533,39 +539,39 @@ AL_API void AL_APIENTRY alGetSourceiv( ALuint sid, ALenum param, ALint* values
*/
/* Play, replay, or resume (if paused) a list of Sources */
AL_API void AL_APIENTRY alSourcePlayv( ALsizei ns, const ALuint *sids );
AL_API void AL_APIENTRY alSourcePlayv( ALsizei ns, const ALuint *sids ) OPENAL_DEPRECATED;
/* Stop a list of Sources */
AL_API void AL_APIENTRY alSourceStopv( ALsizei ns, const ALuint *sids );
AL_API void AL_APIENTRY alSourceStopv( ALsizei ns, const ALuint *sids ) OPENAL_DEPRECATED;
/* Rewind a list of Sources */
AL_API void AL_APIENTRY alSourceRewindv( ALsizei ns, const ALuint *sids );
AL_API void AL_APIENTRY alSourceRewindv( ALsizei ns, const ALuint *sids ) OPENAL_DEPRECATED;
/* Pause a list of Sources */
AL_API void AL_APIENTRY alSourcePausev( ALsizei ns, const ALuint *sids );
AL_API void AL_APIENTRY alSourcePausev( ALsizei ns, const ALuint *sids ) OPENAL_DEPRECATED;
/*
* Source based playback calls
*/
/* Play, replay, or resume a Source */
AL_API void AL_APIENTRY alSourcePlay( ALuint sid );
AL_API void AL_APIENTRY alSourcePlay( ALuint sid ) OPENAL_DEPRECATED;
/* Stop a Source */
AL_API void AL_APIENTRY alSourceStop( ALuint sid );
AL_API void AL_APIENTRY alSourceStop( ALuint sid ) OPENAL_DEPRECATED;
/* Rewind a Source (set playback postiton to beginning) */
AL_API void AL_APIENTRY alSourceRewind( ALuint sid );
AL_API void AL_APIENTRY alSourceRewind( ALuint sid ) OPENAL_DEPRECATED;
/* Pause a Source */
AL_API void AL_APIENTRY alSourcePause( ALuint sid );
AL_API void AL_APIENTRY alSourcePause( ALuint sid ) OPENAL_DEPRECATED;
/*
* Source Queuing
*/
AL_API void AL_APIENTRY alSourceQueueBuffers( ALuint sid, ALsizei numEntries, const ALuint *bids );
AL_API void AL_APIENTRY alSourceQueueBuffers( ALuint sid, ALsizei numEntries, const ALuint *bids ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alSourceUnqueueBuffers( ALuint sid, ALsizei numEntries, ALuint *bids );
AL_API void AL_APIENTRY alSourceUnqueueBuffers( ALuint sid, ALsizei numEntries, ALuint *bids ) OPENAL_DEPRECATED;
/**
@ -583,58 +589,58 @@ AL_API void AL_APIENTRY alSourceUnqueueBuffers( ALuint sid, ALsizei numEntries,
*/
/* Create Buffer objects */
AL_API void AL_APIENTRY alGenBuffers( ALsizei n, ALuint* buffers );
AL_API void AL_APIENTRY alGenBuffers( ALsizei n, ALuint* buffers ) OPENAL_DEPRECATED;
/* Delete Buffer objects */
AL_API void AL_APIENTRY alDeleteBuffers( ALsizei n, const ALuint* buffers );
AL_API void AL_APIENTRY alDeleteBuffers( ALsizei n, const ALuint* buffers ) OPENAL_DEPRECATED;
/* Verify a handle is a valid Buffer */
AL_API ALboolean AL_APIENTRY alIsBuffer( ALuint bid );
AL_API ALboolean AL_APIENTRY alIsBuffer( ALuint bid ) OPENAL_DEPRECATED;
/* Specify the data to be copied into a buffer */
AL_API void AL_APIENTRY alBufferData( ALuint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq );
AL_API void AL_APIENTRY alBufferData( ALuint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq ) OPENAL_DEPRECATED;
/*
* Set Buffer parameters
*/
AL_API void AL_APIENTRY alBufferf( ALuint bid, ALenum param, ALfloat value );
AL_API void AL_APIENTRY alBufferf( ALuint bid, ALenum param, ALfloat value ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alBuffer3f( ALuint bid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 );
AL_API void AL_APIENTRY alBuffer3f( ALuint bid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alBufferfv( ALuint bid, ALenum param, const ALfloat* values );
AL_API void AL_APIENTRY alBufferfv( ALuint bid, ALenum param, const ALfloat* values ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alBufferi( ALuint bid, ALenum param, ALint value );
AL_API void AL_APIENTRY alBufferi( ALuint bid, ALenum param, ALint value ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alBuffer3i( ALuint bid, ALenum param, ALint value1, ALint value2, ALint value3 );
AL_API void AL_APIENTRY alBuffer3i( ALuint bid, ALenum param, ALint value1, ALint value2, ALint value3 ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alBufferiv( ALuint bid, ALenum param, const ALint* values );
AL_API void AL_APIENTRY alBufferiv( ALuint bid, ALenum param, const ALint* values ) OPENAL_DEPRECATED;
/*
* Get Buffer parameters
*/
AL_API void AL_APIENTRY alGetBufferf( ALuint bid, ALenum param, ALfloat* value );
AL_API void AL_APIENTRY alGetBufferf( ALuint bid, ALenum param, ALfloat* value ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetBuffer3f( ALuint bid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3);
AL_API void AL_APIENTRY alGetBuffer3f( ALuint bid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetBufferfv( ALuint bid, ALenum param, ALfloat* values );
AL_API void AL_APIENTRY alGetBufferfv( ALuint bid, ALenum param, ALfloat* values ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetBufferi( ALuint bid, ALenum param, ALint* value );
AL_API void AL_APIENTRY alGetBufferi( ALuint bid, ALenum param, ALint* value ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetBuffer3i( ALuint bid, ALenum param, ALint* value1, ALint* value2, ALint* value3);
AL_API void AL_APIENTRY alGetBuffer3i( ALuint bid, ALenum param, ALint* value1, ALint* value2, ALint* value3) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alGetBufferiv( ALuint bid, ALenum param, ALint* values );
AL_API void AL_APIENTRY alGetBufferiv( ALuint bid, ALenum param, ALint* values ) OPENAL_DEPRECATED;
/*
* Global Parameters
*/
AL_API void AL_APIENTRY alDopplerFactor( ALfloat value );
AL_API void AL_APIENTRY alDopplerFactor( ALfloat value ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alDopplerVelocity( ALfloat value );
AL_API void AL_APIENTRY alDopplerVelocity( ALfloat value ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alSpeedOfSound( ALfloat value );
AL_API void AL_APIENTRY alSpeedOfSound( ALfloat value ) OPENAL_DEPRECATED;
AL_API void AL_APIENTRY alDistanceModel( ALenum distanceModel );
AL_API void AL_APIENTRY alDistanceModel( ALenum distanceModel ) OPENAL_DEPRECATED;
/*
* Pointer-to-function types, useful for dynamically getting AL entry points.

View File

@ -1,6 +1,8 @@
#ifndef AL_ALC_H
#define AL_ALC_H
#include <os/availability.h>
#if defined(__cplusplus)
extern "C" {
#endif
@ -38,6 +40,9 @@ extern "C" {
#define ALCAPIENTRY ALC_APIENTRY
#define ALC_INVALID 0
#ifndef OPENAL_DEPRECATED
#define OPENAL_DEPRECATED API_DEPRECATED("OpenAL is deprecated", macos(10.4, 10.15), ios(2.0, 13.0))
#endif // OPENAL_DEPRECATED
#define ALC_VERSION_0_1 1
@ -183,34 +188,34 @@ typedef void ALCvoid;
/*
* Context Management
*/
ALC_API ALCcontext * ALC_APIENTRY alcCreateContext( ALCdevice *device, const ALCint* attrlist );
ALC_API ALCcontext * ALC_APIENTRY alcCreateContext( ALCdevice *device, const ALCint* attrlist ) OPENAL_DEPRECATED;
ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent( ALCcontext *context );
ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent( ALCcontext *context ) OPENAL_DEPRECATED;
ALC_API void ALC_APIENTRY alcProcessContext( ALCcontext *context );
ALC_API void ALC_APIENTRY alcProcessContext( ALCcontext *context ) OPENAL_DEPRECATED;
ALC_API void ALC_APIENTRY alcSuspendContext( ALCcontext *context );
ALC_API void ALC_APIENTRY alcSuspendContext( ALCcontext *context ) OPENAL_DEPRECATED;
ALC_API void ALC_APIENTRY alcDestroyContext( ALCcontext *context );
ALC_API void ALC_APIENTRY alcDestroyContext( ALCcontext *context ) OPENAL_DEPRECATED;
ALC_API ALCcontext * ALC_APIENTRY alcGetCurrentContext( void );
ALC_API ALCcontext * ALC_APIENTRY alcGetCurrentContext( void ) OPENAL_DEPRECATED;
ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice( ALCcontext *context );
ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice( ALCcontext *context ) OPENAL_DEPRECATED;
/*
* Device Management
*/
ALC_API ALCdevice * ALC_APIENTRY alcOpenDevice( const ALCchar *devicename );
ALC_API ALCdevice * ALC_APIENTRY alcOpenDevice( const ALCchar *devicename ) OPENAL_DEPRECATED;
ALC_API ALCboolean ALC_APIENTRY alcCloseDevice( ALCdevice *device );
ALC_API ALCboolean ALC_APIENTRY alcCloseDevice( ALCdevice *device ) OPENAL_DEPRECATED;
/*
* Error support.
* Obtain the most recent Context error
*/
ALC_API ALCenum ALC_APIENTRY alcGetError( ALCdevice *device );
ALC_API ALCenum ALC_APIENTRY alcGetError( ALCdevice *device ) OPENAL_DEPRECATED;
/*
@ -218,33 +223,33 @@ ALC_API ALCenum ALC_APIENTRY alcGetError( ALCdevice *device );
* Query for the presence of an extension, and obtain any appropriate
* function pointers and enum values.
*/
ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent( ALCdevice *device, const ALCchar *extname );
ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent( ALCdevice *device, const ALCchar *extname ) OPENAL_DEPRECATED;
ALC_API void * ALC_APIENTRY alcGetProcAddress( ALCdevice *device, const ALCchar *funcname );
ALC_API void * ALC_APIENTRY alcGetProcAddress( ALCdevice *device, const ALCchar *funcname ) OPENAL_DEPRECATED;
ALC_API ALCenum ALC_APIENTRY alcGetEnumValue( ALCdevice *device, const ALCchar *enumname );
ALC_API ALCenum ALC_APIENTRY alcGetEnumValue( ALCdevice *device, const ALCchar *enumname ) OPENAL_DEPRECATED;
/*
* Query functions
*/
ALC_API const ALCchar * ALC_APIENTRY alcGetString( ALCdevice *device, ALCenum param );
ALC_API const ALCchar * ALC_APIENTRY alcGetString( ALCdevice *device, ALCenum param ) OPENAL_DEPRECATED;
ALC_API void ALC_APIENTRY alcGetIntegerv( ALCdevice *device, ALCenum param, ALCsizei size, ALCint *data );
ALC_API void ALC_APIENTRY alcGetIntegerv( ALCdevice *device, ALCenum param, ALCsizei size, ALCint *data ) OPENAL_DEPRECATED;
/*
* Capture functions
*/
ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize );
ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize ) OPENAL_DEPRECATED;
ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice( ALCdevice *device );
ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice( ALCdevice *device ) OPENAL_DEPRECATED;
ALC_API void ALC_APIENTRY alcCaptureStart( ALCdevice *device );
ALC_API void ALC_APIENTRY alcCaptureStart( ALCdevice *device ) OPENAL_DEPRECATED;
ALC_API void ALC_APIENTRY alcCaptureStop( ALCdevice *device );
ALC_API void ALC_APIENTRY alcCaptureStop( ALCdevice *device ) OPENAL_DEPRECATED;
ALC_API void ALC_APIENTRY alcCaptureSamples( ALCdevice *device, ALCvoid *buffer, ALCsizei samples );
ALC_API void ALC_APIENTRY alcCaptureSamples( ALCdevice *device, ALCvoid *buffer, ALCsizei samples ) OPENAL_DEPRECATED;
/*
* Pointer-to-function types, useful for dynamically getting ALC entry points.

View File

@ -36,11 +36,11 @@ extern "C" {
#endif
#endif
ALUTAPI ALvoid ALUTAPIENTRY alutInit(ALint *argc,ALbyte **argv);
ALUTAPI ALvoid ALUTAPIENTRY alutExit(ALvoid);
ALUTAPI ALvoid ALUTAPIENTRY alutLoadWAVFile(ALbyte *file,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq);
ALUTAPI ALvoid ALUTAPIENTRY alutLoadWAVMemory(ALbyte *memory,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq);
ALUTAPI ALvoid ALUTAPIENTRY alutUnloadWAV(ALenum format,ALvoid *data,ALsizei size,ALsizei freq);
ALUTAPI ALvoid ALUTAPIENTRY alutInit(ALint *argc,ALbyte **argv) OPENAL_DEPRECATED;
ALUTAPI ALvoid ALUTAPIENTRY alutExit(ALvoid) OPENAL_DEPRECATED;
ALUTAPI ALvoid ALUTAPIENTRY alutLoadWAVFile(ALbyte *file,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq) OPENAL_DEPRECATED;
ALUTAPI ALvoid ALUTAPIENTRY alutLoadWAVMemory(ALbyte *memory,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq) OPENAL_DEPRECATED;
ALUTAPI ALvoid ALUTAPIENTRY alutUnloadWAV(ALenum format,ALvoid *data,ALsizei size,ALsizei freq) OPENAL_DEPRECATED;
#ifdef TARGET_OS_MAC
#if TARGET_OS_MAC

View File

@ -21,6 +21,7 @@
*
**********************************************************************************************************************************/
#import <AudioToolbox/AudioComponent.h>
#include "OALCaptureDevice.h"
#define LOG_CAPTURE 0
@ -101,7 +102,7 @@ OALCaptureDevice::~OALCaptureDevice()
DebugMessageN1("OALCaptureDevice::~OALCaptureDevice() - OALCaptureDevice = %ld", (long int) mSelfToken);
#endif
if (mInputUnit)
CloseComponent(mInputUnit);
AudioComponentInstanceDispose(mInputUnit);
if (mBufferData)
free(mBufferData);
delete mRingBuffer;
@ -139,9 +140,9 @@ void OALCaptureDevice::InitializeAU(const char* inDeviceName)
DebugMessageN2("OALCaptureDevice::InitializeAU() - OALCaptureDevice = %ld:%s", (long int) mSelfToken, inDeviceName);
#endif
// open input unit
OSStatus result = noErr;
Component comp;
ComponentDescription desc;
OSStatus result = noErr;
AudioComponent comp;
AudioComponentDescription desc;
try {
desc.componentType = kAudioUnitType_Output;
@ -149,11 +150,11 @@ void OALCaptureDevice::InitializeAU(const char* inDeviceName)
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
comp = FindNextComponent(NULL, &desc);
comp = AudioComponentFindNext(NULL, &desc);
if (comp == NULL)
throw -1;
result = OpenAComponent(comp, &mInputUnit);
result = AudioComponentInstanceNew(comp, &mInputUnit);
THROW_RESULT
UInt32 enableIO;
@ -207,11 +208,11 @@ void OALCaptureDevice::InitializeAU(const char* inDeviceName)
}
catch (OSStatus result) {
if (mInputUnit) CloseComponent(mInputUnit);
if (mInputUnit) AudioComponentInstanceDispose(mInputUnit);
throw result;
}
catch (...) {
if (mInputUnit) CloseComponent(mInputUnit);
if (mInputUnit) AudioComponentInstanceDispose(mInputUnit);
throw - 1;
}
}
@ -403,4 +404,4 @@ UInt32 OALCaptureDevice::AvailableFrames()
DebugMessageN2("OALCaptureDevice::AvailableFrames - buffer: %ld actual: %ld", availableFrames, (UInt32)(availableFrames / mSampleRateRatio));
#endif
return availableFrames / mSampleRateRatio;
}
}

View File

@ -282,7 +282,7 @@ void OALContext::InitializeMixer(UInt32 inStereoBusCount)
mSettableMixerAttenuationCurves = true;
}
ComponentDescription mixerCD;
AudioComponentDescription mixerCD;
mixerCD.componentFlags = 0;
mixerCD.componentFlagsMask = 0;
mixerCD.componentType = kAudioUnitType_Mixer;
@ -290,10 +290,10 @@ void OALContext::InitializeMixer(UInt32 inStereoBusCount)
mixerCD.componentManufacturer = kAudioUnitManufacturer_Apple;
// CREATE NEW NODE FOR THE GRAPH
result = AUGraphNewNode (mOwningDevice->GetGraph(), &mixerCD, 0, NULL, &mMixerNode);
result = AUGraphAddNode(mOwningDevice->GetGraph(), &mixerCD, &mMixerNode);
THROW_RESULT
result = AUGraphGetNodeInfo (mOwningDevice->GetGraph(), mMixerNode, 0, 0, 0, &mMixerUnit);
result = AUGraphNodeInfo(mOwningDevice->GetGraph(), mMixerNode, &mixerCD, &mMixerUnit);
THROW_RESULT
// Get Default Distance Setting when the good 3DMixer is around

View File

@ -367,7 +367,7 @@ void OALDevice::InitializeGraph (const char* inDeviceName)
// ~~~~~~~~~~~~~~~~~~~~ SET UP OUTPUT NODE
ComponentDescription cd;
AudioComponentDescription cd;
cd.componentFlags = 0;
cd.componentFlagsMask = 0;
@ -375,7 +375,7 @@ void OALDevice::InitializeGraph (const char* inDeviceName)
cd.componentType = kAudioUnitType_Output;
cd.componentSubType = kAudioUnitSubType_DefaultOutput;
cd.componentManufacturer = kAudioUnitManufacturer_Apple;
result = AUGraphNewNode (mAUGraph, &cd, 0, NULL, &mOutputNode);
result = AUGraphAddNode(mAUGraph, &cd, &mOutputNode);
THROW_RESULT
// ~~~~~~~~~~~~~~~~~~~~ OPEN GRAPH
@ -383,7 +383,7 @@ void OALDevice::InitializeGraph (const char* inDeviceName)
result = AUGraphOpen (mAUGraph);
THROW_RESULT
result = AUGraphGetNodeInfo (mAUGraph, mOutputNode, 0, 0, 0, &mOutputUnit);
result = AUGraphNodeInfo (mAUGraph, mOutputNode, &cd, &mOutputUnit);
THROW_RESULT
result = AudioUnitInitialize (mOutputUnit);

View File

@ -176,18 +176,26 @@ UInt32 Get3DMixerVersion ()
if (mixerVersion == kUnknown3DMixerVersion)
{
ComponentDescription mixerCD;
mixerCD.componentFlags = 0;
mixerCD.componentFlagsMask = 0;
mixerCD.componentType = kAudioUnitType_Mixer;
mixerCD.componentSubType = kAudioUnitSubType_3DMixer;
mixerCD.componentManufacturer = kAudioUnitManufacturer_Apple;
ComponentInstance mixerInstance = OpenComponent(FindNextComponent(0, &mixerCD));
long version = CallComponentVersion(mixerInstance);
CloseComponent(mixerInstance);
if (version < kMinimumMixerVersion)
AudioComponentDescription mixerDesc;
UInt32 version = 0;
mixerDesc.componentType = kAudioUnitType_Mixer;
mixerDesc.componentSubType = kAudioUnitSubType_3DMixer;
mixerDesc.componentManufacturer = kAudioUnitManufacturer_Apple;
mixerDesc.componentFlags = 0;
mixerDesc.componentFlagsMask = 0;
AudioComponent auComp = AudioComponentFindNext(NULL, &mixerDesc);
if ( auComp )
{
if ( AudioComponentGetVersion(auComp, &version) != noErr )
version = 0;
}
if (version < kMinimumMixerVersion)
{
mixerVersion = kUnsupported3DMixer; // we do not have a current enough 3DMixer to use
}
@ -569,14 +577,14 @@ ALCint alcCheckUnitIsPresent(OSType componentSubType)
{
ALCint isPresent = kUnknownAUState;
ComponentDescription desc;
AudioComponentDescription desc;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
desc.componentType = kAudioUnitType_Effect;
desc.componentSubType = componentSubType;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
isPresent = (FindNextComponent(0, &desc) != 0) ? kAUIsPresent : kAUIsNotPresent;
isPresent = (AudioComponentFindNext(0, &desc) != 0) ? kAUIsPresent : kAUIsNotPresent;
return isPresent;
}

View File

@ -37,42 +37,42 @@ extern "C" {
#endif
// added for OSX Extension
ALC_API ALvoid alcMacOSXRenderingQuality (ALint value);
ALC_API ALvoid alMacOSXRenderChannelCount (ALint value);
ALC_API ALvoid alcMacOSXMixerMaxiumumBusses (ALint value);
ALC_API ALvoid alcMacOSXMixerOutputRate(ALdouble value);
ALC_API ALvoid alcMacOSXRenderingQuality (ALint value) OPENAL_DEPRECATED;
ALC_API ALvoid alMacOSXRenderChannelCount (ALint value) OPENAL_DEPRECATED;
ALC_API ALvoid alcMacOSXMixerMaxiumumBusses (ALint value) OPENAL_DEPRECATED;
ALC_API ALvoid alcMacOSXMixerOutputRate(ALdouble value) OPENAL_DEPRECATED;
ALC_API ALint alcMacOSXGetRenderingQuality ();
ALC_API ALint alMacOSXGetRenderChannelCount ();
ALC_API ALint alcMacOSXGetMixerMaxiumumBusses ();
ALC_API ALdouble alcMacOSXGetMixerOutputRate();
ALC_API ALint alcMacOSXGetRenderingQuality () OPENAL_DEPRECATED;
ALC_API ALint alMacOSXGetRenderChannelCount () OPENAL_DEPRECATED;
ALC_API ALint alcMacOSXGetMixerMaxiumumBusses () OPENAL_DEPRECATED;
ALC_API ALdouble alcMacOSXGetMixerOutputRate() OPENAL_DEPRECATED;
AL_API ALvoid AL_APIENTRY alSetInteger (ALenum pname, ALint value);
AL_API ALvoid AL_APIENTRY alSetDouble (ALenum pname, ALdouble value);
AL_API ALvoid AL_APIENTRY alSetInteger (ALenum pname, ALint value) OPENAL_DEPRECATED;
AL_API ALvoid AL_APIENTRY alSetDouble (ALenum pname, ALdouble value) OPENAL_DEPRECATED;
AL_API ALvoid AL_APIENTRY alBufferDataStatic (ALint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq);
AL_API ALvoid AL_APIENTRY alBufferDataStatic (ALint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq) OPENAL_DEPRECATED;
// source notifications
AL_API ALenum alSourceAddNotification (ALuint sid, ALuint notificationID, alSourceNotificationProc notifyProc, ALvoid* userData);
AL_API ALvoid alSourceRemoveNotification (ALuint sid, ALuint notificationID, alSourceNotificationProc notifyProc, ALvoid* userData);
AL_API ALenum alSourceAddNotification (ALuint sid, ALuint notificationID, alSourceNotificationProc notifyProc, ALvoid* userData) OPENAL_DEPRECATED;
AL_API ALvoid alSourceRemoveNotification (ALuint sid, ALuint notificationID, alSourceNotificationProc notifyProc, ALvoid* userData) OPENAL_DEPRECATED;
// source spatialization
AL_API ALvoid alSourceRenderingQuality (ALuint sid, ALint value);
AL_API ALint alSourceGetRenderingQuality (ALuint sid);
AL_API ALvoid alSourceRenderingQuality (ALuint sid, ALint value) OPENAL_DEPRECATED;
AL_API ALint alSourceGetRenderingQuality (ALuint sid) OPENAL_DEPRECATED;
// added for ASA (Apple Environmental Audio)
ALC_API ALenum alcASAGetSource(ALuint property, ALuint source, ALvoid *data, ALuint* dataSize);
ALC_API ALenum alcASASetSource(ALuint property, ALuint source, ALvoid *data, ALuint dataSize);
ALC_API ALenum alcASAGetListener(ALuint property, ALvoid *data, ALuint* dataSize);
ALC_API ALenum alcASASetListener(ALuint property, ALvoid *data, ALuint dataSize);
ALC_API ALenum alcASAGetSource(ALuint property, ALuint source, ALvoid *data, ALuint* dataSize) OPENAL_DEPRECATED;
ALC_API ALenum alcASASetSource(ALuint property, ALuint source, ALvoid *data, ALuint dataSize) OPENAL_DEPRECATED;
ALC_API ALenum alcASAGetListener(ALuint property, ALvoid *data, ALuint* dataSize) OPENAL_DEPRECATED;
ALC_API ALenum alcASASetListener(ALuint property, ALvoid *data, ALuint dataSize) OPENAL_DEPRECATED;
// 3DMixer output capturer
ALC_API ALvoid alcOutputCapturerPrepare( ALCuint frequency, ALCenum format, ALCsizei buffersize );
ALC_API ALvoid alcOutputCapturerStart();
ALC_API ALvoid alcOutputCapturerStop();
ALC_API ALint alcOutputCapturerAvailableSamples();
ALC_API ALvoid alcOutputCapturerSamples( ALCvoid *buffer, ALCsizei samples );
ALC_API ALvoid alcOutputCapturerPrepare( ALCuint frequency, ALCenum format, ALCsizei buffersize ) OPENAL_DEPRECATED;
ALC_API ALvoid alcOutputCapturerStart() OPENAL_DEPRECATED;
ALC_API ALvoid alcOutputCapturerStop() OPENAL_DEPRECATED;
ALC_API ALint alcOutputCapturerAvailableSamples() OPENAL_DEPRECATED;
ALC_API ALvoid alcOutputCapturerSamples( ALCvoid *buffer, ALCsizei samples ) OPENAL_DEPRECATED;
// Used internally but no longer available via a header file. Some OpenAL applications may have been built with a header
// that defined these constants so keep defining them.

View File

@ -603,7 +603,7 @@ ALUTAPI ALvoid ALUTAPIENTRY alutLoadWAVMemory(ALbyte *memory,ALenum *format,ALvo
memset(*data,0,ChunkHdr.Size+31);
}
else{
realloc(*data,ChunkHdr.Size + 31);
*data = realloc(*data,ChunkHdr.Size + 31);
memset(*data,0,ChunkHdr.Size+31);
}
if (*data)
@ -782,42 +782,3 @@ AL_API ALvoid AL_APIENTRY alExit(void)
#ifdef __cplusplus
}
#endif
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#pragma mark ***** OALRingBuffer *****
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// count the leading zeroes in a word
static __inline__ int CountLeadingZeroes(int arg) {
#if TARGET_CPU_X86 || TARGET_CPU_X86_64
__asm__ volatile(
"bsrl %0, %0\n\t"
"movl $63, %%ecx\n\t"
"cmove %%ecx, %0\n\t"
"xorl $31, %0"
: "=r" (arg)
: "0" (arg)
);
#elif TARGET_CPU_PPC || TARGET_CPU_PPC64
__asm__ volatile("cntlzw %0, %1" : "=r" (arg) : "r" (arg));
#else
#error "ERROR - assembly instructions for counting leading zeroes not present"
#endif
return arg;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// base 2 log of next power of two greater or equal to x
inline UInt32 Log2Ceil(UInt32 x)
{
return 32 - CountLeadingZeroes(x - 1);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// next power of two greater or equal to x
inline UInt32 NextPowerOfTwo(UInt32 x)
{
return 1L << Log2Ceil(x);
}

View File

@ -1635,7 +1635,7 @@ void OALSource::SetupRogerBeepAU()
DebugMessageN1("OALSource::SetupRogerBeepAU called - OALSource = %ld\n", (long int) mSelfToken);
#endif
ComponentDescription desc;
AudioComponentDescription desc;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
desc.componentType = kAudioUnitType_Effect;
@ -1643,10 +1643,10 @@ void OALSource::SetupRogerBeepAU()
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
// CREATE NEW NODE FOR THE GRAPH
OSStatus result = AUGraphNewNode (mOwningContext->GetGraph(), &desc, 0, NULL, &mRogerBeepNode);
OSStatus result = AUGraphAddNode(mOwningContext->GetGraph(), &desc, &mRogerBeepNode);
THROW_RESULT
result = AUGraphGetNodeInfo (mOwningContext->GetGraph(), mRogerBeepNode, 0, 0, 0, &mRogerBeepAU);
result = AUGraphNodeInfo (mOwningContext->GetGraph(), mRogerBeepNode, &desc, &mRogerBeepAU);
THROW_RESULT
}
@ -1655,7 +1655,7 @@ void OALSource::SetupDistortionAU()
#if LOG_VERBOSE
DebugMessageN1("OALSource::SetupDistortionAU called - OALSource = %ld\n", (long int) mSelfToken);
#endif
ComponentDescription desc;
AudioComponentDescription desc;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
desc.componentType = kAudioUnitType_Effect;
@ -1663,10 +1663,10 @@ void OALSource::SetupDistortionAU()
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
// CREATE NEW NODE FOR THE GRAPH
OSStatus result = AUGraphNewNode (mOwningContext->GetGraph(), &desc, 0, NULL, &mDistortionNode);
OSStatus result = AUGraphAddNode (mOwningContext->GetGraph(), &desc, &mDistortionNode);
THROW_RESULT
result = AUGraphGetNodeInfo (mOwningContext->GetGraph(), mDistortionNode, 0, 0, 0, &mDistortionAU);
result = AUGraphNodeInfo (mOwningContext->GetGraph(), mDistortionNode, &desc, &mDistortionAU);
THROW_RESULT
}
@ -1807,7 +1807,7 @@ void OALSource::Play()
if(!mASADistortionEnable)
{
// connect render proc to unit if distortion is not enabled
result = AUGraphGetNodeInfo (mOwningContext->GetGraph(), mRogerBeepNode, 0, 0, 0, &mRenderUnit);
result = AUGraphNodeInfo (mOwningContext->GetGraph(), mRogerBeepNode, NULL, &mRenderUnit);
THROW_RESULT;
}
}
@ -1824,7 +1824,7 @@ void OALSource::Play()
THROW_RESULT
// distortion unit will always be first if it exists
result = AUGraphGetNodeInfo (mOwningContext->GetGraph(), mDistortionNode, 0, 0, 0, &mRenderUnit);
result = AUGraphNodeInfo (mOwningContext->GetGraph(), mDistortionNode, NULL, &mRenderUnit);
THROW_RESULT
if(mASARogerBeepEnable)
@ -4746,4 +4746,4 @@ UInt32 BufferQueue::FrameOffsetToPacketOffset(UInt32 inFrameOffset)
// if non pcm formats are used return the packet that contains inFrameOffset, which may back up the
// requested frame - round backward not forward
}
}

View File

@ -1,189 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#include "CAAUMIDIMap.h"
#include <pthread.h>
struct AllMidiTransformers
{
MIDILinearTransformer linearTrans;
MIDILogTransformer logTrans;
MIDIExpTransformer expTrans;
MIDISqrtTransformer sqrtTrans;
MIDISquareTransformer squareTrans;
MIDICubeRtTransformer cubeRtTrans;
MIDICubeTransformer cubeTrans;
};
AllMidiTransformers* gAllMidiTransformers = NULL;
#if TARGET_OS_MAC
static pthread_once_t sOnce = PTHREAD_ONCE_INIT;
static void InitAllMidiTransformers()
{
gAllMidiTransformers = new AllMidiTransformers();
}
static void CheckInitAllMidiTransformers()
{
pthread_once(&sOnce, InitAllMidiTransformers);
}
#endif
MIDIValueTransformer * CAAUMIDIMap::GetTransformer (UInt32 inFlags)
{
#if TARGET_OS_MAC
if (gAllMidiTransformers == NULL)
CheckInitAllMidiTransformers();
#else
if (gAllMidiTransformers == NULL)
gAllMidiTransformers = new AllMidiTransformers();
#endif
if (AudioUnitDisplayTypeIsLogarithmic(inFlags))
return &gAllMidiTransformers->logTrans;
else if (AudioUnitDisplayTypeIsExponential(inFlags))
return &gAllMidiTransformers->expTrans;
else if (AudioUnitDisplayTypeIsSquareRoot(inFlags))
return &gAllMidiTransformers->sqrtTrans;
else if (AudioUnitDisplayTypeIsSquared(inFlags))
return &gAllMidiTransformers->squareTrans;
else if (AudioUnitDisplayTypeIsCubed(inFlags))
return &gAllMidiTransformers->cubeTrans;
else if (AudioUnitDisplayTypeIsCubeRoot(inFlags))
return &gAllMidiTransformers->cubeRtTrans;
else
return &gAllMidiTransformers->linearTrans;
}
// The CALLER of this method must ensure that the status byte's MIDI Command matches!!!
bool CAAUMIDIMap::MIDI_Matches (UInt8 inChannel, UInt8 inData1, UInt8 inData2, Float32 &outLinear) const
{
// see if the channels match first
SInt8 chan = Channel();
// channel matches (if chan is less than zero, "Any Channel" flag is set)
if (chan >= 0 && chan != inChannel)
return false;
// match the special cases first
if (IsKeyEvent()) {
// we're using this key event as an on/off type switch
if (IsBipolar()) {
if (IsKeyPressure()){
if (IsBipolar_OnValue()) {
if (inData2 > 63) {
outLinear = 1;
return true;
}
} else {
if (inData2 < 64) {
outLinear = 0;
return true;
}
}
return false;
}
else {
if (IsBipolar_OnValue()) {
if (inData1 > 63) {
outLinear = 1;
return true;
}
} else {
if (inData1 < 64) {
outLinear = 0;
return true;
}
}
return false;
}
}
if (IsAnyNote()) {
// not quite sure how to interpret this...
if (IsKeyPressure())
outLinear = inData2 / 127.0;
else
outLinear = inData1 / 127.0;
return true;
}
if (mData1 == inData1) {
if (IsKeyPressure())
outLinear = inData2 / 127.0;
else
outLinear = 1;
return true;
}
return false;
}
else if (IsControlChange()) {
// controller ID matches
if (mData1 == inData1) {
if (IsBipolar()) {
if (IsBipolar_OnValue()) {
if (inData2 > 63) {
outLinear = 1;
return true;
}
} else {
if (inData2 < 64) {
outLinear = 0;
return true;
}
}
return false;
}
//printf("this in midi matches %X with ", this);
outLinear = inData2 / 127.;
return true;
}
return false;
}
// this just matches on the patch change value itself...
if (IsPatchChange()) {
if (mData1 == inData1) {
outLinear = 1;
return true;
}
return false;
}
// finally, for the other two, just check the bi-polar matching conditions
// pitch bend and after touch
if (IsBipolar()) {
if (IsBipolar_OnValue()) {
if (inData1 > 63) {
outLinear = 1;
return true;
}
} else {
if (inData1 < 64) {
outLinear = 0;
return true;
}
}
return false;
}
if (IsPitchBend()) {
UInt16 value = (inData2 << 7) | inData1;
outLinear = value / 16383.;
}
else if (IsChannelPressure()) {
outLinear = inData1 / 127.0;
}
return true;
}
void CAAUMIDIMap::Print () const
{
printf ("CAAUMIDIMap:%p, (%u/%u), mParamID %d, IsValid:%c, Status:0x%X, mData1 %d, Flags:0x%X\n", this, (unsigned int)mScope, (unsigned int)mElement, (int)mParameterID, (IsValid() ? 'T' : 'F'), mStatus, mData1, (int)mFlags);
}

View File

@ -1,503 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#ifndef __CAAUMIDIMap_h_
#define __CAAUMIDIMap_h_
#include <AudioUnit/AudioUnitProperties.h>
#include <algorithm>
/*
enum {
kAUParameterMIDIMapping_AnyChannelFlag = (1L << 0),
// If this flag is set and mStatus is a MIDI channel message, then the MIDI channel number
// in the status byte is ignored; the mapping is from the specified MIDI message on ANY channel.
kAUParameterMIDIMapping_AnyNoteFlag = (1L << 1),
// If this flag is set and mStatus is a Note On, Note Off, or Polyphonic Pressure message,
// the message's note number is ignored; the mapping is from ANY note number.
kAUParameterMIDIMapping_SubRange = (1L << 2),
// set this flag if the midi control should map only to a sub-range of the parameter's value
// then specify that range in the mSubRangeMin and mSubRangeMax members
kAUParameterMIDIMapping_Toggle = (1L << 3),
// this is only useful for boolean typed parameters. When set, it means that the parameter's
// value should be toggled (if true, become false and vice versa) when the represented MIDI message
// is received
kAUParameterMIDIMapping_Bipolar = (1L << 4),
// this can be set to when mapping a MIDI Controller to indicate that the parameter (typically a boolean
// style parameter) will only have its value changed to either the on or off state of a MIDI controller message
// (0 < 64 is off, 64 < 127 is on) such as the sustain pedal. The seeting of the next flag
// (kAUParameterMIDIMapping_Bipolar_On) determine whether the parameter is mapped to the on or off
// state of the controller
kAUParameterMIDIMapping_Bipolar_On = (1L << 5)
// only a valid flag if kAUParameterMIDIMapping_Bipolar is set
};
// The reserved fields here are being used to reserve space (as well as align to 64 bit size) for future use
// When/If these fields are used, the names of the fields will be changed to reflect their functionality
// so, apps should NOT refer to these reserved fields directly by name
typedef struct AUParameterMIDIMapping
{
AudioUnitScope mScope;
AudioUnitElement mElement;
AudioUnitParameterID mParameterID;
UInt32 mFlags;
Float32 mSubRangeMin;
Float32 mSubRangeMax;
UInt8 mStatus;
UInt8 mData1;
UInt8 reserved1; // MUST be set to zero
UInt8 reserved2; // MUST be set to zero
UInt32 reserved3; // MUST be set to zero
} AUParameterMIDIMapping;
*/
/*
Parameter To MIDI Mapping Properties
These properties are used to:
Describe a current set of mappings between MIDI messages and Parameter value setting
Create a mapping between a parameter and a MIDI message through either:
- explicitly adding (or removing) the mapping
- telling the AU to hot-map the next MIDI message to a specified Parameter
The same MIDI Message can map to one or more parameters
One Parameter can be mapped from multiple MIDI messages
In general usage, these properties only apply to AU's that implement the MIDI API
AU Instruments (type=='aumu') and Music Effects (type == 'aumf')
These properties are used in the Global scope. The scope and element members of the structure describe
the scope and element of the parameter. In all usages, mScope, mElement and mParameterID must be
correctly specified.
* The AUParameterMIDIMapping Structure
Command mStatus mData1
Note Off 0x8n Note Num
Note On 0x9n Note Num
Key Pressure 0xAn Note Num
Control Change 0xBn ControllerID
Patch Change 0xCn Patch Num
Channel Pressure DxDn 0 (Unused)
Pitch Bend 0xEn 0 (Unused)
(where n is 0-0xF to correspond to MIDI channels 1-16)
Details:
In general MIDI Commands can be mapped to either a specific channel as specified in the mStatus bit.
If the kAUParameterMIDIMapping_AnyChannelFlag bit is set mStatus is a MIDI channel message, then the
MIDI channel number in the status byte is ignored; the mapping is from the specified MIDI message on ANY channel.
For note commands (note on, note off, key pressure), the MIDI message can trigger either with just a specific
note number, or any note number if the kAUParameterMIDIMapping_AnyNoteFlag bit is set. In these instances, the
note number is used as the trigger value (for instance, a note message could be used to set the
cut off frequency of a filter).
The Properties:
kAudioUnitProperty_AllParameterMIDIMappings array of AUParameterMIDIMapping (read/write)
This property is used to both retreive and set the current mapping state between (some/many/all of) its parameters
and MIDI messages. When set, it should replace any previous mapped settings the AU had.
If this property is implemented by a non-MIDI capable AU (such as an 'aufx' type), then the property is
read only, and recommends a suggested set of mappings for the host to perform. In this case, it is the
host's responsibility to map MIDI message to the AU parameters. As described previously, there are a set
of default mappings (see AudioToolbox/AUMIDIController.h) that the host can recommend to the user
in this circumstance.
This property's size will be very dynamic, depending on the number of mappings currently in affect, so the
caller should always get the size of the property first before retrieving it. The AU should return an error
if the caller doesn't provide enough space to return all of the current mappings.
kAudioUnitProperty_AddParameterMIDIMapping array of AUParameterMIDIMapping (write only)
This property is used to Add mappings to the existing set of mappings the AU possesses. It does NOT replace
any existing mappings.
kAudioUnitProperty_RemoveParameterMIDIMapping array of AUParameterMIDIMapping (write only)
This property is used to remove the specified mappings from the AU. If a mapping is specified that does not
currently exist in the AU, then it should just be ignored.
kAudioUnitProperty_HotMapParameterMIDIMapping AUParameterMIDIMapping (read/write)
This property is used in two ways, determined by the value supplied by the caller.
(1) If a mapping struct is provided, then that struct provides *all* of the information that the AU should
use to map the parameter, *except* for the MIDI message. The AU should then listen for the next MIDI message
and associate that MIDI message with the supplied AUParameter mapping. When this MIDI message is received and
the mapping made, the AU should also issue a notification on this property
(kAudioUnitProperty_HotMapParameterMIDIMapping) to indicate to the host that the mapping has been made. The host
can then retrieve the mapping that was made by getting the value of this property.
To avoid possible confusion, it is recommended that once the host has retrieved this mapping (if it is
presenting a UI to describe the mappings for example), that it then clears the mapping state as described next.
Thus, the only time this property will return a valid value is when the AU has made a mapping. If the AU's mapping
state has been cleared (or it has not been asked to make a mapping), then the AU should return
kAudioUnitErr_InvalidPropertyValue if the host tries to read this value.
(2) If the value passed in is NULL, then if the AU had a parameter that it was in the process of mapping, it
should disregard that (stop listening to the MIDI messages to create a mapping) and discard the partially
mapped struct. If the value is NULL and the AU is not in the process of mapping, the AU can ignore the request.
At all times, the _AllMappings property will completely describe the current known state of the AU's mappings
of MIDI messages to parameters.
*/
/*
When mapping, it is recommended that LSB controllers are in general not mapped (ie. the controller range of 32 < 64)
as many host parsers will map 14 bit control values. If you know (or can present an option) that the host deals with
7 bit controllers only, then these controller ID's can be mapped of course.
*/
struct MIDIValueTransformer {
virtual double tolinear(double) = 0;
virtual double fromlinear(double) = 0;
#if DEBUG
// suppress warning
virtual ~MIDIValueTransformer() { }
#endif
};
struct MIDILinearTransformer : public MIDIValueTransformer {
virtual double tolinear(double x) { return x; }
virtual double fromlinear(double x) { return x; }
};
struct MIDILogTransformer : public MIDIValueTransformer {
virtual double tolinear(double x) { return log(std::max(x, .00001)); }
virtual double fromlinear(double x) { return exp(x); }
};
struct MIDIExpTransformer : public MIDIValueTransformer {
virtual double tolinear(double x) { return exp(x); }
virtual double fromlinear(double x) { return log(std::max(x, .00001)); }
};
struct MIDISqrtTransformer : public MIDIValueTransformer {
virtual double tolinear(double x) { return x < 0. ? -(sqrt(-x)) : sqrt(x); }
virtual double fromlinear(double x) { return x < 0. ? -(x * x) : x * x; }
};
struct MIDISquareTransformer : public MIDIValueTransformer {
virtual double tolinear(double x) { return x < 0. ? -(x * x) : x * x; }
virtual double fromlinear(double x) { return x < 0. ? -(sqrt(-x)) : sqrt(x); }
};
struct MIDICubeRtTransformer : public MIDIValueTransformer {
virtual double tolinear(double x) { return x < 0. ? -(pow(-x, 1./3.)) : pow(x, 1./3.); }
virtual double fromlinear(double x) { return x * x * x; }
};
struct MIDICubeTransformer : public MIDIValueTransformer {
virtual double tolinear(double x) { return x * x * x; }
virtual double fromlinear(double x) { return x < 0. ? -(pow(-x, 1./3.)) : pow(x, 1./3.); }
};
class CAAUMIDIMap : public AUParameterMIDIMapping {
public:
// variables for more efficient parsing of MIDI to Param value
Float32 mMinValue;
Float32 mMaxValue;
MIDIValueTransformer *mTransType;
// methods
static MIDIValueTransformer *GetTransformer (UInt32 inFlags);
CAAUMIDIMap() { memset(this, 0, sizeof(CAAUMIDIMap)); }
CAAUMIDIMap (const AUParameterMIDIMapping& inMap)
{
memset(this, 0, sizeof(CAAUMIDIMap));
memcpy (this, &inMap, sizeof(inMap));
}
CAAUMIDIMap (AudioUnitScope inScope, AudioUnitElement inElement, AudioUnitParameterID inParam)
{
memset(this, 0, sizeof(CAAUMIDIMap));
mScope = inScope;
mElement = inElement;
mParameterID = inParam;
}
bool IsValid () const { return mStatus != 0; }
// returns -1 if any channel bit is set
SInt32 Channel () const { return IsAnyChannel() ? -1 : (mStatus & 0xF); }
bool IsAnyChannel () const {
return mFlags & kAUParameterMIDIMapping_AnyChannelFlag;
}
// preserves the existing channel info in the status byte
// preserves any previously set mFlags value
void SetAnyChannel (bool inFlag)
{
if (inFlag)
mFlags |= kAUParameterMIDIMapping_AnyChannelFlag;
else
mFlags &= ~kAUParameterMIDIMapping_AnyChannelFlag;
}
bool IsAnyNote () const {
return (mFlags & kAUParameterMIDIMapping_AnyNoteFlag) != 0;
}
// preserves the existing key num in the mData1 byte
// preserves any previously set mFlags value
void SetAnyNote (bool inFlag)
{
if (inFlag)
mFlags |= kAUParameterMIDIMapping_AnyNoteFlag;
else
mFlags &= ~kAUParameterMIDIMapping_AnyNoteFlag;
}
bool IsToggle() const { return (mFlags & kAUParameterMIDIMapping_Toggle) != 0; }
void SetToggle (bool inFlag)
{
if (inFlag)
mFlags |= kAUParameterMIDIMapping_Toggle;
else
mFlags &= ~kAUParameterMIDIMapping_Toggle;
}
bool IsBipolar() const { return (mFlags & kAUParameterMIDIMapping_Bipolar) != 0; }
// inUseOnValue is valid ONLY if inFlag is true
void SetBipolar (bool inFlag, bool inUseOnValue = false)
{
if (inFlag) {
mFlags |= kAUParameterMIDIMapping_Bipolar;
if (inUseOnValue)
mFlags |= kAUParameterMIDIMapping_Bipolar_On;
else
mFlags &= ~kAUParameterMIDIMapping_Bipolar_On;
} else {
mFlags &= ~kAUParameterMIDIMapping_Bipolar;
mFlags &= ~kAUParameterMIDIMapping_Bipolar_On;
}
}
bool IsBipolar_OnValue () const { return (mFlags & kAUParameterMIDIMapping_Bipolar_On) != 0; }
bool IsSubRange () const { return (mFlags & kAUParameterMIDIMapping_SubRange) != 0; }
void SetSubRange (Float32 inStartValue, Float32 inStopValue)
{
mFlags |= kAUParameterMIDIMapping_SubRange;
mSubRangeMin = inStartValue;
mSubRangeMax = inStopValue;
}
void SetParamRange(Float32 minValue, Float32 maxValue)
{
mMinValue = minValue;
mMaxValue = maxValue;
}
// this will retain the subrange values previously set.
void SetSubRange (bool inFlag)
{
if (inFlag)
mFlags |= kAUParameterMIDIMapping_SubRange;
else
mFlags &= ~kAUParameterMIDIMapping_SubRange;
}
bool IsAnyValue() const{return !IsBipolar();}
bool IsOnValue() const{return IsBipolar_OnValue();}
bool IsOffValue() const{return IsBipolar();}
bool IsNoteOff () const { return ((mStatus & 0xF0) == 0x80); }
bool IsNoteOn () const { return ((mStatus & 0xF0) == 0x90); }
bool IsKeyPressure () const { return ((mStatus & 0xF0) == 0xA0); }
bool IsKeyEvent () const { return (mStatus > 0x7F) && (mStatus < 0xB0); }
bool IsPatchChange () const { return ((mStatus & 0xF0) == 0xC0); }
bool IsChannelPressure () const { return ((mStatus & 0xF0) == 0xD0); }
bool IsPitchBend () const { return ((mStatus & 0xF0) == 0xE0); }
bool IsControlChange () const { return ((mStatus & 0xF0) == 0xB0); }
void SetControllerOnValue(){SetBipolar(true,true);}
void SetControllerOffValue(){SetBipolar(true,false);}
void SetControllerAnyValue(){SetBipolar(false,false);}
// All of these Set calls will reset the mFlags field based on the
// anyChannel param value
void SetNoteOff (UInt8 key, SInt8 channel, bool anyChannel = false)
{
mStatus = 0x80 | (channel & 0xF);
mData1 = key;
mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
}
void SetNoteOn (UInt8 key, SInt8 channel, bool anyChannel = false)
{
mStatus = 0x90 | (channel & 0xF);
mData1 = key;
mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
}
void SetPolyKey (UInt8 key, SInt8 channel, bool anyChannel = false)
{
mStatus = 0xA0 | (channel & 0xF);
mData1 = key;
mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
}
void SetControlChange (UInt8 controllerID, SInt8 channel, bool anyChannel = false)
{
mStatus = 0xB0 | (channel & 0xF);
mData1 = controllerID;
mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
}
void SetPatchChange (UInt8 patchChange, SInt8 channel, bool anyChannel = false)
{
mStatus = 0xC0 | (channel & 0xF);
mData1 = patchChange;
mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
}
void SetChannelPressure (SInt8 channel, bool anyChannel = false)
{
mStatus = 0xD0 | (channel & 0xF);
mData1 = 0;
mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
}
void SetPitchBend (SInt8 channel, bool anyChannel = false)
{
mStatus = 0xE0 | (channel & 0xF);
mData1 = 0;
mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
}
Float32 ParamValueFromMIDILinear (Float32 inLinearValue) const
{
Float32 low, high;
if (IsSubRange()){
low = mSubRangeMin;
high = mSubRangeMax;
}
else {
low = mMinValue;
high = mMaxValue;
}
// WE ARE ASSUMING YOU HAVE SET THIS UP PROPERLY!!!!! (or this will crash cause it will be NULL)
return (Float32)mTransType->fromlinear((inLinearValue * (high - low)) + low);
}
// The CALLER of this method must ensure that the status byte's MIDI Command (ignoring the channel) matches!!!
bool MIDI_Matches (UInt8 inChannel, UInt8 inData1, UInt8 inData2, Float32 &outLinear) const;
void Print () const;
void Save (CFPropertyListRef &outData) const;
void Restore (CFDictionaryRef inData);
static void SaveAsMapPList (AudioUnit inUnit,
const AUParameterMIDIMapping * inMappings,
UInt32 inNumMappings,
CFPropertyListRef &outData,
CFStringRef inName = NULL);
// inNumMappings describes how much memory is allocated in outMappings
static void RestoreFromMapPList (const CFDictionaryRef inData,
AUParameterMIDIMapping * outMappings,
UInt32 inNumMappings);
static UInt32 NumberOfMaps (const CFDictionaryRef inData);
};
// these sorting operations sort for run-time efficiency based on the MIDI messages
inline bool operator== (const CAAUMIDIMap &a, const CAAUMIDIMap &b)
{
// ignore channel first
return (((a.mStatus & 0xF0) == (b.mStatus & 0xF0))
&& (a.mData1 == b.mData1)
&& ((a.mStatus & 0xF) == (b.mStatus & 0xf)) // now compare the channel
&& (a.mParameterID == b.mParameterID)
&& (a.mElement == b.mElement)
&& (a.mScope == b.mScope));
// reserved field comparisons - ignored until/if they are used
}
inline bool operator< (const CAAUMIDIMap &a, const CAAUMIDIMap &b)
{
if ((a.mStatus & 0xF0) != (b.mStatus & 0xF0))
return ((a.mStatus & 0xF0) < (b.mStatus & 0xF0));
if (a.mData1 != b.mData1)
return (a.mData1 < b.mData1);
if ((a.mStatus & 0xF) != (b.mStatus & 0xf)) // now compare the channel
return ((a.mStatus & 0xF) < (b.mStatus & 0xf));
// reserved field comparisons - ignored until/if they are used
// we're sorting this by MIDI, so we don't really care how the rest is sorted
return ((a.mParameterID < b.mParameterID)
&& (a.mElement < b.mElement)
&& (a.mScope < b.mScope));
}
class CompareMIDIMap {
int compare (const CAAUMIDIMap &a, const CAAUMIDIMap &b)
{
if ((a.mStatus & 0xF0) < (b.mStatus & 0xF0))
return -1;
if ((a.mStatus & 0xF0) > (b.mStatus & 0xF0))
return 1;
// note event
if (a.mStatus < 0xB0 || a.mStatus >= 0xD0)
return 0;
if (a.mData1 > b.mData1) return 1;
if (a.mData1 < b.mData1) return -1;
return 0;
}
public:
bool operator() (const CAAUMIDIMap &a, const CAAUMIDIMap &b) {
return compare (a, b) < 0;
}
bool Finish (const CAAUMIDIMap &a, const CAAUMIDIMap &b) {
return compare (a, b) != 0;
}
};
/*
usage: To find potential mapped events for a given status byte, where mMMapEvents is a sorted vec
CompareMIDIMap comparObj;
sortVecIter lower_iter = std::lower_bound(mMMapEvents.begin(), mMMapEvents.end(), inStatusByte, compareObj);
for (;lower_iter < mMMapEvents.end(); ++lower_iter) {
// then, see if we go out of the status byte range, using the Finish method
if (compareObj.Finish(map, tempMap)) // tempMap is a CAAUMIDIMap object with the status/dataByte 1 set
break;
// ...
}
in the for loop you call the MIDI_Matches call, to see if the MIDI event matches a given AUMIDIParam mapping
special note: you HAVE to transform note on (with vel zero) events to the note off status byte
*/
#endif

View File

@ -1,195 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#include "CAAUMIDIMapManager.h"
#include <AudioToolbox/AudioUnitUtilities.h>
CAAUMIDIMapManager::CAAUMIDIMapManager()
{
hotMapping = false;
}
static void FillInMap (CAAUMIDIMap &map, AUBase &That)
{
AudioUnitParameterInfo info;
That.GetParameterInfo (map.mScope, map.mParameterID, info);
if (map.IsSubRange()) {
map.mMinValue = map.mSubRangeMin;
map.mMaxValue = map.mSubRangeMax;
} else {
map.mMinValue = info.minValue;
map.mMaxValue = info.maxValue;
}
map.mTransType = CAAUMIDIMap::GetTransformer(info.flags);
}
OSStatus CAAUMIDIMapManager::SortedInsertToParamaterMaps (AUParameterMIDIMapping *maps, UInt32 inNumMaps, AUBase &That)
{
for (unsigned int i = 0; i < inNumMaps; ++i)
{
CAAUMIDIMap map(maps[i]);
FillInMap (map, That);
int idx = FindParameterIndex (maps[i]);
if (idx > -1)
mParameterMaps.erase(mParameterMaps.begin() + idx);
// least disruptive place to put this is at the end
mParameterMaps.push_back(map);
}
std::sort(mParameterMaps.begin(), mParameterMaps.end(), CompareMIDIMap());
return noErr;
}
void CAAUMIDIMapManager::GetHotParameterMap(AUParameterMIDIMapping &outMap )
{
outMap = mHotMap;
}
void CAAUMIDIMapManager::SortedRemoveFromParameterMaps(AUParameterMIDIMapping *maps, UInt32 inNumMaps, bool &outMapDidChange)
{
if (hotMapping) {
hotMapping = false;
}
outMapDidChange = false;
for (unsigned int i = 0; i < inNumMaps; ++i) {
int idx = FindParameterIndex (maps[i]);
if (idx > -1) {
//mParameterMaps[idx].Print();
mParameterMaps.erase(mParameterMaps.begin() + idx);
outMapDidChange = true;
}
}
}
void CAAUMIDIMapManager::ReplaceAllMaps (AUParameterMIDIMapping* inMappings, UInt32 inNumMaps, AUBase &That)
{
mParameterMaps.clear();
for (unsigned int i = 0; i < inNumMaps; ++i) {
CAAUMIDIMap mapping(inMappings[i]);
FillInMap (mapping, That);
mParameterMaps.push_back (mapping);
}
std::sort(mParameterMaps.begin(),mParameterMaps.end(), CompareMIDIMap());
}
bool CAAUMIDIMapManager::HandleHotMapping(UInt8 inStatus,
UInt8 inChannel,
UInt8 inData1,
AUBase &That)
{ //used to set the hot map info
if (inStatus == 0xf0) return false;
if (!hotMapping) return false;
hotMapping = false;
mHotMap.mStatus = inStatus | inChannel;
mHotMap.mData1 = inData1;
SortedInsertToParamaterMaps (&mHotMap, 1, That);
return true;
}
#if DEBUG
void CAAUMIDIMapManager::Print()
{
for ( ParameterMaps::iterator i = mParameterMaps.begin(); i < mParameterMaps.end(); ++i) {
CAAUMIDIMap* listmap = &(*i);
listmap->Print();
}
}
#endif // DEBUG
void CAAUMIDIMapManager::GetMaps(AUParameterMIDIMapping* maps)
{
int i = 0;
for ( ParameterMaps::iterator iter = mParameterMaps.begin(); iter < mParameterMaps.end(); ++iter, ++i) {
AUParameterMIDIMapping &listmap = (*iter);
maps[i] = listmap;
}
}
int CAAUMIDIMapManager::FindParameterIndex (AUParameterMIDIMapping &inMap)
{
//used to get back hot mapping and one at a time maps, for ui
int idx = 0;
for ( ParameterMaps::iterator i = mParameterMaps.begin(); i < mParameterMaps.end(); ++i) {
CAAUMIDIMap & listmap = (*i);
if ( (listmap.mParameterID == inMap.mParameterID) &&
(listmap.mScope == inMap.mScope) &&
(listmap.mElement == inMap.mElement) )
{
return idx;
}
idx++;
}
return -1;
}
bool CAAUMIDIMapManager::FindParameterMapEventMatch( UInt8 inStatus,
UInt8 inChannel,
UInt8 inData1,
UInt8 inData2,
UInt32 inBufferOffset,
AUBase& inAUBase)
{
bool ret_value = false;
if (inStatus == 0x90 && !inData2)
inStatus = 0x80 | inChannel;
//used to test for midi matches once map is made
CAAUMIDIMap tempMap;
tempMap.mStatus = inStatus | inChannel;
tempMap.mData1 = inData1;
CompareMIDIMap compareObj;
AudioUnitEvent event;
event.mEventType = kAudioUnitEvent_ParameterValueChange;
event.mArgument.mParameter.mAudioUnit = inAUBase.GetComponentInstance();
ParameterMaps::iterator lower_iter =
std::lower_bound(mParameterMaps.begin(), mParameterMaps.end(), tempMap, compareObj);
while (lower_iter < mParameterMaps.end())
{
CAAUMIDIMap & map = (*lower_iter);
if (compareObj.Finish(map, tempMap))
break;
Float32 value;
if (map.MIDI_Matches(inChannel, inData1, inData2, value))
{
inAUBase.SetParameter ( map.mParameterID, map.mScope, map.mElement,
map.ParamValueFromMIDILinear(value), inBufferOffset);
event.mArgument.mParameter.mParameterID = map.mParameterID;
event.mArgument.mParameter.mScope = map.mScope;
event.mArgument.mParameter.mElement = map.mElement;
AUEventListenerNotify(NULL, NULL, &event);
ret_value = true;
}
++lower_iter;
}
return ret_value;
}

View File

@ -1,64 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#ifndef __CAAUMIDIMapManager_h_
#define __CAAUMIDIMapManager_h_
#include "AUBase.h"
#include "CAAUMIDIMap.h"
#include <vector>
#include <AudioToolbox/AudioUnitUtilities.h>
class CAAUMIDIMapManager {
protected:
typedef std::vector<CAAUMIDIMap> ParameterMaps;
ParameterMaps mParameterMaps;
bool hotMapping;
AUParameterMIDIMapping mHotMap;
public:
CAAUMIDIMapManager();
UInt32 NumMaps(){return static_cast<UInt32>(mParameterMaps.size());}
void GetMaps(AUParameterMIDIMapping* maps);
int FindParameterIndex(AUParameterMIDIMapping &map);
void GetHotParameterMap(AUParameterMIDIMapping &outMap);
void SortedRemoveFromParameterMaps (AUParameterMIDIMapping *maps, UInt32 inNumMaps, bool &outMapDidChange);
OSStatus SortedInsertToParamaterMaps (AUParameterMIDIMapping *maps, UInt32 inNumMaps, AUBase &That);
void ReplaceAllMaps (AUParameterMIDIMapping* inMappings, UInt32 inNumMaps, AUBase &That);
bool IsHotMapping(){return hotMapping;}
void SetHotMapping (AUParameterMIDIMapping &inMap){hotMapping = true; mHotMap = inMap; }
bool HandleHotMapping( UInt8 inStatus,
UInt8 inChannel,
UInt8 inData1,
AUBase &That);
bool FindParameterMapEventMatch(UInt8 inStatus,
UInt8 inChannel,
UInt8 inData1,
UInt8 inData2,
UInt32 inBufferOffset,
AUBase& inAUBase);
#if DEBUG
void Print();
#endif
};
#endif

View File

@ -1,268 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
/*
This file implements all Atomic operations using Interlocked functions specified in
Winbase.h
NOTE: According to Microsoft documentation, all Interlocked functions generates a
full barrier.
On Windows:
As the Interlocked functions returns the Old value, Extra checks and operations
are made after the atomic operation to return value consistent with OSX counterparts.
*/
#ifndef __CAAtomic_h__
#define __CAAtomic_h__
#if TARGET_OS_WIN32
#include <windows.h>
#include <intrin.h>
#pragma intrinsic(_InterlockedOr)
#pragma intrinsic(_InterlockedAnd)
#else
#include <CoreFoundation/CFBase.h>
#include <libkern/OSAtomic.h>
#endif
inline void CAMemoryBarrier()
{
#if TARGET_OS_WIN32
MemoryBarrier();
#else
OSMemoryBarrier();
#endif
}
inline SInt32 CAAtomicAdd32Barrier(SInt32 theAmt, volatile SInt32* theValue)
{
#if TARGET_OS_WIN32
long lRetVal = InterlockedExchangeAdd((volatile long*)theValue, theAmt);
// InterlockedExchangeAdd returns the original value which differs from OSX version.
// At this point the addition would have occured and hence returning the new value
// to keep it sync with OSX.
return lRetVal + theAmt;
#else
return OSAtomicAdd32Barrier(theAmt, (volatile int32_t *)theValue);
#endif
}
inline SInt32 CAAtomicOr32Barrier(UInt32 theMask, volatile UInt32* theValue)
{
#if TARGET_OS_WIN32
// InterlockedAnd macro is not defined in x86 platform, and hence using the intrinsic
// function instead.
long j = _InterlockedOr((volatile long*)theValue, theMask);
// _InterlockedOr returns the original value which differs from OSX version.
// Returning the new value similar to OSX
return (SInt32)(j | theMask);
#else
return OSAtomicOr32Barrier(theMask, (volatile uint32_t *)theValue);
#endif
}
inline SInt32 CAAtomicAnd32Barrier(UInt32 theMask, volatile UInt32* theValue)
{
#if TARGET_OS_WIN32
// InterlockedAnd macro is not defined in x86 platform, and hence using the intrinsic
// function instead.
long j = _InterlockedAnd((volatile long*)theValue, theMask);
// _InterlockedAnd returns the original value which differs from OSX version.
// Returning the new value similar to OSX
return (SInt32)(j & theMask);
#else
return OSAtomicAnd32Barrier(theMask, (volatile uint32_t *)theValue);
#endif
}
inline bool CAAtomicCompareAndSwap32Barrier(SInt32 oldValue, SInt32 newValue, volatile SInt32 *theValue)
{
#if TARGET_OS_WIN32
// InterlockedCompareExchange returns the old value. But we need to return bool value.
long lRetVal = InterlockedCompareExchange((volatile long*)theValue, newValue, oldValue);
// Hence we check if the new value is set and if it is we return true else false.
// If theValue is equal to oldValue then the swap happens. Otherwise swap doesn't happen.
return (oldValue == lRetVal);
#else
return OSAtomicCompareAndSwap32Barrier(oldValue, newValue, (volatile int32_t *)theValue);
#endif
}
inline SInt32 CAAtomicIncrement32(volatile SInt32* theValue)
{
#if TARGET_OS_WIN32
return (SInt32)InterlockedIncrement((volatile long*)theValue);
#else
return OSAtomicIncrement32((volatile int32_t *)theValue);
#endif
}
inline SInt32 CAAtomicDecrement32(volatile SInt32* theValue)
{
#if TARGET_OS_WIN32
return (SInt32)InterlockedDecrement((volatile long*)theValue);
#else
return OSAtomicDecrement32((volatile int32_t *)theValue);
#endif
}
inline SInt32 CAAtomicIncrement32Barrier(volatile SInt32* theValue)
{
#if TARGET_OS_WIN32
return CAAtomicIncrement32(theValue);
#else
return OSAtomicIncrement32Barrier((volatile int32_t *)theValue);
#endif
}
inline SInt32 CAAtomicDecrement32Barrier(volatile SInt32* theValue)
{
#if TARGET_OS_WIN32
return CAAtomicDecrement32(theValue);
#else
return OSAtomicDecrement32Barrier((volatile int32_t *)theValue);
#endif
}
inline bool CAAtomicTestAndClearBarrier(int bitToClear, void* theAddress)
{
#if TARGET_OS_WIN32
BOOL bOldVal = InterlockedBitTestAndReset((long*)theAddress, bitToClear);
return (bOldVal ? true : false);
#else
return OSAtomicTestAndClearBarrier(bitToClear, (volatile void *)theAddress);
#endif
}
inline bool CAAtomicTestAndClear(int bitToClear, void* theAddress)
{
#if TARGET_OS_WIN32
BOOL bOldVal = CAAtomicTestAndClearBarrier(bitToClear, (long*)theAddress);
return (bOldVal ? true : false);
#else
return OSAtomicTestAndClear(bitToClear, (volatile void *)theAddress);
#endif
}
inline bool CAAtomicTestAndSetBarrier(int bitToSet, void* theAddress)
{
#if TARGET_OS_WIN32
BOOL bOldVal = InterlockedBitTestAndSet((long*)theAddress, bitToSet);
return (bOldVal ? true : false);
#else
return OSAtomicTestAndSetBarrier(bitToSet, (volatile void *)theAddress);
#endif
}
// int32_t flavors -- for C++ only since we can't overload in C
// CFBase.h defines SInt32 as signed int which is similar to int32_t. If CFBase.h is included, then
// this will generate redefinition error. But on Mac, CFBase.h, still includes MacTypes.h where
// SInt32 is defined as signed long so this would work there.
// So in order to fix the redefinition errors, we define these functions only if MacTypes.h is included.
#if defined(__cplusplus) && defined(__MACTYPES__) && !__LP64__
inline int32_t CAAtomicAdd32Barrier(int32_t theAmt, volatile int32_t* theValue)
{
return CAAtomicAdd32Barrier(theAmt, (volatile SInt32 *)theValue);
}
inline int32_t CAAtomicOr32Barrier(uint32_t theMask, volatile uint32_t* theValue)
{
return CAAtomicOr32Barrier(theMask, (volatile UInt32 *)theValue);
}
inline int32_t CAAtomicAnd32Barrier(uint32_t theMask, volatile uint32_t* theValue)
{
return CAAtomicAnd32Barrier(theMask, (volatile UInt32 *)theValue);
}
inline bool CAAtomicCompareAndSwap32Barrier(int32_t oldValue, int32_t newValue, volatile int32_t *theValue)
{
return CAAtomicCompareAndSwap32Barrier(oldValue, newValue, (volatile SInt32 *)theValue);
}
inline int32_t CAAtomicIncrement32(volatile int32_t* theValue)
{
return CAAtomicIncrement32((volatile SInt32 *)theValue);
}
inline int32_t CAAtomicDecrement32(volatile int32_t* theValue)
{
return CAAtomicDecrement32((volatile SInt32 *)theValue);
}
inline int32_t CAAtomicIncrement32Barrier(volatile int32_t* theValue)
{
return CAAtomicIncrement32Barrier((volatile SInt32 *)theValue);
}
inline int32_t CAAtomicDecrement32Barrier(volatile int32_t* theValue)
{
return CAAtomicDecrement32Barrier((volatile SInt32 *)theValue);
}
#endif // __cplusplus && !__LP64__
#if __LP64__
inline bool CAAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue )
{
return OSAtomicCompareAndSwap64Barrier(__oldValue, __newValue, __theValue);
}
#endif
inline bool CAAtomicCompareAndSwapPtrBarrier(void *__oldValue, void *__newValue, volatile void ** __theValue)
{
#if __LP64__
return CAAtomicCompareAndSwap64Barrier((int64_t)__oldValue, (int64_t)__newValue, (int64_t *)__theValue);
#else
return CAAtomicCompareAndSwap32Barrier((int32_t)__oldValue, (int32_t)__newValue, (int32_t *)__theValue);
#endif
}
/* Spinlocks. These use memory barriers as required to synchronize access to shared
* memory protected by the lock. The lock operation spins, but employs various strategies
* to back off if the lock is held, making it immune to most priority-inversion livelocks.
* The try operation immediately returns false if the lock was held, true if it took the
* lock. The convention is that unlocked is zero, locked is nonzero.
*/
#define CA_SPINLOCK_INIT 0
typedef int32_t CASpinLock;
bool CASpinLockTry( volatile CASpinLock *__lock );
void CASpinLockLock( volatile CASpinLock *__lock );
void CASpinLockUnlock( volatile CASpinLock *__lock );
inline void CASpinLockLock( volatile CASpinLock *__lock )
{
#if TARGET_OS_MAC
OSSpinLockLock(__lock);
#else
while (CAAtomicTestAndSetBarrier(0, (void*)__lock))
usleep(1000); // ???
#endif
}
inline void CASpinLockUnlock( volatile CASpinLock *__lock )
{
#if TARGET_OS_MAC
OSSpinLockUnlock(__lock);
#else
CAAtomicTestAndClearBarrier(0, (void*)__lock);
#endif
}
inline bool CASpinLockTry( volatile CASpinLock *__lock )
{
#if TARGET_OS_MAC
return OSSpinLockTry(__lock);
#else
return (CAAtomicTestAndSetBarrier(0, (void*)__lock) == 0);
#endif
}
#endif // __CAAtomic_h__

View File

@ -1,201 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#ifndef __CAAtomicStack_h__
#define __CAAtomicStack_h__
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <libkern/OSAtomic.h>
#else
#include <CAAtomic.h>
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
#include <CoreServices/CoreServices.h>
#endif
// linked list LIFO or FIFO (pop_all_reversed) stack, elements are pushed and popped atomically
// class T must implement T *& next().
template <class T>
class TAtomicStack {
public:
TAtomicStack() : mHead(NULL) { }
// non-atomic routines, for use when initializing/deinitializing, operate NON-atomically
void push_NA(T *item)
{
item->next() = mHead;
mHead = item;
}
T * pop_NA()
{
T *result = mHead;
if (result)
mHead = result->next();
return result;
}
bool empty() const { return mHead == NULL; }
T * head() { return mHead; }
// atomic routines
void push_atomic(T *item)
{
T *head_;
do {
head_ = mHead;
item->next() = head_;
} while (!compare_and_swap(head_, item, &mHead));
}
void push_multiple_atomic(T *item)
// pushes entire linked list headed by item
{
T *head_, *p = item, *tail;
// find the last one -- when done, it will be linked to head
do {
tail = p;
p = p->next();
} while (p);
do {
head_ = mHead;
tail->next() = head_;
} while (!compare_and_swap(head_, item, &mHead));
}
T * pop_atomic_single_reader()
// this may only be used when only one thread may potentially pop from the stack.
// if multiple threads may pop, this suffers from the ABA problem.
// <rdar://problem/4606346> TAtomicStack suffers from the ABA problem
{
T *result;
do {
if ((result = mHead) == NULL)
break;
} while (!compare_and_swap(result, result->next(), &mHead));
return result;
}
T * pop_atomic()
// This is inefficient for large linked lists.
// prefer pop_all() to a series of calls to pop_atomic.
// push_multiple_atomic has to traverse the entire list.
{
T *result = pop_all();
if (result) {
T *next = result->next();
if (next)
// push all the remaining items back onto the stack
push_multiple_atomic(next);
}
return result;
}
T * pop_all()
{
T *result;
do {
if ((result = mHead) == NULL)
break;
} while (!compare_and_swap(result, NULL, &mHead));
return result;
}
T* pop_all_reversed()
{
TAtomicStack<T> reversed;
T *p = pop_all(), *next;
while (p != NULL) {
next = p->next();
reversed.push_NA(p);
p = next;
}
return reversed.mHead;
}
static bool compare_and_swap(T *oldvalue, T *newvalue, T **pvalue)
{
#if TARGET_OS_MAC
#if __LP64__
return ::OSAtomicCompareAndSwap64Barrier(int64_t(oldvalue), int64_t(newvalue), (int64_t *)pvalue);
#elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
return ::OSAtomicCompareAndSwap32Barrier(int32_t(oldvalue), int32_t(newvalue), (int32_t *)pvalue);
#else
return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue);
#endif
#else
//return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue);
return CAAtomicCompareAndSwap32Barrier(SInt32(oldvalue), SInt32(newvalue), (SInt32*)pvalue);
#endif
}
protected:
T * mHead;
};
#if ((MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) && !TARGET_OS_WIN32)
#include <libkern/OSAtomic.h>
class CAAtomicStack {
public:
CAAtomicStack(size_t nextPtrOffset) : mNextPtrOffset(nextPtrOffset) {
/*OSQueueHead h = OS_ATOMIC_QUEUE_INIT; mHead = h;*/
mHead.opaque1 = 0; mHead.opaque2 = 0;
}
// a subset of the above
void push_atomic(void *p) { OSAtomicEnqueue(&mHead, p, mNextPtrOffset); }
void push_NA(void *p) { push_atomic(p); }
void * pop_atomic() { return OSAtomicDequeue(&mHead, mNextPtrOffset); }
void * pop_atomic_single_reader() { return pop_atomic(); }
void * pop_NA() { return pop_atomic(); }
private:
OSQueueHead mHead;
size_t mNextPtrOffset;
};
// a more efficient subset of TAtomicStack using OSQueue.
template <class T>
class TAtomicStack2 {
public:
TAtomicStack2() {
/*OSQueueHead h = OS_ATOMIC_QUEUE_INIT; mHead = h;*/
mHead.opaque1 = 0; mHead.opaque2 = 0;
mNextPtrOffset = -1;
}
void push_atomic(T *item) {
if (mNextPtrOffset < 0) {
T **pnext = &item->next(); // hack around offsetof not working with C++
mNextPtrOffset = (Byte *)pnext - (Byte *)item;
}
OSAtomicEnqueue(&mHead, item, mNextPtrOffset);
}
void push_NA(T *item) { push_atomic(item); }
T * pop_atomic() { return (T *)OSAtomicDequeue(&mHead, mNextPtrOffset); }
T * pop_atomic_single_reader() { return pop_atomic(); }
T * pop_NA() { return pop_atomic(); }
// caution: do not try to implement pop_all_reversed here. the writer could add new elements
// while the reader is trying to pop old ones!
private:
OSQueueHead mHead;
ssize_t mNextPtrOffset;
};
#else
#define TAtomicStack2 TAtomicStack
#endif // MAC_OS_X_VERSION_MAX_ALLOWED && !TARGET_OS_WIN32
#endif // __CAAtomicStack_h__

View File

@ -1,115 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
//=============================================================================
// Includes
//=============================================================================
// Self Include
#include "CAAudioChannelLayout.h"
#include "CAAutoDisposer.h"
#include <stdlib.h>
#include <string.h>
//=============================================================================
// CAAudioChannelLayout
//=============================================================================
AudioChannelLayout* CAAudioChannelLayout::Create(UInt32 inNumberChannelDescriptions)
{
UInt32 theSize = CalculateByteSize(inNumberChannelDescriptions);
AudioChannelLayout* theAnswer = static_cast<AudioChannelLayout*>(CA_calloc(1, theSize));
if(theAnswer != NULL)
{
SetAllToUnknown(*theAnswer, inNumberChannelDescriptions);
}
return theAnswer;
}
void CAAudioChannelLayout::Destroy(AudioChannelLayout* inChannelLayout)
{
free(inChannelLayout);
}
void CAAudioChannelLayout::SetAllToUnknown(AudioChannelLayout& outChannelLayout, UInt32 inNumberChannelDescriptions)
{
outChannelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
outChannelLayout.mChannelBitmap = 0;
outChannelLayout.mNumberChannelDescriptions = inNumberChannelDescriptions;
for(UInt32 theChannelIndex = 0; theChannelIndex < inNumberChannelDescriptions; ++theChannelIndex)
{
outChannelLayout.mChannelDescriptions[theChannelIndex].mChannelLabel = kAudioChannelLabel_Unknown;
outChannelLayout.mChannelDescriptions[theChannelIndex].mChannelFlags = 0;
outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[0] = 0;
outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[1] = 0;
outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[2] = 0;
}
}
bool operator== (const AudioChannelLayout &x, const AudioChannelLayout &y)
{
// compare based on the number of channel descriptions present
// (this may be too strict a comparison if all you care about are matching layout tags)
UInt32 theSize1 = CAAudioChannelLayout::CalculateByteSize(x.mNumberChannelDescriptions);
UInt32 theSize2 = CAAudioChannelLayout::CalculateByteSize(y.mNumberChannelDescriptions);
if (theSize1 != theSize2)
return false;
return !memcmp (&x, &y, theSize1);
}
bool operator!= (const AudioChannelLayout &x, const AudioChannelLayout &y)
{
return !(x == y);
}
// counting the one bits in a word
inline UInt32 CountOnes(UInt32 x)
{
// secret magic algorithm for counting bits in a word.
UInt32 t;
x = x - ((x >> 1) & 0x55555555);
t = ((x >> 2) & 0x33333333);
x = (x & 0x33333333) + t;
x = (x + (x >> 4)) & 0x0F0F0F0F;
x = x + (x << 8);
x = x + (x << 16);
return x >> 24;
}
UInt32 CAAudioChannelLayout::NumberChannels (const AudioChannelLayout& inLayout)
{
if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions)
return inLayout.mNumberChannelDescriptions;
if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
return CountOnes (inLayout.mChannelBitmap);
return AudioChannelLayoutTag_GetNumberOfChannels(inLayout.mChannelLayoutTag);
}
void CAShowAudioChannelLayout (FILE* file, const AudioChannelLayout *layout)
{
if (layout == NULL)
{
fprintf (file, "\tNULL layout\n");
return;
}
fprintf (file, "\tTag=0x%X, ", (int)layout->mChannelLayoutTag);
if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
fprintf (file, "Using Bitmap:0x%X\n", (int)layout->mChannelBitmap);
else {
fprintf (file, "Num Chan Descs=%d\n", (int)layout->mNumberChannelDescriptions);
const AudioChannelDescription *desc = layout->mChannelDescriptions;
for (unsigned int i = 0; i < layout->mNumberChannelDescriptions; ++i, ++desc) {
fprintf (file, "\t\tLabel=%d, Flags=0x%X, ", (int)desc->mChannelLabel, (int)desc->mChannelFlags);
fprintf (file, "[az=%f,el=%f,dist=%f]\n", desc->mCoordinates[0], desc->mCoordinates[1], desc->mCoordinates[2]);
}
}
}

View File

@ -1,161 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#if !defined(__CAAudioChannelLayout_h__)
#define __CAAudioChannelLayout_h__
//=============================================================================
// Includes
//=============================================================================
// System Includes
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#include <CoreFoundation/CoreFoundation.h>
#else
#include <CoreAudioTypes.h>
#include <CoreFoundation.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CADebugMacros.h"
#include "CAAutoDisposer.h"
#if !HAL_Build
#include "CAReferenceCounted.h"
#endif
//=============================================================================
// CAAudioChannelLayout
//=============================================================================
bool operator== (const AudioChannelLayout &x, const AudioChannelLayout &y);
bool operator!= (const AudioChannelLayout &x, const AudioChannelLayout &y);
extern "C" void CAShowAudioChannelLayout (FILE* file, const AudioChannelLayout *layout);
class CAAudioChannelLayout
{
// static Construction/Destruction
public:
static AudioChannelLayout* Create(UInt32 inNumberChannelDescriptions);
static void Destroy(AudioChannelLayout* inChannelLayout);
static UInt32 CalculateByteSize(UInt32 inNumberChannelDescriptions) {
return SizeOf32(AudioChannelLayout) - SizeOf32(AudioChannelDescription) + (inNumberChannelDescriptions * SizeOf32(AudioChannelDescription));
}
static void SetAllToUnknown(AudioChannelLayout& outChannelLayout, UInt32 inNumberChannelDescriptions);
static UInt32 NumberChannels(const AudioChannelLayout& inLayout);
#if !HAL_Build
// object methods
public:
CAAudioChannelLayout ();
CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround);
// if inChooseSurround is false, then symmetrical speaker arrangements
// are chosen in place of surround layouts if there is a choice
// This call chooses layouts based on the expected defaults in
// AudioUnit usage
CAAudioChannelLayout (AudioChannelLayoutTag inTag);
CAAudioChannelLayout (const CAAudioChannelLayout &c);
CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout);
~CAAudioChannelLayout();
CAAudioChannelLayout& operator= (const AudioChannelLayout* inChannelLayout);
CAAudioChannelLayout& operator= (const CAAudioChannelLayout& c);
bool operator== (const CAAudioChannelLayout &c) const;
bool operator!= (const CAAudioChannelLayout &c) const;
void SetWithTag(AudioChannelLayoutTag inTag);
bool IsValid() const { return NumberChannels() > 0; }
UInt32 Size() const { return mLayout ? mLayout->Size() : 0; }
UInt32 NumberChannels() const { return mLayout ? mLayout->NumberChannels() : 0; }
AudioChannelLayoutTag Tag() const { return Layout().mChannelLayoutTag; }
const AudioChannelLayout& Layout() const { return mLayout->Layout(); }
operator const AudioChannelLayout *() const { return &Layout(); }
void Print () const { Print (stdout); }
void Print (FILE* file) const;
OSStatus Save (CFPropertyListRef *outData) const;
OSStatus Restore (CFPropertyListRef &inData);
private:
class RefCountedLayout : public CAReferenceCounted {
void * operator new(size_t /* size */, size_t aclSize)
{
return CA_malloc(sizeof(RefCountedLayout) - sizeof(AudioChannelLayout) + aclSize);
}
void operator delete(void *mem)
{
free(mem);
}
RefCountedLayout(UInt32 inDataSize) :
mByteSize(inDataSize)
{
memset(&mACL, 0, inDataSize);
}
public:
static RefCountedLayout *CreateWithNumberChannelDescriptions(unsigned nChannels) {
size_t size = CAAudioChannelLayout::CalculateByteSize(nChannels);
return new(size) RefCountedLayout((UInt32)size);
}
static RefCountedLayout *CreateWithLayout(const AudioChannelLayout *layout) {
size_t size = CAAudioChannelLayout::CalculateByteSize(layout->mNumberChannelDescriptions);
RefCountedLayout *acl = new(size) RefCountedLayout((UInt32)size);
memcpy(&acl->mACL, layout, size);
return acl;
}
static RefCountedLayout *CreateWithLayoutTag(AudioChannelLayoutTag layoutTag) {
RefCountedLayout *acl = CreateWithNumberChannelDescriptions(0);
acl->mACL.mChannelLayoutTag = layoutTag;
return acl;
}
const AudioChannelLayout & Layout() const { return mACL; }
UInt32 Size () const { return mByteSize; }
UInt32 NumberChannels() { return CAAudioChannelLayout::NumberChannels(Layout()); }
private:
const UInt32 mByteSize;
AudioChannelLayout mACL;
// * * * mACL is variable length and thus must be last * * *
// only the constructors can change the actual state of the layout
friend CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround);
friend OSStatus CAAudioChannelLayout::Restore (CFPropertyListRef &inData);
friend CAAudioChannelLayout& CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout);
friend void CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag);
AudioChannelLayout * GetLayout() { return &mACL; }
private:
// prohibited methods: private and unimplemented.
RefCountedLayout();
RefCountedLayout(const RefCountedLayout& c);
RefCountedLayout& operator=(const RefCountedLayout& c);
};
RefCountedLayout *mLayout;
#endif // HAL_Build
};
#endif

View File

@ -1,172 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#include "CAAudioChannelLayout.h"
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <AudioToolbox/AudioFormat.h>
#else
#include <AudioFormat.h>
#endif
CAAudioChannelLayout::CAAudioChannelLayout ()
{
mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(0);
}
//=============================================================================
// CAAudioChannelLayout::CAAudioChannelLayout
//=============================================================================
CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround)
{
// this chooses default layouts based on the number of channels...
AudioChannelLayoutTag tag;
switch (inNumberChannels)
{
default:
// here we have a "broken" layout, in the sense that we haven't any idea how to lay this out
mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(inNumberChannels);
SetAllToUnknown(*mLayout->GetLayout(), inNumberChannels);
return; // don't fall into the tag case
case 1:
tag = kAudioChannelLayoutTag_Mono;
break;
case 2:
tag = inChooseSurround ? kAudioChannelLayoutTag_Binaural : kAudioChannelLayoutTag_Stereo;
break;
case 4:
tag = inChooseSurround ? kAudioChannelLayoutTag_Ambisonic_B_Format : kAudioChannelLayoutTag_AudioUnit_4;
break;
case 5:
tag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_5_0 : kAudioChannelLayoutTag_AudioUnit_5;
break;
case 6:
tag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_6_0 : kAudioChannelLayoutTag_AudioUnit_6;
break;
case 7:
tag = kAudioChannelLayoutTag_AudioUnit_7_0;
break;
case 8:
tag = kAudioChannelLayoutTag_AudioUnit_8;
break;
}
mLayout = RefCountedLayout::CreateWithLayoutTag(tag);
}
//=============================================================================
// CAAudioChannelLayout::CAAudioChannelLayout
//=============================================================================
CAAudioChannelLayout::CAAudioChannelLayout (AudioChannelLayoutTag inLayoutTag)
: mLayout(NULL)
{
SetWithTag(inLayoutTag);
}
//=============================================================================
// CAAudioChannelLayout::CAAudioChannelLayout
//=============================================================================
CAAudioChannelLayout::CAAudioChannelLayout (const CAAudioChannelLayout &c)
: mLayout(NULL)
{
*this = c;
}
//=============================================================================
// CAAudioChannelLayout::AudioChannelLayout
//=============================================================================
CAAudioChannelLayout::CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout)
: mLayout(NULL)
{
*this = inChannelLayout;
}
//=============================================================================
// CAAudioChannelLayout::~CAAudioChannelLayout
//=============================================================================
CAAudioChannelLayout::~CAAudioChannelLayout ()
{
if (mLayout) {
mLayout->release();
mLayout = NULL;
}
}
//=============================================================================
// CAAudioChannelLayout::CAAudioChannelLayout
//=============================================================================
CAAudioChannelLayout& CAAudioChannelLayout::operator= (const CAAudioChannelLayout &c)
{
if (mLayout != c.mLayout) {
if (mLayout)
mLayout->release();
if ((mLayout = c.mLayout) != NULL)
mLayout->retain();
}
return *this;
}
CAAudioChannelLayout& CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout)
{
if (mLayout && &mLayout->Layout() == inChannelLayout)
return *this;
if (mLayout)
mLayout->release();
if (inChannelLayout == NULL)
{
mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(0);
}
else
{
mLayout = RefCountedLayout::CreateWithLayout(inChannelLayout);
}
return *this;
}
void CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag)
{
if (mLayout)
mLayout->release();
mLayout = RefCountedLayout::CreateWithLayoutTag(inTag);
}
//=============================================================================
// CAAudioChannelLayout::operator==
//=============================================================================
bool CAAudioChannelLayout::operator== (const CAAudioChannelLayout &c) const
{
if (mLayout == c.mLayout)
return true;
return Layout() == c.Layout();
}
//=============================================================================
// CAAudioChannelLayout::operator!=
//=============================================================================
bool CAAudioChannelLayout::operator!= (const CAAudioChannelLayout &c) const
{
if (mLayout == c.mLayout)
return false;
return !(Layout() == c.Layout());
}
//=============================================================================
// CAAudioChannelLayout::Print
//=============================================================================
void CAAudioChannelLayout::Print (FILE* file) const
{
CAShowAudioChannelLayout (file, &Layout());
}

View File

@ -1,470 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#if !defined(__CAPtr_h__)
#define __CAPtr_h__
#include <stdlib.h> // for malloc
#include <new> // for bad_alloc
#include <string.h> // for memset
inline void* CA_malloc(size_t size)
{
void* p = malloc(size);
if (!p && size) throw std::bad_alloc();
return p;
}
inline void* CA_realloc(void* old, size_t size)
{
#if TARGET_OS_WIN32
void* p = realloc(old, size);
#else
void* p = reallocf(old, size); // reallocf ensures the old pointer is freed if memory is full (p is NULL).
#endif
if (!p && size) throw std::bad_alloc();
return p;
}
#ifndef UINTPTR_MAX
#if __LP64__
#define UINTPTR_MAX 18446744073709551615ULL
#else
#define UINTPTR_MAX 4294967295U
#endif
#endif
inline void* CA_calloc(size_t n, size_t size)
{
// ensure that multiplication will not overflow
if (n && UINTPTR_MAX / n < size) throw std::bad_alloc();
size_t nsize = n*size;
void* p = malloc(nsize);
if (!p && nsize) throw std::bad_alloc();
memset(p, 0, nsize);
return p;
}
// helper class for automatic conversions
template <typename T>
struct CAPtrRef
{
T* ptr_;
explicit CAPtrRef(T* ptr) : ptr_(ptr) {}
};
template <typename T>
class CAAutoFree
{
private:
T* ptr_;
public:
CAAutoFree() : ptr_(0) {}
explicit CAAutoFree(T* ptr) : ptr_(ptr) {}
template<typename U>
CAAutoFree(CAAutoFree<U>& that) : ptr_(that.release()) {} // take ownership
// C++ std says: a template constructor is never a copy constructor
CAAutoFree(CAAutoFree<T>& that) : ptr_(that.release()) {} // take ownership
CAAutoFree(size_t n, bool clear = false)
// this becomes an ambiguous call if n == 0
: ptr_(0)
{
size_t maxItems = ~size_t(0) / sizeof(T);
if (n > maxItems)
throw std::bad_alloc();
ptr_ = static_cast<T*>(clear ? CA_calloc(n, sizeof(T)) : CA_malloc(n * sizeof(T)));
}
~CAAutoFree() { free(); }
void alloc(size_t numItems, bool clear = false)
{
size_t maxItems = ~size_t(0) / sizeof(T);
if (numItems > maxItems) throw std::bad_alloc();
free();
ptr_ = static_cast<T*>(clear ? CA_calloc(numItems, sizeof(T)) : CA_malloc(numItems * sizeof(T)));
}
void allocBytes(size_t numBytes, bool clear = false)
{
free();
ptr_ = static_cast<T*>(clear ? CA_calloc(1, numBytes) : CA_malloc(numBytes));
}
void reallocBytes(size_t numBytes)
{
ptr_ = static_cast<T*>(CA_realloc(ptr_, numBytes));
}
void reallocItems(size_t numItems)
{
size_t maxItems = ~size_t(0) / sizeof(T);
if (numItems > maxItems) throw std::bad_alloc();
ptr_ = static_cast<T*>(CA_realloc(ptr_, numItems * sizeof(T)));
}
template <typename U>
CAAutoFree& operator=(CAAutoFree<U>& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoFree& operator=(CAAutoFree& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoFree& operator=(T* ptr)
{
set(ptr);
return *this;
}
template <typename U>
CAAutoFree& operator=(U* ptr)
{
set(ptr);
return *this;
}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
T* operator()() const { return ptr_; }
T* get() const { return ptr_; }
operator T*() const { return ptr_; }
bool operator==(CAAutoFree const& that) const { return ptr_ == that.ptr_; }
bool operator!=(CAAutoFree const& that) const { return ptr_ != that.ptr_; }
bool operator==(T* ptr) const { return ptr_ == ptr; }
bool operator!=(T* ptr) const { return ptr_ != ptr; }
T* release()
{
// release ownership
T* result = ptr_;
ptr_ = 0;
return result;
}
void set(T* ptr)
{
if (ptr != ptr_)
{
::free(ptr_);
ptr_ = ptr;
}
}
void free()
{
set(0);
}
// automatic conversions to allow assignment from results of functions.
// hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
CAAutoFree(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }
CAAutoFree& operator=(CAPtrRef<T> ref)
{
set(ref.ptr_);
return *this;
}
template<typename U>
operator CAPtrRef<U>()
{ return CAPtrRef<U>(release()); }
template<typename U>
operator CAAutoFree<U>()
{ return CAAutoFree<U>(release()); }
};
template <typename T>
class CAAutoDelete
{
private:
T* ptr_;
public:
CAAutoDelete() : ptr_(0) {}
explicit CAAutoDelete(T* ptr) : ptr_(ptr) {}
template<typename U>
CAAutoDelete(CAAutoDelete<U>& that) : ptr_(that.release()) {} // take ownership
// C++ std says: a template constructor is never a copy constructor
CAAutoDelete(CAAutoDelete<T>& that) : ptr_(that.release()) {} // take ownership
~CAAutoDelete() { free(); }
template <typename U>
CAAutoDelete& operator=(CAAutoDelete<U>& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoDelete& operator=(CAAutoDelete& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoDelete& operator=(T* ptr)
{
set(ptr);
return *this;
}
template <typename U>
CAAutoDelete& operator=(U* ptr)
{
set(ptr);
return *this;
}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
T* operator()() const { return ptr_; }
T* get() const { return ptr_; }
operator T*() const { return ptr_; }
bool operator==(CAAutoDelete const& that) const { return ptr_ == that.ptr_; }
bool operator!=(CAAutoDelete const& that) const { return ptr_ != that.ptr_; }
bool operator==(T* ptr) const { return ptr_ == ptr; }
bool operator!=(T* ptr) const { return ptr_ != ptr; }
T* release()
{
// release ownership
T* result = ptr_;
ptr_ = 0;
return result;
}
void set(T* ptr)
{
if (ptr != ptr_)
{
delete ptr_;
ptr_ = ptr;
}
}
void free()
{
set(0);
}
// automatic conversions to allow assignment from results of functions.
// hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
CAAutoDelete(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }
CAAutoDelete& operator=(CAPtrRef<T> ref)
{
set(ref.ptr_);
return *this;
}
template<typename U>
operator CAPtrRef<U>()
{ return CAPtrRef<U>(release()); }
template<typename U>
operator CAAutoFree<U>()
{ return CAAutoFree<U>(release()); }
};
template <typename T>
class CAAutoArrayDelete
{
private:
T* ptr_;
public:
CAAutoArrayDelete() : ptr_(0) {}
explicit CAAutoArrayDelete(T* ptr) : ptr_(ptr) {}
template<typename U>
CAAutoArrayDelete(CAAutoArrayDelete<U>& that) : ptr_(that.release()) {} // take ownership
// C++ std says: a template constructor is never a copy constructor
CAAutoArrayDelete(CAAutoArrayDelete<T>& that) : ptr_(that.release()) {} // take ownership
// this becomes an ambiguous call if n == 0
CAAutoArrayDelete(size_t n) : ptr_(new T[n]) {}
~CAAutoArrayDelete() { free(); }
void alloc(size_t numItems)
{
free();
ptr_ = new T [numItems];
}
template <typename U>
CAAutoArrayDelete& operator=(CAAutoArrayDelete<U>& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoArrayDelete& operator=(CAAutoArrayDelete& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoArrayDelete& operator=(T* ptr)
{
set(ptr);
return *this;
}
template <typename U>
CAAutoArrayDelete& operator=(U* ptr)
{
set(ptr);
return *this;
}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
T* operator()() const { return ptr_; }
T* get() const { return ptr_; }
operator T*() const { return ptr_; }
bool operator==(CAAutoArrayDelete const& that) const { return ptr_ == that.ptr_; }
bool operator!=(CAAutoArrayDelete const& that) const { return ptr_ != that.ptr_; }
bool operator==(T* ptr) const { return ptr_ == ptr; }
bool operator!=(T* ptr) const { return ptr_ != ptr; }
T* release()
{
// release ownership
T* result = ptr_;
ptr_ = 0;
return result;
}
void set(T* ptr)
{
if (ptr != ptr_)
{
delete [] ptr_;
ptr_ = ptr;
}
}
void free()
{
set(0);
}
// automatic conversions to allow assignment from results of functions.
// hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
CAAutoArrayDelete(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }
CAAutoArrayDelete& operator=(CAPtrRef<T> ref)
{
set(ref.ptr_);
return *this;
}
template<typename U>
operator CAPtrRef<U>()
{ return CAPtrRef<U>(release()); }
template<typename U>
operator CAAutoArrayDelete<U>()
{ return CAAutoFree<U>(release()); }
};
// convenience function
template <typename T>
void free(CAAutoFree<T>& p)
{
p.free();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
#if 0
// example program showing ownership transfer
CAAutoFree<char> source()
{
// source allocates and returns ownership to the caller.
const char* str = "this is a test";
size_t size = strlen(str) + 1;
CAAutoFree<char> captr(size, false);
strlcpy(captr(), str, size);
printf("source %08X %08X '%s'\n", &captr, captr(), captr());
return captr;
}
void user(CAAutoFree<char> const& captr)
{
// passed by const reference. user can access the pointer but does not take ownership.
printf("user: %08X %08X '%s'\n", &captr, captr(), captr());
}
void sink(CAAutoFree<char> captr)
{
// passed by value. sink takes ownership and frees the pointer on return.
printf("sink: %08X %08X '%s'\n", &captr, captr(), captr());
}
int main (int argc, char * const argv[])
{
CAAutoFree<char> captr(source());
printf("main captr A %08X %08X\n", &captr, captr());
user(captr);
sink(captr);
printf("main captr B %08X %08X\n", &captr, captr());
return 0;
}
#endif
#endif

View File

@ -1,223 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#include "CABufferList.h"
#include "CAByteOrder.h"
void CABufferList::AllocateBuffers(UInt32 nBytes)
{
if (nBytes <= GetNumBytes()) return;
if (mABL.mNumberBuffers > 1)
// align successive buffers for Altivec and to take alternating
// cache line hits by spacing them by odd multiples of 16
nBytes = ((nBytes + 15) & ~15) | 16;
UInt32 memorySize = nBytes * mABL.mNumberBuffers;
Byte *newMemory = new Byte[memorySize], *p = newMemory;
memset(newMemory, 0, memorySize); // get page faults now, not later
AudioBuffer *buf = mABL.mBuffers;
for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
if (buf->mData != NULL && buf->mDataByteSize > 0)
// preserve existing buffer contents
memcpy(p, buf->mData, buf->mDataByteSize);
buf->mDataByteSize = nBytes;
buf->mData = p;
p += nBytes;
}
Byte *oldMemory = mBufferMemory;
mBufferMemory = newMemory;
mBufferCapacity = nBytes;
delete[] oldMemory;
}
void CABufferList::AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inSrcList, CABufferList *inSetPtrList)
{
if (mABL.mNumberBuffers != inSrcList->mABL.mNumberBuffers) return;
if (mABL.mNumberBuffers != inSetPtrList->mABL.mNumberBuffers) return;
if (nBytes <= GetNumBytes()) {
CopyAllFrom(inSrcList, inSetPtrList);
return;
}
inSetPtrList->VerifyNotTrashingOwnedBuffer();
UInt32 fromByteSize = inSrcList->GetNumBytes();
if (mABL.mNumberBuffers > 1)
// align successive buffers for Altivec and to take alternating
// cache line hits by spacing them by odd multiples of 16
nBytes = ((nBytes + 15) & ~15) | 16;
UInt32 memorySize = nBytes * mABL.mNumberBuffers;
Byte *newMemory = new Byte[memorySize], *p = newMemory;
memset(newMemory, 0, memorySize); // make buffer "hot"
AudioBuffer *buf = mABL.mBuffers;
AudioBuffer *ptrBuf = inSetPtrList->mABL.mBuffers;
AudioBuffer *srcBuf = inSrcList->mABL.mBuffers;
for (UInt32 i = mABL.mNumberBuffers; i--; ++buf, ++ptrBuf, ++srcBuf) {
if (srcBuf->mData != NULL && srcBuf->mDataByteSize > 0)
// preserve existing buffer contents
memmove(p, srcBuf->mData, srcBuf->mDataByteSize);
buf->mDataByteSize = nBytes;
buf->mData = p;
ptrBuf->mDataByteSize = srcBuf->mDataByteSize;
ptrBuf->mData = p;
p += nBytes;
}
Byte *oldMemory = mBufferMemory;
mBufferMemory = newMemory;
mBufferCapacity = nBytes;
if (inSrcList != inSetPtrList)
inSrcList->BytesConsumed(fromByteSize);
delete[] oldMemory;
}
void CABufferList::DeallocateBuffers()
{
AudioBuffer *buf = mABL.mBuffers;
for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
buf->mData = NULL;
buf->mDataByteSize = 0;
}
if (mBufferMemory != NULL) {
delete[] mBufferMemory;
mBufferMemory = NULL;
mBufferCapacity = 0;
}
}
static void show(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label, const char *fmtstr=NULL)
{
printf("%s %p (%d fr%s):\n", label ? label : "AudioBufferList", &abl, framesToPrint, fmtstr ? fmtstr : "");
const AudioBuffer *buf = abl.mBuffers;
for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++buf) {
printf(" [%2d] %5dbytes %dch @ %p", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData);
if (framesToPrint && buf->mData != NULL) {
printf(":");
Byte *p = (Byte *)buf->mData;
for (int j = framesToPrint * buf->mNumberChannels; --j >= 0; )
switch (wordSize) {
case 0: // native float
printf(" %6.3f", *(Float32 *)p);
p += sizeof(Float32);
break;
// positive: big endian
case 1:
case -1:
printf(" %02X", *p);
p += 1;
break;
case 2:
printf(" %04X", CFSwapInt16BigToHost(*(UInt16 *)p));
p += 2;
break;
case 3:
printf(" %06X", (p[0] << 16) | (p[1] << 8) | p[2]);
p += 3;
break;
case 4:
printf(" %08X", (unsigned int)CFSwapInt32BigToHost(*(UInt32 *)p));
p += 4;
break;
case 10:
printf(" %6.3f", CASwapFloat32BigToHost(*(Float32 *)p));
p += sizeof(Float32);
break;
case -2:
printf(" %04X", CFSwapInt16LittleToHost(*(UInt16 *)p));
p += 2;
break;
case -3:
printf(" %06X", (p[2] << 16) | (p[1] << 8) | p[0]);
p += 3;
break;
case -4:
printf(" %08X", (unsigned int)CFSwapInt32LittleToHost(*(UInt32 *)p));
p += 4;
break;
case -10:
printf(" %6.3f", CASwapFloat32LittleToHost(*(Float32 *)p));
p += sizeof(Float32);
break;
}
}
printf("\n");
}
}
void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, const AudioStreamBasicDescription &asbd, const char *label)
{
CAStreamBasicDescription fmt(asbd);
int wordSize = 1;
char fmtstr[80] = { 0 };
if (fmt.mFormatID == kAudioFormatLinearPCM) {
if (fmt.mFormatFlags & kLinearPCMFormatFlagIsFloat) {
if (fmt.mBitsPerChannel == 32) {
if (fmt.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) {
wordSize = 10;
strlcpy(fmtstr, ", BEF", sizeof(fmtstr));
} else {
wordSize = -10;
strlcpy(fmtstr, ", LEF", sizeof(fmtstr));
}
}
} else {
wordSize = fmt.SampleWordSize();
if (wordSize > 0) {
int fracbits = (asbd.mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
if (fracbits > 0)
snprintf(fmtstr, sizeof(fmtstr), ", %d.%d-bit", (int)asbd.mBitsPerChannel - fracbits, fracbits);
else
snprintf(fmtstr, sizeof(fmtstr), ", %d-bit", (int)asbd.mBitsPerChannel);
if (!(fmt.mFormatFlags & kLinearPCMFormatFlagIsBigEndian)) {
wordSize = -wordSize;
strlcat(fmtstr, " LEI", sizeof(fmtstr));
} else {
strlcat(fmtstr, " BEI", sizeof(fmtstr));
}
}
}
}
show(abl, framesToPrint, wordSize, label, fmtstr);
}
void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label)
{
show(abl, framesToPrint, wordSize, label);
}
extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize)
{
show(*abl, framesToPrint, wordSize, NULL);
}
#pragma mark- CrashIfClientProvidedBogusAudioBufferList Diagostic Function
// if the return result is odd, there was a null buffer.
/*
extern "C" int CrashIfClientProvidedBogusAudioBufferList(const AudioBufferList *abl, bool nullok)
{
const AudioBuffer *buf = abl->mBuffers, *bufend = buf + abl->mNumberBuffers;
int sum = 0; // defeat attempts by the compiler to optimize away the code that touches the buffers
int anyNull = 0;
for ( ; buf < bufend; ++buf) {
const int *p = (const int *)buf->mData;
if (p == NULL) {
anyNull = 1;
if (nullok) continue;
}
unsigned datasize = buf->mDataByteSize;
if (datasize >= sizeof(int)) {
sum += p[0];
sum += p[datasize / sizeof(int) - 1];
}
}
return anyNull | (sum & ~1);
}
*/

View File

@ -1,286 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#ifndef __CABufferList_h__
#define __CABufferList_h__
#include <stddef.h>
#include "CAStreamBasicDescription.h"
#include "CAXException.h"
void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, const AudioStreamBasicDescription &fmt, const char *label=NULL);
void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label=NULL);
extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize);
extern "C" int CrashIfClientProvidedBogusAudioBufferList(const AudioBufferList *abl, bool nullOK=false);
/* ____________________________________________________________________________
// CABufferList - variable length buffer list
This class is designed for use in non-simplistic cases. For AudioUnits, AUBufferList
is preferred.
CABufferList can be used in one of two ways:
- as mutable pointers into non-owned memory
- as an immutable array of buffers (owns its own memory).
All buffers are assumed to have the same format (number of channels, word size), so that
we can assume their mDataByteSizes are all the same.
____________________________________________________________________________ */
class CABufferList {
public:
void * operator new(size_t /*size*/, int nBuffers) {
return ::operator new(sizeof(CABufferList) + (nBuffers-1) * sizeof(AudioBuffer));
}
static CABufferList * New(const char *name, const CAStreamBasicDescription &format)
{
UInt32 numBuffers = format.NumberChannelStreams(), channelsPerBuffer = format.NumberInterleavedChannels();
return new(numBuffers) CABufferList(name, numBuffers, channelsPerBuffer);
}
static CABufferList * New(const CAStreamBasicDescription &format) { return New("", format); }
static CABufferList * New(UInt32 numBuffers, UInt32 channelsPerBuffer, const char *name="") {
return new(numBuffers) CABufferList(name, numBuffers, channelsPerBuffer);
}
protected:
CABufferList(const char *name, UInt32 numBuffers, UInt32 channelsPerBuffer) :
mName(name),
mBufferMemory(NULL),
mBufferCapacity(0)
{
//XAssert(numBuffers > 0 /*&& channelsPerBuffer > 0*/);
mABL.mNumberBuffers = numBuffers;
AudioBuffer *buf = mABL.mBuffers;
for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
buf->mNumberChannels = channelsPerBuffer;
buf->mDataByteSize = 0;
buf->mData = NULL;
}
}
public:
~CABufferList()
{
if (mBufferMemory)
delete[] mBufferMemory;
}
const char * Name() { return mName; }
const AudioBufferList & GetBufferList() const { return mABL; }
AudioBufferList & GetModifiableBufferList() { return _GetBufferList(); }
UInt32 GetNumberBuffers() const { return mABL.mNumberBuffers; }
UInt32 GetNumBytes() const
{
return mABL.mBuffers[0].mDataByteSize;
}
void SetBytes(UInt32 nBytes, void *data)
{
VerifyNotTrashingOwnedBuffer();
XAssert(mABL.mNumberBuffers == 1);
mABL.mBuffers[0].mDataByteSize = nBytes;
mABL.mBuffers[0].mData = data;
}
void CopyAllFrom(CABufferList *srcbl, CABufferList *ptrbl)
// copies bytes from srcbl
// make ptrbl reflect the length copied
// note that srcbl may be same as ptrbl!
{
// Note that this buffer *can* own memory and its pointers/lengths are not
// altered; only its buffer contents, which are copied from srcbl.
// The pointers/lengths in ptrbl are updated to reflect the addresses/lengths
// of the copied data, and srcbl's contents are consumed.
ptrbl->VerifyNotTrashingOwnedBuffer();
UInt32 nBytes = srcbl->GetNumBytes();
AudioBuffer *mybuf = mABL.mBuffers, *srcbuf = srcbl->mABL.mBuffers,
*ptrbuf = ptrbl->mABL.mBuffers;
for (UInt32 i = mABL.mNumberBuffers; i--; ++mybuf, ++srcbuf, ++ptrbuf) {
memmove(mybuf->mData, srcbuf->mData, srcbuf->mDataByteSize);
ptrbuf->mData = mybuf->mData;
ptrbuf->mDataByteSize = srcbuf->mDataByteSize;
}
if (srcbl != ptrbl)
srcbl->BytesConsumed(nBytes);
}
// copies data from another buffer list.
void CopyDataFrom(const AudioBufferList &other)
{
for (unsigned i = 0; i < other.mNumberBuffers; ++i) {
XAssert(mBufferCapacity == 0 || other.mBuffers[i].mDataByteSize <= mBufferCapacity);
memcpy(mABL.mBuffers[i].mData, other.mBuffers[i].mData,
mABL.mBuffers[i].mDataByteSize = other.mBuffers[i].mDataByteSize);
}
}
void AppendFrom(CABufferList *blp, UInt32 nBytes)
{
// this may mutate a buffer that owns memory.
AudioBuffer *mybuf = mABL.mBuffers, *srcbuf = blp->mABL.mBuffers;
for (UInt32 i = mABL.mNumberBuffers; i--; ++mybuf, ++srcbuf) {
XAssert(nBytes <= srcbuf->mDataByteSize);
XAssert(mBufferCapacity == 0 || mybuf->mDataByteSize + nBytes <= mBufferCapacity);
memcpy((Byte *)mybuf->mData + mybuf->mDataByteSize, srcbuf->mData, nBytes);
mybuf->mDataByteSize += nBytes;
}
blp->BytesConsumed(nBytes);
}
void PadWithZeroes(UInt32 desiredBufferSize)
// for cases where an algorithm (e.g. SRC) requires some
// padding to create silence following end-of-file
{
XAssert(mBufferCapacity == 0 || desiredBufferSize <= mBufferCapacity);
if (GetNumBytes() > desiredBufferSize) return;
AudioBuffer *buf = mABL.mBuffers;
for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
memset((Byte *)buf->mData + buf->mDataByteSize, 0, desiredBufferSize - buf->mDataByteSize);
buf->mDataByteSize = desiredBufferSize;
}
}
void SetToZeroes(UInt32 nBytes)
{
XAssert(mBufferCapacity == 0 || nBytes <= mBufferCapacity);
AudioBuffer *buf = mABL.mBuffers;
for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
memset((Byte *)buf->mData, 0, nBytes);
buf->mDataByteSize = nBytes;
}
}
void Reset()
{
DeallocateBuffers();
}
Boolean SameDataAs(const CABufferList* anotherBufferList)
{
// check to see if two buffer lists point to the same memory.
if (mABL.mNumberBuffers != anotherBufferList->mABL.mNumberBuffers) return false;
for (UInt32 i = 0; i < mABL.mNumberBuffers; ++i) {
if (mABL.mBuffers[i].mData != anotherBufferList->mABL.mBuffers[i].mData) return false;
}
return true;
}
void BytesConsumed(UInt32 nBytes)
// advance buffer pointers, decrease buffer sizes
{
VerifyNotTrashingOwnedBuffer();
AudioBuffer *buf = mABL.mBuffers;
for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
XAssert(nBytes <= buf->mDataByteSize);
buf->mData = (Byte *)buf->mData + nBytes;
buf->mDataByteSize -= nBytes;
}
}
void SetFrom(const AudioBufferList *abl)
{
VerifyNotTrashingOwnedBuffer();
memcpy(&_GetBufferList(), abl, (char *)&abl->mBuffers[abl->mNumberBuffers] - (char *)abl);
}
void SetFrom(const CABufferList *blp)
{
SetFrom(&blp->GetBufferList());
}
void SetFrom(const AudioBufferList *abl, UInt32 nBytes)
{
VerifyNotTrashingOwnedBuffer();
AudioBuffer *mybuf = mABL.mBuffers;
const AudioBuffer *srcbuf = abl->mBuffers;
for (UInt32 i = mABL.mNumberBuffers; i--; ++mybuf, ++srcbuf) {
mybuf->mNumberChannels = srcbuf->mNumberChannels;
mybuf->mDataByteSize = nBytes;
mybuf->mData = srcbuf->mData;
}
}
void SetFrom(const CABufferList *blp, UInt32 nBytes)
{
SetFrom(&blp->GetBufferList(), nBytes);
}
AudioBufferList * ToAudioBufferList(AudioBufferList *abl) const
{
memcpy(abl, &GetBufferList(), (char *)&abl->mBuffers[mABL.mNumberBuffers] - (char *)abl);
return abl;
}
void AllocateBuffers(UInt32 nBytes);
void AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inCopyFromList, CABufferList *inSetPtrList);
void DeallocateBuffers();
void UseExternalBuffer(Byte *ptr, UInt32 nBytes);
void AdvanceBufferPointers(UInt32 nBytes) // $$$ ReducingSize
// this is for bufferlists that function simply as
// an array of pointers into another bufferlist, being advanced,
// as in RenderOutput implementations
{
VerifyNotTrashingOwnedBuffer();
AudioBuffer *buf = mABL.mBuffers;
for (UInt32 i = mABL.mNumberBuffers; i--; ++buf) {
buf->mData = (Byte *)buf->mData + nBytes;
buf->mDataByteSize -= nBytes;
}
}
void SetNumBytes(UInt32 nBytes)
{
XAssert(mBufferCapacity == 0 || nBytes <= mBufferCapacity);
AudioBuffer *buf = mABL.mBuffers;
for (UInt32 i = mABL.mNumberBuffers; i--; ++buf)
buf->mDataByteSize = nBytes;
}
void Print(const char *label=NULL, int nframes=0, int wordSize=0) const
{
if (label == NULL)
label = mName;
printf("%s - ", label);
CAShowAudioBufferList(&GetBufferList(), nframes, wordSize);
if (mBufferMemory)
printf(" owned memory @ 0x%p:\n", mBufferMemory);
}
UInt32 GetCapacityBytes() const { return mBufferCapacity; }
template <typename T>
T* GetData(UInt32 inBuffer) {
return static_cast<T*>(mABL.mBuffers[inBuffer].mData);
}
protected:
AudioBufferList & _GetBufferList() { return mABL; } // use with care
// if we make this public, then we lose ability to call VerifyNotTrashingOwnedBuffer
void VerifyNotTrashingOwnedBuffer()
{
// This needs to be called from places where we are modifying the buffer pointers.
// It's an error to modify the buffer pointers or lengths if we own the buffer memory.
XAssert(mBufferMemory == NULL);
}
const char * mName; // for debugging
Byte * mBufferMemory;
UInt32 mBufferCapacity; // max mDataByteSize of each buffer
AudioBufferList mABL;
// don't add anything here
};
#endif // __CABufferList_h__

View File

@ -1,123 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#if !defined(__CAByteOrder_h__)
#define __CAByteOrder_h__
//=============================================================================
// Includes
//=============================================================================
// System Includes
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreFoundation/CoreFoundation.h>
#else
#include "CoreFoundation.h"
#endif
#if defined(__cplusplus)
extern "C" {
#endif
CF_INLINE Float32 CASwapFloat32 (Float32 arg) {
union {
Float32 f;
UInt32 i;
} flip;
flip.f = arg;
flip.i = CFSwapInt32 (flip.i);
return flip.f;
}
CF_INLINE Float64 CASwapFloat64 (Float64 arg) {
union {
Float64 f;
UInt64 i;
} flip;
flip.f = arg;
flip.i = CFSwapInt64 (flip.i);
return flip.f;
}
#pragma mark -Flippers
CF_INLINE Float32 CASwapFloat32BigToHost(Float32 arg) {
#if defined(__BIG_ENDIAN__)
return arg;
#else
return CASwapFloat32(arg);
#endif
}
CF_INLINE Float64 CASwapFloat64BigToHost(Float64 arg) {
#if defined(__BIG_ENDIAN__)
return arg;
#else
return CASwapFloat64(arg);
#endif
}
CF_INLINE Float32 CASwapFloat32HostToBig(Float32 arg) {
#if defined(__BIG_ENDIAN__)
return arg;
#else
return CASwapFloat32(arg);
#endif
}
CF_INLINE Float64 CASwapFloat64HostToBig(Float64 arg) {
#if defined(__BIG_ENDIAN__)
return arg;
#else
return CASwapFloat64(arg);
#endif
}
CF_INLINE Float32 CASwapFloat32LittleToHost(Float32 arg) {
#if defined(__LITTLE_ENDIAN__)
return arg;
#else
return CASwapFloat32(arg);
#endif
}
CF_INLINE Float64 CASwapFloat64LittleToHost(Float64 arg) {
#if defined(__LITTLE_ENDIAN__)
return arg;
#else
return CASwapFloat64(arg);
#endif
}
CF_INLINE Float32 CASwapFloat32HostToLittle(Float32 arg) {
#if defined(__LITTLE_ENDIAN__)
return arg;
#else
return CASwapFloat32(arg);
#endif
}
CF_INLINE Float64 CASwapFloat64HostToLittle(Float64 arg) {
#if defined(__LITTLE_ENDIAN__)
return arg;
#else
return CASwapFloat64(arg);
#endif
}
#if defined(__cplusplus)
}
#endif
#endif

View File

@ -1,52 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#include "CADebugMacros.h"
#include <stdio.h>
#include <stdarg.h>
#if TARGET_API_MAC_OSX
#include <syslog.h>
#endif
#if DEBUG
#include <stdio.h>
void DebugPrint(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
#endif // DEBUG
void LogError(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
#if DEBUG
vprintf(fmt, args);
#endif
#if TARGET_API_MAC_OSX
vsyslog(LOG_ERR, fmt, args);
#endif
va_end(args);
}
void LogWarning(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
#if DEBUG
vprintf(fmt, args);
#endif
#if TARGET_API_MAC_OSX
vsyslog(LOG_WARNING, fmt, args);
#endif
va_end(args);
}

View File

@ -1,433 +0,0 @@
/* Copyright © 2007 Apple Inc. All Rights Reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by
Apple Inc. ("Apple") in consideration of your agreement to the
following terms, and your use, installation, modification or
redistribution of this Apple software constitutes acceptance of these
terms. If you do not agree with these terms, please do not use,
install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc.
may be used to endorse or promote products derived from the Apple
Software without specific prior written permission from Apple. Except
as expressly stated in this notice, no other rights or licenses, express
or implied, are granted by Apple herein, including but not limited to
any patent rights that may be infringed by your derivative works or by
other works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/*=============================================================================
CADebugMacros.h
=============================================================================*/
#if !defined(__CADebugMacros_h__)
#define __CADebugMacros_h__
//=============================================================================
// Includes
//=============================================================================
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include "CoreAudioTypes.h"
#endif
//=============================================================================
// CADebugMacros
//=============================================================================
//#define CoreAudio_StopOnFailure 1
//#define CoreAudio_TimeStampMessages 1
//#define CoreAudio_ThreadStampMessages 1
//#define CoreAudio_FlushDebugMessages 1
#if TARGET_RT_BIG_ENDIAN
#define CA4CCToCString(the4CC) { ((char*)&the4CC)[0], ((char*)&the4CC)[1], ((char*)&the4CC)[2], ((char*)&the4CC)[3], 0 }
#define CACopy4CCToCString(theCString, the4CC) { theCString[0] = ((char*)&the4CC)[0]; theCString[1] = ((char*)&the4CC)[1]; theCString[2] = ((char*)&the4CC)[2]; theCString[3] = ((char*)&the4CC)[3]; theCString[4] = 0; }
#else
#define CA4CCToCString(the4CC) { ((char*)&the4CC)[3], ((char*)&the4CC)[2], ((char*)&the4CC)[1], ((char*)&the4CC)[0], 0 }
#define CACopy4CCToCString(theCString, the4CC) { theCString[0] = ((char*)&the4CC)[3]; theCString[1] = ((char*)&the4CC)[2]; theCString[2] = ((char*)&the4CC)[1]; theCString[3] = ((char*)&the4CC)[0]; theCString[4] = 0; }
#endif
#pragma mark Basic Definitions
#if DEBUG || CoreAudio_Debug
// can be used to break into debugger immediately, also see CADebugger
#define BusError() (*(long *)0 = 0)
// basic debugging print routines
#if TARGET_OS_MAC && !TARGET_API_MAC_CARBON
extern pascal void DebugStr(const unsigned char* debuggerMsg);
#define DebugMessage(msg) DebugStr("\p"msg)
#define DebugMessageN1(msg, N1)
#define DebugMessageN2(msg, N1, N2)
#define DebugMessageN3(msg, N1, N2, N3)
#else
#include "CADebugPrintf.h"
#if (CoreAudio_FlushDebugMessages && !CoreAudio_UseSysLog) || defined(CoreAudio_UseSideFile)
#define FlushRtn ;fflush(DebugPrintfFile)
#else
#define FlushRtn
#endif
#if CoreAudio_ThreadStampMessages
#include <pthread.h>
#include "CAHostTimeBase.h"
#define DebugMessage(msg) DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: %s"DebugPrintfLineEnding, pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), msg) FlushRtn
#define DebugMessageN1(msg, N1) DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1) FlushRtn
#define DebugMessageN2(msg, N1, N2) DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2) FlushRtn
#define DebugMessageN3(msg, N1, N2, N3) DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3) FlushRtn
#define DebugMessageN4(msg, N1, N2, N3, N4) DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4) FlushRtn
#define DebugMessageN5(msg, N1, N2, N3, N4, N5) DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5) FlushRtn
#define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6) FlushRtn
#define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7) FlushRtn
#define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8) FlushRtn
#define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: "msg"\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8, N9) FlushRtn
#elif CoreAudio_TimeStampMessages
#include "CAHostTimeBase.h"
#define DebugMessage(msg) DebugPrintfRtn(DebugPrintfFileComma "%.4f: %s"DebugPrintfLineEnding, pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), msg) FlushRtn
#define DebugMessageN1(msg, N1) DebugPrintfRtn(DebugPrintfFileComma "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1) FlushRtn
#define DebugMessageN2(msg, N1, N2) DebugPrintfRtn(DebugPrintfFileComma "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2) FlushRtn
#define DebugMessageN3(msg, N1, N2, N3) DebugPrintfRtn(DebugPrintfFileComma "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3) FlushRtn
#define DebugMessageN4(msg, N1, N2, N3, N4) DebugPrintfRtn(DebugPrintfFileComma "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4) FlushRtn
#define DebugMessageN5(msg, N1, N2, N3, N4, N5) DebugPrintfRtn(DebugPrintfFileComma "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5) FlushRtn
#define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) DebugPrintfRtn(DebugPrintfFileComma "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6) FlushRtn
#define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) DebugPrintfRtn(DebugPrintfFileComma "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7) FlushRtn
#define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) DebugPrintfRtn(DebugPrintfFileComma "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8) FlushRtn
#define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugPrintfRtn(DebugPrintfFileComma "%.4f: "msg DebugPrintfLineEnding, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), N1, N2, N3, N4, N5, N6, N7, N8, N9) FlushRtn
#else
#define DebugMessage(msg) DebugPrintfRtn(DebugPrintfFileComma "%s"DebugPrintfLineEnding, msg) FlushRtn
#define DebugMessageN1(msg, N1) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1) FlushRtn
#define DebugMessageN2(msg, N1, N2) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2) FlushRtn
#define DebugMessageN3(msg, N1, N2, N3) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2, N3) FlushRtn
#define DebugMessageN4(msg, N1, N2, N3, N4) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2, N3, N4) FlushRtn
#define DebugMessageN5(msg, N1, N2, N3, N4, N5) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2, N3, N4, N5) FlushRtn
#define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6) FlushRtn
#define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6, N7) FlushRtn
#define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6, N7, N8) FlushRtn
#define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugPrintfRtn(DebugPrintfFileComma msg DebugPrintfLineEnding, N1, N2, N3, N4, N5, N6, N7, N8, N9) FlushRtn
#endif
#endif
void DebugPrint(const char *fmt, ...); // can be used like printf
#define DEBUGPRINT(msg) DebugPrint msg // have to double-parenthesize arglist (see Debugging.h)
#if VERBOSE
#define vprint(msg) DEBUGPRINT(msg)
#else
#define vprint(msg)
#endif
#if CoreAudio_StopOnFailure
#include "CADebugger.h"
#define STOP CADebuggerStop()
#else
#define STOP
#endif
#else
#define DebugMessage(msg)
#define DebugMessageN1(msg, N1)
#define DebugMessageN2(msg, N1, N2)
#define DebugMessageN3(msg, N1, N2, N3)
#define DebugMessageN4(msg, N1, N2, N3, N4)
#define DebugMessageN5(msg, N1, N2, N3, N4, N5)
#define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6)
#define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7)
#define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8)
#define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9)
#define DEBUGPRINT(msg)
#define vprint(msg)
#define STOP
#endif
void LogError(const char *fmt, ...); // writes to syslog (and stderr if debugging)
void LogWarning(const char *fmt, ...); // writes to syslog (and stderr if debugging)
#if DEBUG || CoreAudio_Debug
#pragma mark Debug Macros
#define Assert(inCondition, inMessage) \
if(!(inCondition)) \
{ \
DebugMessage(inMessage); \
STOP; \
}
#define AssertNoError(inError, inMessage) \
{ \
SInt32 __Err = (inError); \
if(__Err != 0) \
{ \
char __4CC[5] = CA4CCToCString(__Err); \
DebugMessageN2(inMessage ", Error: %d (%s)", (int)__Err, __4CC); \
STOP; \
} \
}
#define AssertNoKernelError(inError, inMessage) \
{ \
unsigned int __Err = (unsigned int)(inError); \
if(__Err != 0) \
{ \
DebugMessageN1(inMessage ", Error: 0x%X", __Err); \
STOP; \
} \
}
#define FailIf(inCondition, inHandler, inMessage) \
if(inCondition) \
{ \
DebugMessage(inMessage); \
STOP; \
goto inHandler; \
}
#define FailWithAction(inCondition, inAction, inHandler, inMessage) \
if(inCondition) \
{ \
DebugMessage(inMessage); \
STOP; \
{ inAction; } \
goto inHandler; \
}
#define FailIfNULL(inPointer, inAction, inHandler, inMessage) \
if((inPointer) == NULL) \
{ \
DebugMessage(inMessage); \
STOP; \
{ inAction; } \
goto inHandler; \
}
#define FailIfKernelError(inKernelError, inException, inMessage) \
{ \
kern_return_t __Err = (inKernelError); \
if(__Err != 0) \
{ \
DebugMessageN1(inMessage ", Error: 0x%X", __Err); \
STOP; \
{ inAction; } \
goto inHandler; \
} \
}
#define FailIfError(inError, inException, inMessage) \
{ \
SInt32 __Err = (inError); \
if(__Err != 0) \
{ \
char __4CC[5] = CA4CCToCString(__Err); \
DebugMessageN2(inMessage ", Error: %ld (%s)", __Err, __4CC); \
STOP; \
{ inAction; } \
goto inHandler; \
} \
}
#if defined(__cplusplus)
#define Throw(inException) STOP; throw (inException)
#define ThrowIf(inCondition, inException, inMessage) \
if(inCondition) \
{ \
DebugMessage(inMessage); \
Throw(inException); \
}
#define ThrowIfNULL(inPointer, inException, inMessage) \
if((inPointer) == NULL) \
{ \
DebugMessage(inMessage); \
Throw(inException); \
}
#define ThrowIfKernelError(inKernelError, inException, inMessage) \
{ \
kern_return_t __Err = (inKernelError); \
if(__Err != 0) \
{ \
DebugMessageN1(inMessage ", Error: 0x%X", __Err); \
Throw(inException); \
} \
}
#define ThrowIfError(inError, inException, inMessage) \
{ \
SInt32 __Err = (inError); \
if(__Err != 0) \
{ \
char __4CC[5] = CA4CCToCString(__Err); \
DebugMessageN2(inMessage ", Error: %d (%s)", (int)__Err, __4CC); \
Throw(inException); \
} \
}
#if TARGET_OS_WIN32
#define ThrowIfWinError(inError, inException, inMessage) \
{ \
HRESULT __Err = (inError); \
if(FAILED(__Err)) \
{ \
DebugMessageN2(inMessage ", Code: %d, Facility: 0x%X", HRESULT_CODE(__Err), HRESULT_FACILITY(__Err)); \
Throw(inException); \
} \
}
#endif
#define SubclassResponsibility(inMethodName, inException) \
{ \
DebugMessage(inMethodName": Subclasses must implement this method"); \
Throw(inException); \
}
#endif // defined(__cplusplus)
#else
#pragma mark Release Macros
#define Assert(inCondition, inMessage) \
if(!(inCondition)) \
{ \
STOP; \
}
#define AssertNoError(inError, inMessage) \
{ \
SInt32 __Err = (inError); \
if(__Err != 0) \
{ \
STOP; \
} \
}
#define AssertNoKernelError(inError, inMessage) \
{ \
unsigned int __Err = (unsigned int)(inError); \
if(__Err != 0) \
{ \
STOP; \
} \
}
#define FailIf(inCondition, inHandler, inMessage) \
if(inCondition) \
{ \
STOP; \
goto inHandler; \
}
#define FailWithAction(inCondition, inAction, inHandler, inMessage) \
if(inCondition) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
}
#define FailIfNULL(inPointer, inAction, inHandler, inMessage) \
if((inPointer) == NULL) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
}
#define FailIfKernelError(inKernelError, inException, inMessage) \
if((inKernelError) != 0) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
}
#define FailIfError(inError, inException, inMessage) \
if((inError) != 0) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
}
#if defined(__cplusplus)
#define Throw(inException) STOP; throw (inException)
#define ThrowIf(inCondition, inException, inMessage) \
if(inCondition) \
{ \
Throw(inException); \
}
#define ThrowIfNULL(inPointer, inException, inMessage) \
if((inPointer) == NULL) \
{ \
Throw(inException); \
}
#define ThrowIfKernelError(inKernelError, inException, inMessage) \
{ \
kern_return_t __Err = (inKernelError); \
if(__Err != 0) \
{ \
Throw(inException); \
} \
}
#define ThrowIfError(inError, inException, inMessage) \
{ \
SInt32 __Err = (inError); \
if(__Err != 0) \
{ \
Throw(inException); \
} \
}
#if TARGET_OS_WIN32
#define ThrowIfWinError(inError, inException, inMessage) \
{ \
HRESULT __Err = (inError); \
if(FAILED(__Err)) \
{ \
Throw(inException); \
} \
}
#endif
#define SubclassResponsibility(inMethodName, inException) \
{ \
Throw(inException); \
}
#endif // defined(__cplusplus)
#endif // DEBUG || CoreAudio_Debug
#endif

View File

@ -1,51 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
//==================================================================================================
// Includes
//==================================================================================================
// Self Include
#include "CADebugPrintf.h"
#if DEBUG || CoreAudio_Debug
#if TARGET_OS_WIN32
#include <stdarg.h>
#include <stdio.h>
#include <Windows.h>
extern "C"
int CAWin32DebugPrintf(char* inFormat, ...)
{
char theMessage[1024];
va_list theArguments;
va_start(theArguments, inFormat);
_vsnprintf(theMessage, 1024, inFormat, theArguments);
va_end(theArguments);
OutputDebugString(theMessage);
return 0;
}
#endif
#if defined(CoreAudio_UseSideFile)
#include <unistd.h>
FILE* sDebugPrintfSideFile = NULL;
extern "C"
void OpenDebugPrintfSideFile()
{
if(sDebugPrintfSideFile == NULL)
{
char theFileName[1024];
snprintf(theFileName, sizeof(theFileName), CoreAudio_UseSideFile, getpid());
sDebugPrintfSideFile = fopen(theFileName, "a+");
DebugPrintfRtn(DebugPrintfFileComma "\n------------------------------\n");
}
}
#endif
#endif

View File

@ -1,89 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#if !defined(__CADebugPrintf_h__)
#define __CADebugPrintf_h__
//=============================================================================
// Includes
//=============================================================================
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include "CoreAudioTypes.h"
#endif
//=============================================================================
// Macros to redirect debugging output to various logging services
//=============================================================================
//#define CoreAudio_UseSideFile "/CoreAudio-%d.txt"
#if DEBUG || CoreAudio_Debug
#if TARGET_OS_WIN32
#if defined(__cplusplus)
extern "C"
#endif
extern int CAWin32DebugPrintf(char* inFormat, ...);
#define DebugPrintfRtn CAWin32DebugPrintf
#define DebugPrintfFile
#define DebugPrintfLineEnding "\n"
#define DebugPrintfFileComma
#define DebugPrintf(inFormat, ...) CAWin32DebugPrintf(informat "\n", ## __VA_ARGS__)
#else
#if CoreAudio_UseSysLog
#include <sys/syslog.h>
#define DebugPrintfRtn syslog
#define DebugPrintfFile LOG_NOTICE
#define DebugPrintfLineEnding ""
#define DebugPrintfFileComma DebugPrintfFile,
#define DebugPrintf(inFormat, ...) DebugPrintfRtn(DebugPrintfFileComma inFormat DebugPrintfLineEnding, ## __VA_ARGS__)
#elif defined(CoreAudio_UseSideFile)
#include <stdio.h>
#if defined(__cplusplus)
extern "C"
#endif
void OpenDebugPrintfSideFile();
extern FILE* sDebugPrintfSideFile;
#define DebugPrintfRtn fprintf
#define DebugPrintfFile ((sDebugPrintfSideFile != NULL) ? sDebugPrintfSideFile : stderr)
#define DebugPrintfLineEnding "\n"
#define DebugPrintfFileComma DebugPrintfFile,
#define DebugPrintf(inFormat, ...) DebugPrintfRtn(DebugPrintfFileComma inFormat DebugPrintfLineEnding, ## __VA_ARGS__)
#elif CoreAudio_UseCALog
#include "CALog.h"
/* We cannot use 'LOG' for 'DebugPrintfRtn' because it is a concatenating macro itself. So we have to use syslog here. */
#include <sys/syslog.h>
#define DebugPrintfRtn syslog
#define DebugPrintfFile LOG_NOTICE
#define DebugPrintfLineEnding ""
#define DebugPrintfFileComma DebugPrintfFile,
/* Direct calls to 'DebugPrintf' use the new CALog system */
#define DebugPrintf(inFormat, ...) LOG(kLogPriority_Notice, 0, inFormat, ## __VA_ARGS__)
#else
#include <stdio.h>
#define DebugPrintfRtn fprintf
#define DebugPrintfFile stderr
#define DebugPrintfLineEnding "\n"
#define DebugPrintfFileComma DebugPrintfFile,
#define DebugPrintf(inFormat, ...) DebugPrintfRtn(DebugPrintfFileComma inFormat DebugPrintfLineEnding, ## __VA_ARGS__)
#endif
#endif
#else
#define DebugPrintfRtn
#define DebugPrintfFile
#define DebugPrintfLineEnding
#define DebugPrintfFileComma
#define DebugPrintf(inFormat, ...)
#endif
#endif

View File

@ -1,65 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
//=============================================================================
// Includes
//=============================================================================
#include "CADebugger.h"
//=============================================================================
// CADebugger
//=============================================================================
#if TARGET_API_MAC_OSX
#include <sys/sysctl.h>
#include <stdlib.h>
#include <unistd.h>
bool CAIsDebuggerAttached(void)
{
int mib[4];
struct kinfo_proc info;
size_t size;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = getpid();
size = sizeof(info);
info.kp_proc.p_flag = 0;
sysctl(mib, 4, &info, &size, NULL, 0);
return (info.kp_proc.p_flag & P_TRACED) == P_TRACED;
}
#endif
void CADebuggerStop(void)
{
#if CoreAudio_Debug
#if TARGET_API_MAC_OSX
if(CAIsDebuggerAttached())
{
#if defined(__i386__) || defined(__x86_64__)
asm("int3");
#else
__builtin_trap();
#endif
}
else
{
abort();
}
#else
__debugbreak();
#endif
#endif
}

View File

@ -1,31 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#if !defined(__CADebugger_h__)
#define __CADebugger_h__
//=============================================================================
// Includes
//=============================================================================
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include <CoreAudioTypes.h>
#endif
//=============================================================================
// CADebugger
//=============================================================================
#if TARGET_API_MAC_OSX
extern bool CAIsDebuggerAttached(void);
#endif
extern void CADebuggerStop(void);
#endif

View File

@ -1,45 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#if !defined(__CAException_h__)
#define __CAException_h__
//=============================================================================
// Includes
//=============================================================================
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include "CoreAudioTypes.h"
#endif
//=============================================================================
// CAException
//=============================================================================
class CAException
{
public:
CAException(OSStatus inError) : mError(inError) {}
CAException(const CAException& inException) : mError(inException.mError) {}
CAException& operator=(const CAException& inException) { mError = inException.mError; return *this; }
~CAException() {}
OSStatus GetError() const { return mError; }
protected:
OSStatus mError;
};
#define CATry try{
#define CACatch } catch(...) {}
#define CASwallowException(inExpression) try { inExpression; } catch(...) {}
#endif

View File

@ -1,305 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
//==================================================================================================
// Includes
//==================================================================================================
// Self Include
#include "CAGuard.h"
#if TARGET_OS_MAC
#include <errno.h>
#endif
// PublicUtility Inludes
#include "CADebugMacros.h"
#include "CAException.h"
#include "CAHostTimeBase.h"
//==================================================================================================
// Logging
//==================================================================================================
#if CoreAudio_Debug
// #define Log_Ownership 1
// #define Log_WaitOwnership 1
// #define Log_TimedWaits 1
// #define Log_Latency 1
// #define Log_Errors 1
#endif
//#warning Need a try-based Locker too
//==================================================================================================
// CAGuard
//==================================================================================================
CAGuard::CAGuard(const char* inName)
:
CAMutex(inName)
#if Log_Average_Latency
,mAverageLatencyAccumulator(0.0),
mAverageLatencyCount(0)
#endif
{
#if TARGET_OS_MAC
OSStatus theError = pthread_cond_init(&mCondVar, NULL);
ThrowIf(theError != 0, CAException(theError), "CAGuard::CAGuard: Could not init the cond var");
#elif TARGET_OS_WIN32
mEvent = CreateEvent(NULL, true, false, NULL);
ThrowIfNULL(mEvent, CAException(GetLastError()), "CAGuard::CAGuard: Could not create the event");
#endif
}
CAGuard::~CAGuard()
{
#if TARGET_OS_MAC
pthread_cond_destroy(&mCondVar);
#elif TARGET_OS_WIN32
if(mEvent != NULL)
{
CloseHandle(mEvent);
}
#endif
}
void CAGuard::Wait()
{
#if TARGET_OS_MAC
ThrowIf(!pthread_equal(pthread_self(), mOwner), CAException(1), "CAGuard::Wait: A thread has to have locked a guard before it can wait");
mOwner = 0;
#if Log_WaitOwnership
DebugPrintf("%p %.4f: CAGuard::Wait: thread %p is waiting on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
#endif
OSStatus theError = pthread_cond_wait(&mCondVar, &mMutex);
ThrowIf(theError != 0, CAException(theError), "CAGuard::Wait: Could not wait for a signal");
mOwner = pthread_self();
#if Log_WaitOwnership
DebugPrintf("%p %.4f: CAGuard::Wait: thread %p waited on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
#endif
#elif TARGET_OS_WIN32
ThrowIf(GetCurrentThreadId() != mOwner, CAException(1), "CAGuard::Wait: A thread has to have locked a guard before it can wait");
mOwner = 0;
#if Log_WaitOwnership
DebugPrintf("%lu %.4f: CAGuard::Wait: thread %lu is waiting on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
ReleaseMutex(mMutex);
HANDLE theHandles[] = { mMutex, mEvent };
OSStatus theError = WaitForMultipleObjects(2, theHandles, true, INFINITE);
ThrowIfError(theError, CAException(GetLastError()), "CAGuard::Wait: Could not wait for the signal");
mOwner = GetCurrentThreadId();
ResetEvent(mEvent);
#if Log_WaitOwnership
DebugPrintf("%lu %.4f: CAGuard::Wait: thread %lu waited on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
#endif
}
bool CAGuard::WaitFor(UInt64 inNanos)
{
bool theAnswer = false;
#if TARGET_OS_MAC
ThrowIf(!pthread_equal(pthread_self(), mOwner), CAException(1), "CAGuard::WaitFor: A thread has to have locked a guard be for it can wait");
#if Log_TimedWaits
DebugMessageN1("CAGuard::WaitFor: waiting %.0f", (Float64)inNanos);
#endif
struct timespec theTimeSpec;
static const UInt64 kNanosPerSecond = 1000000000ULL;
if(inNanos >= kNanosPerSecond)
{
theTimeSpec.tv_sec = static_cast<long>(inNanos / kNanosPerSecond);
theTimeSpec.tv_nsec = static_cast<long>(inNanos % kNanosPerSecond);
}
else
{
theTimeSpec.tv_sec = 0;
theTimeSpec.tv_nsec = static_cast<long>(inNanos);
}
#if Log_TimedWaits || Log_Latency || Log_Average_Latency
UInt64 theStartNanos = CAHostTimeBase::GetCurrentTimeInNanos();
#endif
mOwner = 0;
#if Log_WaitOwnership
DebugPrintf("%p %.4f: CAGuard::WaitFor: thread %p is waiting on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
#endif
OSStatus theError = pthread_cond_timedwait_relative_np(&mCondVar, &mMutex, &theTimeSpec);
ThrowIf((theError != 0) && (theError != ETIMEDOUT), CAException(theError), "CAGuard::WaitFor: Wait got an error");
mOwner = pthread_self();
#if Log_TimedWaits || Log_Latency || Log_Average_Latency
UInt64 theEndNanos = CAHostTimeBase::GetCurrentTimeInNanos();
#endif
#if Log_TimedWaits
DebugMessageN1("CAGuard::WaitFor: waited %.0f", (Float64)(theEndNanos - theStartNanos));
#endif
#if Log_Latency
DebugMessageN1("CAGuard::WaitFor: latency %.0f", (Float64)((theEndNanos - theStartNanos) - inNanos));
#endif
#if Log_Average_Latency
++mAverageLatencyCount;
mAverageLatencyAccumulator += (theEndNanos - theStartNanos) - inNanos;
if(mAverageLatencyCount >= 50)
{
DebugMessageN2("CAGuard::WaitFor: average latency %.3f ns over %ld waits", mAverageLatencyAccumulator / mAverageLatencyCount, mAverageLatencyCount);
mAverageLatencyCount = 0;
mAverageLatencyAccumulator = 0.0;
}
#endif
#if Log_WaitOwnership
DebugPrintf("%p %.4f: CAGuard::WaitFor: thread %p waited on %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
#endif
theAnswer = theError == ETIMEDOUT;
#elif TARGET_OS_WIN32
ThrowIf(GetCurrentThreadId() != mOwner, CAException(1), "CAGuard::WaitFor: A thread has to have locked a guard be for it can wait");
#if Log_TimedWaits
DebugMessageN1("CAGuard::WaitFor: waiting %.0f", (Float64)inNanos);
#endif
// the time out is specified in milliseconds(!)
UInt32 theWaitTime = static_cast<UInt32>(inNanos / 1000000ULL);
#if Log_TimedWaits || Log_Latency || Log_Average_Latency
UInt64 theStartNanos = CAHostTimeBase::GetCurrentTimeInNanos();
#endif
mOwner = 0;
#if Log_WaitOwnership
DebugPrintf("%lu %.4f: CAGuard::WaitFor: thread %lu is waiting on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
ReleaseMutex(mMutex);
HANDLE theHandles[] = { mMutex, mEvent };
OSStatus theError = WaitForMultipleObjects(2, theHandles, true, theWaitTime);
ThrowIf((theError != WAIT_OBJECT_0) && (theError != WAIT_TIMEOUT), CAException(GetLastError()), "CAGuard::WaitFor: Wait got an error");
mOwner = GetCurrentThreadId();
ResetEvent(mEvent);
// This mutex should be locked again when time out happens.rdar://12270555
if(theError == WAIT_TIMEOUT) {
DWORD dwError = WaitForSingleObject(mMutex, INFINITE);
ThrowIf((dwError != WAIT_OBJECT_0), CAException(GetLastError()), "CAGuard::WaitFor: failed to acquire the mutex back when timeout happened\n");
}
#if Log_TimedWaits || Log_Latency || Log_Average_Latency
UInt64 theEndNanos = CAHostTimeBase::GetCurrentTimeInNanos();
#endif
#if Log_TimedWaits
DebugMessageN1("CAGuard::WaitFor: waited %.0f", (Float64)(theEndNanos - theStartNanos));
#endif
#if Log_Latency
DebugMessageN1("CAGuard::WaitFor: latency %.0f", (Float64)((theEndNanos - theStartNanos) - inNanos));
#endif
#if Log_Average_Latency
++mAverageLatencyCount;
mAverageLatencyAccumulator += (theEndNanos - theStartNanos) - inNanos;
if(mAverageLatencyCount >= 50)
{
DebugMessageN2("CAGuard::WaitFor: average latency %.3f ns over %ld waits", mAverageLatencyAccumulator / mAverageLatencyCount, mAverageLatencyCount);
mAverageLatencyCount = 0;
mAverageLatencyAccumulator = 0.0;
}
#endif
#if Log_WaitOwnership
DebugPrintf("%lu %.4f: CAGuard::WaitFor: thread %lu waited on %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
theAnswer = theError == WAIT_TIMEOUT;
#endif
return theAnswer;
}
bool CAGuard::WaitUntil(UInt64 inNanos)
{
bool theAnswer = false;
UInt64 theCurrentNanos = CAHostTimeBase::GetCurrentTimeInNanos();
#if Log_TimedWaits
DebugMessageN2("CAGuard::WaitUntil: now: %.0f, requested: %.0f", (double)theCurrentNanos, (double)inNanos);
#endif
if(inNanos > theCurrentNanos)
{
#if Log_Errors
if((inNanos - theCurrentNanos) > 1000000000ULL)
{
DebugMessage("CAGuard::WaitUntil: about to wait for more than a second");
}
#endif
theAnswer = WaitFor(inNanos - theCurrentNanos);
}
else
{
#if Log_Errors
DebugMessageN2("CAGuard::WaitUntil: Time has expired before waiting, now: %.0f, requested: %.0f", (double)theCurrentNanos, (double)inNanos);
#endif
theAnswer = true;
}
return theAnswer;
}
void CAGuard::Notify()
{
#if TARGET_OS_MAC
#if Log_WaitOwnership
DebugPrintf("%p %.4f: CAGuard::Notify: thread %p is notifying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
#endif
OSStatus theError = pthread_cond_signal(&mCondVar);
ThrowIf(theError != 0, CAException(theError), "CAGuard::Notify: failed");
#elif TARGET_OS_WIN32
#if Log_WaitOwnership
DebugPrintf("%lu %.4f: CAGuard::Notify: thread %lu is notifying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
SetEvent(mEvent);
#endif
}
void CAGuard::NotifyAll()
{
#if TARGET_OS_MAC
#if Log_WaitOwnership
DebugPrintf("%p %.4f: CAGuard::NotifyAll: thread %p is notifying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
#endif
OSStatus theError = pthread_cond_broadcast(&mCondVar);
ThrowIf(theError != 0, CAException(theError), "CAGuard::NotifyAll: failed");
#elif TARGET_OS_WIN32
#if Log_WaitOwnership
DebugPrintf("%lu %.4f: CAGuard::NotifyAll: thread %lu is notifying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
SetEvent(mEvent);
#endif
}

View File

@ -1,95 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#if !defined(__CAGuard_h__)
#define __CAGuard_h__
//==================================================================================================
// Includes
//=============================================================================
// Super Class Includes
#include "CAMutex.h"
#if CoreAudio_Debug
// #define Log_Average_Latency 1
#endif
//==================================================================================================
// CAGuard
//
// This is your typical mutex with signalling implemented via pthreads.
// Lock() will return true if and only if the guard is locked on that call.
// A thread that already has the guard will receive 'false' if it locks it
// again. Use of the stack-based CAGuard::Locker class is highly recommended
// to properly manage the recursive nesting. The Wait calls with timeouts
// will return true if and only if the timeout period expired. They will
// return false if they receive notification any other way.
//==================================================================================================
class CAGuard : public CAMutex
{
// Construction/Destruction
public:
CAGuard(const char* inName);
virtual ~CAGuard();
// Actions
public:
virtual void Wait();
virtual bool WaitFor(UInt64 inNanos);
virtual bool WaitUntil(UInt64 inNanos);
virtual void Notify();
virtual void NotifyAll();
// Implementation
protected:
#if TARGET_OS_MAC
pthread_cond_t mCondVar;
#else
HANDLE mEvent;
#endif
#if Log_Average_Latency
Float64 mAverageLatencyAccumulator;
UInt32 mAverageLatencyCount;
#endif
// Helper class to manage taking and releasing recursively
public:
class Locker
{
// Construction/Destruction
public:
Locker(CAGuard& inGuard) : mGuard(inGuard), mNeedsRelease(false) { mNeedsRelease = mGuard.Lock(); }
~Locker() { if(mNeedsRelease) { mGuard.Unlock(); } }
private:
Locker(const Locker&);
Locker& operator=(const Locker&);
// Actions
public:
void Wait() { mGuard.Wait(); }
bool WaitFor(UInt64 inNanos) { return mGuard.WaitFor(inNanos); }
bool WaitUntil(UInt64 inNanos) { return mGuard.WaitUntil(inNanos); }
void Notify() { mGuard.Notify(); }
void NotifyAll() { mGuard.NotifyAll(); }
// Implementation
private:
CAGuard& mGuard;
bool mNeedsRelease;
};
};
#endif

View File

@ -1,61 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
//=============================================================================
// Includes
//=============================================================================
#include "CAHostTimeBase.h"
Float64 CAHostTimeBase::sFrequency = 0;
Float64 CAHostTimeBase::sInverseFrequency = 0;
UInt32 CAHostTimeBase::sMinDelta = 0;
UInt32 CAHostTimeBase::sToNanosNumerator = 0;
UInt32 CAHostTimeBase::sToNanosDenominator = 0;
pthread_once_t CAHostTimeBase::sIsInited = PTHREAD_ONCE_INIT;
#if Track_Host_TimeBase
UInt64 CAHostTimeBase::sLastTime = 0;
#endif
//=============================================================================
// CAHostTimeBase
//
// This class provides platform independent access to the host's time base.
//=============================================================================
void CAHostTimeBase::Initialize()
{
// get the info about Absolute time
#if TARGET_OS_MAC
struct mach_timebase_info theTimeBaseInfo;
mach_timebase_info(&theTimeBaseInfo);
sMinDelta = 1;
sToNanosNumerator = theTimeBaseInfo.numer;
sToNanosDenominator = theTimeBaseInfo.denom;
// the frequency of that clock is: (sToNanosDenominator / sToNanosNumerator) * 10^9
sFrequency = static_cast<Float64>(sToNanosDenominator) / static_cast<Float64>(sToNanosNumerator);
sFrequency *= 1000000000.0;
#elif TARGET_OS_WIN32
LARGE_INTEGER theFrequency;
QueryPerformanceFrequency(&theFrequency);
sMinDelta = 1;
sToNanosNumerator = 1000000000ULL;
sToNanosDenominator = *((UInt64*)&theFrequency);
sFrequency = static_cast<Float64>(*((UInt64*)&theFrequency));
#endif
sInverseFrequency = 1.0 / sFrequency;
#if Log_Host_Time_Base_Parameters
DebugPrintf("Host Time Base Parameters");
DebugPrintf(" Minimum Delta: %lu", (unsigned long)sMinDelta);
DebugPrintf(" Frequency: %f", sFrequency);
DebugPrintf(" To Nanos Numerator: %lu", (unsigned long)sToNanosNumerator);
DebugPrintf(" To Nanos Denominator: %lu", (unsigned long)sToNanosDenominator);
#endif
}

View File

@ -1,196 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#if !defined(__CAHostTimeBase_h__)
#define __CAHostTimeBase_h__
//=============================================================================
// Includes
//=============================================================================
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include <CoreAudioTypes.h>
#endif
#if TARGET_OS_MAC
#include <mach/mach_time.h>
#include <pthread.h>
#elif TARGET_OS_WIN32
#include <windows.h>
#include "WinPThreadDefs.h"
#else
#error Unsupported operating system
#endif
#include "CADebugPrintf.h"
//=============================================================================
// CAHostTimeBase
//
// This class provides platform independent access to the host's time base.
//=============================================================================
#if CoreAudio_Debug
// #define Log_Host_Time_Base_Parameters 1
// #define Track_Host_TimeBase 1
#endif
class CAHostTimeBase
{
public:
static UInt64 ConvertToNanos(UInt64 inHostTime);
static UInt64 ConvertFromNanos(UInt64 inNanos);
static UInt64 GetTheCurrentTime();
#if TARGET_OS_MAC
static UInt64 GetCurrentTime() { return GetTheCurrentTime(); }
#endif
static UInt64 GetCurrentTimeInNanos();
static Float64 GetFrequency() { pthread_once(&sIsInited, Initialize); return sFrequency; }
static Float64 GetInverseFrequency() { pthread_once(&sIsInited, Initialize); return sInverseFrequency; }
static UInt32 GetMinimumDelta() { pthread_once(&sIsInited, Initialize); return sMinDelta; }
static UInt64 AbsoluteHostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime);
static SInt64 HostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime);
static UInt64 MultiplyByRatio(UInt64 inMuliplicand, UInt32 inNumerator, UInt32 inDenominator);
private:
static void Initialize();
static pthread_once_t sIsInited;
static Float64 sFrequency;
static Float64 sInverseFrequency;
static UInt32 sMinDelta;
static UInt32 sToNanosNumerator;
static UInt32 sToNanosDenominator;
#if Track_Host_TimeBase
static UInt64 sLastTime;
#endif
};
inline UInt64 CAHostTimeBase::GetTheCurrentTime()
{
UInt64 theTime = 0;
#if TARGET_OS_MAC
theTime = mach_absolute_time();
#elif TARGET_OS_WIN32
LARGE_INTEGER theValue;
QueryPerformanceCounter(&theValue);
theTime = *((UInt64*)&theValue);
#endif
#if Track_Host_TimeBase
if(sLastTime != 0)
{
if(theTime <= sLastTime)
{
DebugPrintf("CAHostTimeBase::GetTheCurrentTime: the current time is earlier than the last time, now: %qd, then: %qd", theTime, sLastTime);
}
sLastTime = theTime;
}
else
{
sLastTime = theTime;
}
#endif
return theTime;
}
inline UInt64 CAHostTimeBase::ConvertToNanos(UInt64 inHostTime)
{
pthread_once(&sIsInited, Initialize);
UInt64 theAnswer = MultiplyByRatio(inHostTime, sToNanosNumerator, sToNanosDenominator);
#if CoreAudio_Debug
if(((sToNanosNumerator > sToNanosDenominator) && (theAnswer < inHostTime)) || ((sToNanosDenominator > sToNanosNumerator) && (theAnswer > inHostTime)))
{
DebugPrintf("CAHostTimeBase::ConvertToNanos: The conversion wrapped");
}
#endif
return theAnswer;
}
inline UInt64 CAHostTimeBase::ConvertFromNanos(UInt64 inNanos)
{
pthread_once(&sIsInited, Initialize);
UInt64 theAnswer = MultiplyByRatio(inNanos, sToNanosDenominator, sToNanosNumerator);
#if CoreAudio_Debug
if(((sToNanosDenominator > sToNanosNumerator) && (theAnswer < inNanos)) || ((sToNanosNumerator > sToNanosDenominator) && (theAnswer > inNanos)))
{
DebugPrintf("CAHostTimeBase::ConvertFromNanos: The conversion wrapped");
}
#endif
return theAnswer;
}
inline UInt64 CAHostTimeBase::GetCurrentTimeInNanos()
{
return ConvertToNanos(GetTheCurrentTime());
}
inline UInt64 CAHostTimeBase::AbsoluteHostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime)
{
UInt64 theAnswer;
if(inStartTime <= inEndTime)
{
theAnswer = inEndTime - inStartTime;
}
else
{
theAnswer = inStartTime - inEndTime;
}
return ConvertToNanos(theAnswer);
}
inline SInt64 CAHostTimeBase::HostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime)
{
SInt64 theAnswer;
SInt64 theSign = 1;
if(inStartTime <= inEndTime)
{
theAnswer = static_cast<SInt64>(inEndTime - inStartTime);
}
else
{
theAnswer = static_cast<SInt64>(inStartTime - inEndTime);
theSign = -1;
}
return theSign * static_cast<SInt64>(ConvertToNanos(static_cast<UInt64>(theAnswer)));
}
inline UInt64 CAHostTimeBase::MultiplyByRatio(UInt64 inMuliplicand, UInt32 inNumerator, UInt32 inDenominator)
{
#if TARGET_OS_MAC && TARGET_RT_64_BIT
__uint128_t theAnswer = inMuliplicand;
#else
long double theAnswer = inMuliplicand;
#endif
if(inNumerator != inDenominator)
{
theAnswer *= inNumerator;
theAnswer /= inDenominator;
}
return static_cast<UInt64>(theAnswer);
}
#endif

View File

@ -1,102 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#if !defined(__CALogMacros_h__)
#define __CALogMacros_h__
//=============================================================================
// Log Macros
//=============================================================================
#if CoreAudio_Debug
#include "CADebugMacros.h"
#include "CADebugPrintf.h"
#include <stdio.h>
#include <string.h>
#define PrintLine(msg) DebugPrintfRtn(DebugPrintfFileComma "%s\n", (msg))
#define PrintBool(msg, b) DebugPrintfRtn(DebugPrintfFileComma "%s%s\n", (msg), (b) ? "true" : "false")
#define PrintIndexedBool(msg, i, b) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %s\n", (msg), (long)(i), (b) ? "true" : "false")
#define PrintToggle(msg, b) DebugPrintfRtn(DebugPrintfFileComma "%s%s\n", (msg), (b) ? "on" : "off")
#define PrintIndexedToggle(msg, i, b) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %s\n", (msg), (long)(i), (b) ? "on" : "off")
#define PrintInt(msg, n) DebugPrintfRtn(DebugPrintfFileComma "%s%ld\n", (msg), (long)(n))
#define PrintIndexedInt(msg, i, n) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %ld\n", (msg), (long)(i), (long)(n))
#define PrintHex(msg, n) DebugPrintfRtn(DebugPrintfFileComma "%s0x%lX\n", (msg), (unsigned long)(n))
#define PrintIndexedHex(msg, i, n) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: 0x%lX\n", (msg), (long)(i), (unsigned long)(n))
#define PrintFloat(msg, f) DebugPrintfRtn(DebugPrintfFileComma "%s%.6f\n", (msg), (f))
#define PrintIndexedFloat(msg, i, f) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %.6f\n", (msg), (long)(i), (f))
#define PrintFloatIndexedFloat(msg, i, f) DebugPrintfRtn(DebugPrintfFileComma " %s %.6f: %.6f\n", (msg), (i), (f))
#define PrintString(msg, s) DebugPrintfRtn(DebugPrintfFileComma "%s%s\n", (msg), (s))
#define PrintIndexedString(msg, i, s) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %s\n", (msg), (long)(i), (s))
#define PrintPointer(msg, p) DebugPrintfRtn(DebugPrintfFileComma "%s%p\n", (msg), (p))
#define PrintIndexedPointer(msg, i, p) DebugPrintfRtn(DebugPrintfFileComma " %s %ld: %p\n", (msg), (long)(i), (p))
#define Print4CharCode(msg, c) { \
UInt32 __4CC_number = (c); \
char __4CC_string[5] = CA4CCToCString(__4CC_number); \
DebugPrintfRtn(DebugPrintfFileComma "%s'%s'\n", (msg), __4CC_string); \
}
#define PrintIndexed4CharCode(msg, i, c) { \
UInt32 __4CC_number = (c); \
char __4CC_string[5] = CA4CCToCString(__4CC_number); \
DebugPrintfRtn(DebugPrintfFileComma " %s %ld: '%s'\n", (msg), (long)(i), __4CC_string); \
}
#define ErrorLine(s) DebugPrintfRtn(DebugPrintfFileComma "%s\n", (s))
#define OSErrorLine(s, e) { \
OSStatus __err_number = (e); \
char __err_string[5] = CA4CCToCString(__err_number); \
DebugPrintfRtn(DebugPrintfFileComma "%s, OSStatus code: %s\n", (s), __err_string); \
}
#define MessageIfOSError(e, s) if((e) != 0) { OSErrorLine(s, e); }
#define MessageIfNULL(p, s) if((p) == 0) { ErrorLine(s); }
#else
#define PrintLine(msg)
#define PrintBool(msg, b) (b)
#define PrintIndexedBool(msg, i, b) (b)
#define PrintInt(msg, n) (n)
#define PrintIndexedInt(msg, i, n) (n)
#define PrintHex(msg, n) (n)
#define PrintIndexedHex(msg, i, n) (n)
#define PrintFloat(msg, f) (f)
#define PrintIndexedFloat(msg, i, f) (f)
#define PrintFloatIndexedFloat(msg, i, f) (f)
#define PrintString(msg, s) (s)
#define PrintIndexedString(msg, i, s) (s)
#define PrintPointer(msg, p) (p)
#define PrintIndexedPointer(msg, i, p) (p)
#define Print4CharCode(msg, c) (c)
#define PrintIndexed4CharCode(msg, i, c) (c)
#define ErrorLine(s) (s)
#define OSErrorLine(s, e) (e)
#define MessageIfOSError(e, s) (e)
#define MessageIfNULL(p, s) (p)
#endif // CoreAudio_Debug
#endif

View File

@ -1,69 +0,0 @@
/*
File: CAMath.h
Abstract:
Version: 1.2
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2010 Apple Inc. All Rights Reserved.
*/
#ifndef __CAMath_h__
#define __CAMath_h__
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include <CoreAudioTypes.h>
#endif
inline bool fiszero(Float64 f) { return (f == 0.); }
inline bool fiszero(Float32 f) { return (f == 0.f); }
inline bool fnonzero(Float64 f) { return !fiszero(f); }
inline bool fnonzero(Float32 f) { return !fiszero(f); }
inline bool fequal(const Float64 &a, const Float64 &b) { return a == b; }
inline bool fequal(const Float32 &a, const Float32 &b) { return a == b; }
inline bool fnotequal(const Float64 &a, const Float64 &b) { return !fequal(a, b); }
inline bool fnotequal(const Float32 &a, const Float32 &b) { return !fequal(a, b); }
#endif // __CAMath_h__

View File

@ -1,307 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
//==================================================================================================
// Includes
//==================================================================================================
// Self Include
#include "CAMutex.h"
#if TARGET_OS_MAC
#include <errno.h>
#endif
// PublicUtility Includes
#include "CADebugMacros.h"
#include "CAException.h"
#include "CAHostTimeBase.h"
//==================================================================================================
// Logging
//==================================================================================================
#if CoreAudio_Debug
// #define Log_Ownership 1
// #define Log_Errors 1
// #define Log_LongLatencies 1
// #define LongLatencyThreshholdNS 1000000ULL // nanoseconds
#endif
//==================================================================================================
// CAMutex
//==================================================================================================
CAMutex::CAMutex(const char* inName)
:
mName(inName),
mOwner(0)
{
#if TARGET_OS_MAC
OSStatus theError = pthread_mutex_init(&mMutex, NULL);
ThrowIf(theError != 0, CAException(theError), "CAMutex::CAMutex: Could not init the mutex");
#if Log_Ownership
DebugPrintf("%p %.4f: CAMutex::CAMutex: creating %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
#endif
#elif TARGET_OS_WIN32
mMutex = CreateMutex(NULL, false, NULL);
ThrowIfNULL(mMutex, CAException(GetLastError()), "CAMutex::CAMutex: could not create the mutex.");
#if Log_Ownership
DebugPrintf("%lu %.4f: CAMutex::CAMutex: creating %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
#endif
#endif
}
CAMutex::~CAMutex()
{
#if TARGET_OS_MAC
#if Log_Ownership
DebugPrintf("%p %.4f: CAMutex::~CAMutex: destroying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
#endif
pthread_mutex_destroy(&mMutex);
#elif TARGET_OS_WIN32
#if Log_Ownership
DebugPrintf("%lu %.4f: CAMutex::~CAMutex: destroying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
#endif
if(mMutex != NULL)
{
CloseHandle(mMutex);
}
#endif
}
bool CAMutex::Lock()
{
bool theAnswer = false;
#if TARGET_OS_MAC
pthread_t theCurrentThread = pthread_self();
if(!pthread_equal(theCurrentThread, mOwner))
{
#if Log_Ownership
DebugPrintf("%p %.4f: CAMutex::Lock: thread %p is locking %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
#endif
#if Log_LongLatencies
UInt64 lockTryTime = CAHostTimeBase::GetCurrentTimeInNanos();
#endif
OSStatus theError = pthread_mutex_lock(&mMutex);
ThrowIf(theError != 0, CAException(theError), "CAMutex::Lock: Could not lock the mutex");
mOwner = theCurrentThread;
theAnswer = true;
#if Log_LongLatencies
UInt64 lockAcquireTime = CAHostTimeBase::GetCurrentTimeInNanos();
if (lockAcquireTime - lockTryTime >= LongLatencyThresholdNS)
DebugPrintf("Thread %p took %.6fs to acquire the lock %s\n", theCurrentThread, (lockAcquireTime - lockTryTime) * 1.0e-9 /* nanos to seconds */, mName);
#endif
#if Log_Ownership
DebugPrintf("%p %.4f: CAMutex::Lock: thread %p has locked %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
#endif
}
#elif TARGET_OS_WIN32
if(mOwner != GetCurrentThreadId())
{
#if Log_Ownership
DebugPrintf("%lu %.4f: CAMutex::Lock: thread %lu is locking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
OSStatus theError = WaitForSingleObject(mMutex, INFINITE);
ThrowIfError(theError, CAException(theError), "CAMutex::Lock: could not lock the mutex");
mOwner = GetCurrentThreadId();
theAnswer = true;
#if Log_Ownership
DebugPrintf("%lu %.4f: CAMutex::Lock: thread %lu has locked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
}
#endif
return theAnswer;
}
void CAMutex::Unlock()
{
#if TARGET_OS_MAC
if(pthread_equal(pthread_self(), mOwner))
{
#if Log_Ownership
DebugPrintf("%p %.4f: CAMutex::Unlock: thread %p is unlocking %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
#endif
mOwner = 0;
OSStatus theError = pthread_mutex_unlock(&mMutex);
ThrowIf(theError != 0, CAException(theError), "CAMutex::Unlock: Could not unlock the mutex");
#if Log_Ownership
DebugPrintf("%p %.4f: CAMutex::Unlock: thread %p has unlocked %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
#endif
}
else
{
DebugMessage("CAMutex::Unlock: A thread is attempting to unlock a Mutex it doesn't own");
}
#elif TARGET_OS_WIN32
if(mOwner == GetCurrentThreadId())
{
#if Log_Ownership
DebugPrintf("%lu %.4f: CAMutex::Unlock: thread %lu is unlocking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
mOwner = 0;
bool wasReleased = ReleaseMutex(mMutex);
ThrowIf(!wasReleased, CAException(GetLastError()), "CAMutex::Unlock: Could not unlock the mutex");
#if Log_Ownership
DebugPrintf("%lu %.4f: CAMutex::Unlock: thread %lu has unlocked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
}
else
{
DebugMessage("CAMutex::Unlock: A thread is attempting to unlock a Mutex it doesn't own");
}
#endif
}
bool CAMutex::Try(bool& outWasLocked)
{
bool theAnswer = false;
outWasLocked = false;
#if TARGET_OS_MAC
pthread_t theCurrentThread = pthread_self();
if(!pthread_equal(theCurrentThread, mOwner))
{
// this means the current thread doesn't already own the lock
#if Log_Ownership
DebugPrintf("%p %.4f: CAMutex::Try: thread %p is try-locking %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
#endif
// go ahead and call trylock to see if we can lock it.
int theError = pthread_mutex_trylock(&mMutex);
if(theError == 0)
{
// return value of 0 means we successfully locked the lock
mOwner = theCurrentThread;
theAnswer = true;
outWasLocked = true;
#if Log_Ownership
DebugPrintf("%p %.4f: CAMutex::Try: thread %p has locked %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
#endif
}
else if(theError == EBUSY)
{
// return value of EBUSY means that the lock was already locked by another thread
theAnswer = false;
outWasLocked = false;
#if Log_Ownership
DebugPrintf("%p %.4f: CAMutex::Try: thread %p failed to lock %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
#endif
}
else
{
// any other return value means something really bad happenned
ThrowIfError(theError, CAException(theError), "CAMutex::Try: call to pthread_mutex_trylock failed");
}
}
else
{
// this means the current thread already owns the lock
theAnswer = true;
outWasLocked = false;
}
#elif TARGET_OS_WIN32
if(mOwner != GetCurrentThreadId())
{
// this means the current thread doesn't own the lock
#if Log_Ownership
DebugPrintf("%lu %.4f: CAMutex::Try: thread %lu is try-locking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
// try to acquire the mutex
OSStatus theError = WaitForSingleObject(mMutex, 0);
if(theError == WAIT_OBJECT_0)
{
// this means we successfully locked the lock
mOwner = GetCurrentThreadId();
theAnswer = true;
outWasLocked = true;
#if Log_Ownership
DebugPrintf("%lu %.4f: CAMutex::Try: thread %lu has locked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
}
else if(theError == WAIT_TIMEOUT)
{
// this means that the lock was already locked by another thread
theAnswer = false;
outWasLocked = false;
#if Log_Ownership
DebugPrintf("%lu %.4f: CAMutex::Try: thread %lu failed to lock %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
}
else
{
// any other return value means something really bad happenned
ThrowIfError(theError, CAException(GetLastError()), "CAMutex::Try: call to lock the mutex failed");
}
}
else
{
// this means the current thread already owns the lock
theAnswer = true;
outWasLocked = false;
}
#endif
return theAnswer;
}
bool CAMutex::IsFree() const
{
return mOwner == 0;
}
bool CAMutex::IsOwnedByCurrentThread() const
{
bool theAnswer = true;
#if TARGET_OS_MAC
theAnswer = pthread_equal(pthread_self(), mOwner);
#elif TARGET_OS_WIN32
theAnswer = (mOwner == GetCurrentThreadId());
#endif
return theAnswer;
}
CAMutex::Unlocker::Unlocker(CAMutex& inMutex)
: mMutex(inMutex),
mNeedsLock(false)
{
Assert(mMutex.IsOwnedByCurrentThread(), "Major problem: Unlocker attempted to unlock a mutex not owned by the current thread!");
mMutex.Unlock();
mNeedsLock = true;
}
CAMutex::Unlocker::~Unlocker()
{
if(mNeedsLock)
{
mMutex.Lock();
}
}

View File

@ -1,125 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#ifndef __CAMutex_h__
#define __CAMutex_h__
//==================================================================================================
// Includes
//==================================================================================================
// System Includes
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include <CoreAudioTypes.h>
#endif
#if TARGET_OS_MAC
#include <pthread.h>
#elif TARGET_OS_WIN32
#include <windows.h>
#else
#error Unsupported operating system
#endif
//==================================================================================================
// A recursive mutex.
//==================================================================================================
class CAMutex
{
// Construction/Destruction
public:
CAMutex(const char* inName);
virtual ~CAMutex();
// Actions
public:
virtual bool Lock();
virtual void Unlock();
virtual bool Try(bool& outWasLocked); // returns true if lock is free, false if not
virtual bool IsFree() const;
virtual bool IsOwnedByCurrentThread() const;
// Implementation
protected:
const char* mName;
#if TARGET_OS_MAC
pthread_t mOwner;
pthread_mutex_t mMutex;
#elif TARGET_OS_WIN32
UInt32 mOwner;
HANDLE mMutex;
#endif
// Helper class to manage taking and releasing recursively
public:
class Locker
{
// Construction/Destruction
public:
Locker(CAMutex& inMutex) : mMutex(&inMutex), mNeedsRelease(false) { mNeedsRelease = mMutex->Lock(); }
Locker(CAMutex* inMutex) : mMutex(inMutex), mNeedsRelease(false) { mNeedsRelease = (mMutex != NULL && mMutex->Lock()); }
// in this case the mutex can be null
~Locker() { if(mNeedsRelease) { mMutex->Unlock(); } }
private:
Locker(const Locker&);
Locker& operator=(const Locker&);
// Implementation
private:
CAMutex* mMutex;
bool mNeedsRelease;
};
// Unlocker
class Unlocker
{
public:
Unlocker(CAMutex& inMutex);
~Unlocker();
private:
CAMutex& mMutex;
bool mNeedsLock;
// Hidden definitions of copy ctor, assignment operator
Unlocker(const Unlocker& copy); // Not implemented
Unlocker& operator=(const Unlocker& copy); // Not implemented
};
// you can use this with Try - if you take the lock in try, pass in the outWasLocked var
class Tryer {
// Construction/Destruction
public:
Tryer (CAMutex &mutex) : mMutex(mutex), mNeedsRelease(false), mHasLock(false) { mHasLock = mMutex.Try (mNeedsRelease); }
~Tryer () { if (mNeedsRelease) mMutex.Unlock(); }
bool HasLock () const { return mHasLock; }
private:
Tryer(const Tryer&);
Tryer& operator=(const Tryer&);
// Implementation
private:
CAMutex & mMutex;
bool mNeedsRelease;
bool mHasLock;
};
};
#endif // __CAMutex_h__

View File

@ -1,59 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#ifndef __CAReferenceCounted_h__
#define __CAReferenceCounted_h__
#include "CAAtomic.h"
// base class for reference-counted objects
class CAReferenceCounted {
public:
CAReferenceCounted() : mRefCount(1) {}
void retain() { CAAtomicIncrement32(&mRefCount); }
void release()
{
SInt32 rc = CAAtomicDecrement32(&mRefCount);
if (rc == 0) {
releaseObject();
}
}
class Retainer {
public:
Retainer(CAReferenceCounted *obj) : mObject(obj) { mObject->retain(); }
~Retainer() { mObject->release(); }
private:
CAReferenceCounted * mObject;
};
protected:
virtual ~CAReferenceCounted() { }
virtual void releaseObject ()
{
delete this;
}
#if DEBUG
public:
#endif
SInt32 GetReferenceCount() const { return mRefCount; }
private:
SInt32 mRefCount;
CAReferenceCounted(const CAReferenceCounted &a);
CAReferenceCounted &operator=(const CAReferenceCounted &a);
};
#endif // __CAReferenceCounted_h__

View File

@ -1,887 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#include "CAStreamBasicDescription.h"
#include "CAMath.h"
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreFoundation/CFByteOrder.h>
#else
#include <CFByteOrder.h>
#endif
#pragma mark This file needs to compile on earlier versions of the OS, so please keep that in mind when editing it
char *CAStringForOSType (OSType t, char *writeLocation, size_t bufsize)
{
if (bufsize > 0) {
char *p = writeLocation, *pend = writeLocation + bufsize;
union { UInt32 i; unsigned char str[4]; } u;
unsigned char *q = u.str;
u.i = CFSwapInt32HostToBig(t);
bool hasNonPrint = false;
for (int i = 0; i < 4; ++i) {
if (!(isprint(*q) && *q != '\\')) {
hasNonPrint = true;
break;
}
q++;
}
q = u.str;
if (hasNonPrint)
p += snprintf (p, pend - p, "0x");
else if (p < pend)
*p++ = '\'';
for (int i = 0; i < 4 && p < pend; ++i) {
if (hasNonPrint) {
p += snprintf(p, pend - p, "%02X", *q++);
} else {
*p++ = *q++;
}
}
if (!hasNonPrint && p < pend)
*p++ = '\'';
if (p >= pend) p -= 1;
*p = '\0';
}
return writeLocation;
}
const AudioStreamBasicDescription CAStreamBasicDescription::sEmpty = { 0.0, 0, 0, 0, 0, 0, 0, 0, 0 };
CAStreamBasicDescription::CAStreamBasicDescription()
{
memset (this, 0, sizeof(AudioStreamBasicDescription));
}
CAStreamBasicDescription::CAStreamBasicDescription(const AudioStreamBasicDescription &desc)
{
SetFrom(desc);
}
CAStreamBasicDescription::CAStreamBasicDescription(double inSampleRate, UInt32 inFormatID,
UInt32 inBytesPerPacket, UInt32 inFramesPerPacket,
UInt32 inBytesPerFrame, UInt32 inChannelsPerFrame,
UInt32 inBitsPerChannel, UInt32 inFormatFlags)
{
mSampleRate = inSampleRate;
mFormatID = inFormatID;
mBytesPerPacket = inBytesPerPacket;
mFramesPerPacket = inFramesPerPacket;
mBytesPerFrame = inBytesPerFrame;
mChannelsPerFrame = inChannelsPerFrame;
mBitsPerChannel = inBitsPerChannel;
mFormatFlags = inFormatFlags;
mReserved = 0;
}
char *CAStreamBasicDescription::AsString(char *buf, size_t _bufsize, bool brief /*=false*/) const
{
int bufsize = (int)_bufsize; // must be signed to protect against overflow
char *theBuffer = buf;
int nc;
char formatID[24];
CAStringForOSType(mFormatID, formatID, sizeof(formatID));
if (brief) {
CommonPCMFormat com;
bool interleaved;
if (IdentifyCommonPCMFormat(com, &interleaved) && com != kPCMFormatOther) {
const char *desc;
switch (com) {
case kPCMFormatInt16:
desc = "Int16";
break;
case kPCMFormatInt32:
desc = "Int32";
break;
case kPCMFormatFixed824:
desc = "Int8.24";
break;
case kPCMFormatFloat32:
desc = "Float32";
break;
case kPCMFormatFloat64:
desc = "Float64";
break;
default:
desc = NULL;
break;
}
if (desc) {
const char *inter ="";
if (mChannelsPerFrame > 1)
inter = !interleaved ? ", non-inter" : ", inter";
snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz, %s%s", (int)mChannelsPerFrame, mSampleRate, desc, inter);
return theBuffer;
}
}
if (mChannelsPerFrame == 0 && mSampleRate == 0.0 && mFormatID == 0) {
snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz", (int)mChannelsPerFrame, mSampleRate);
return theBuffer;
}
}
nc = snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz, %s (0x%08X) ", (int)NumberChannels(), mSampleRate, formatID, (int)mFormatFlags);
buf += nc; if ((bufsize -= nc) <= 0) goto exit;
if (mFormatID == kAudioFormatLinearPCM) {
bool isInt = !(mFormatFlags & kLinearPCMFormatFlagIsFloat);
int wordSize = static_cast<int>(SampleWordSize());
const char *endian = (wordSize > 1) ?
((mFormatFlags & kLinearPCMFormatFlagIsBigEndian) ? " big-endian" : " little-endian" ) : "";
const char *sign = isInt ?
((mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) ? " signed" : " unsigned") : "";
const char *floatInt = isInt ? "integer" : "float";
char packed[32];
if (wordSize > 0 && PackednessIsSignificant()) {
if (mFormatFlags & kLinearPCMFormatFlagIsPacked)
snprintf(packed, sizeof(packed), "packed in %d bytes", wordSize);
else
snprintf(packed, sizeof(packed), "unpacked in %d bytes", wordSize);
} else
packed[0] = '\0';
const char *align = (wordSize > 0 && AlignmentIsSignificant()) ?
((mFormatFlags & kLinearPCMFormatFlagIsAlignedHigh) ? " high-aligned" : " low-aligned") : "";
const char *deinter = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) ? ", deinterleaved" : "";
const char *commaSpace = (packed[0]!='\0') || (align[0]!='\0') ? ", " : "";
char bitdepth[20];
int fracbits = (mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
if (fracbits > 0)
snprintf(bitdepth, sizeof(bitdepth), "%d.%d", (int)mBitsPerChannel - fracbits, fracbits);
else
snprintf(bitdepth, sizeof(bitdepth), "%d", (int)mBitsPerChannel);
/*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%s-bit%s%s %s%s%s%s%s",
bitdepth, endian, sign, floatInt,
commaSpace, packed, align, deinter);
// buf += nc; if ((bufsize -= nc) <= 0) goto exit;
} else if (mFormatID == kAudioFormatAppleLossless) {
int sourceBits = 0;
switch (mFormatFlags)
{
case 1: // kAppleLosslessFormatFlag_16BitSourceData
sourceBits = 16;
break;
case 2: // kAppleLosslessFormatFlag_20BitSourceData
sourceBits = 20;
break;
case 3: // kAppleLosslessFormatFlag_24BitSourceData
sourceBits = 24;
break;
case 4: // kAppleLosslessFormatFlag_32BitSourceData
sourceBits = 32;
break;
}
if (sourceBits)
nc = snprintf(buf, static_cast<size_t>(bufsize), "from %d-bit source, ", sourceBits);
else
nc = snprintf(buf, static_cast<size_t>(bufsize), "from UNKNOWN source bit depth, ");
buf += nc; if ((bufsize -= nc) <= 0) goto exit;
/*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%d frames/packet", (int)mFramesPerPacket);
// buf += nc; if ((bufsize -= nc) <= 0) goto exit;
}
else
/*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%d bits/channel, %d bytes/packet, %d frames/packet, %d bytes/frame",
(int)mBitsPerChannel, (int)mBytesPerPacket, (int)mFramesPerPacket, (int)mBytesPerFrame);
exit:
return theBuffer;
}
void CAStreamBasicDescription::NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription)
{
// the only thing that changes is to make mixable linear PCM into the canonical linear PCM format
if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0))
{
// the canonical linear PCM format
ioDescription.mFormatFlags = kAudioFormatFlagsCanonical;
ioDescription.mBytesPerPacket = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
ioDescription.mFramesPerPacket = 1;
ioDescription.mBytesPerFrame = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
ioDescription.mBitsPerChannel = 8 * SizeOf32(AudioSampleType);
}
}
void CAStreamBasicDescription::NormalizeLinearPCMFormat(bool inNativeEndian, AudioStreamBasicDescription& ioDescription)
{
// the only thing that changes is to make mixable linear PCM into the canonical linear PCM format
if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0))
{
// the canonical linear PCM format
ioDescription.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked;
if(inNativeEndian)
{
#if TARGET_RT_BIG_ENDIAN
ioDescription.mFormatFlags |= kAudioFormatFlagIsBigEndian;
#endif
}
else
{
#if TARGET_RT_LITTLE_ENDIAN
ioDescription.mFormatFlags |= kAudioFormatFlagIsBigEndian;
#endif
}
ioDescription.mBytesPerPacket = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
ioDescription.mFramesPerPacket = 1;
ioDescription.mBytesPerFrame = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
ioDescription.mBitsPerChannel = 8 * SizeOf32(AudioSampleType);
}
}
void CAStreamBasicDescription::VirtualizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription)
{
// the only thing that changes is to make mixable linear PCM into the HAL's virtual linear PCM format, which is Float32 currently
if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0))
{
// the virtual linear PCM format
ioDescription.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
ioDescription.mBytesPerPacket = SizeOf32(Float32) * ioDescription.mChannelsPerFrame;
ioDescription.mFramesPerPacket = 1;
ioDescription.mBytesPerFrame = SizeOf32(Float32) * ioDescription.mChannelsPerFrame;
ioDescription.mBitsPerChannel = 8 * SizeOf32(Float32);
}
}
void CAStreamBasicDescription::VirtualizeLinearPCMFormat(bool inNativeEndian, AudioStreamBasicDescription& ioDescription)
{
// the only thing that changes is to make mixable linear PCM into the HAL's virtual linear PCM format, which is Float32 currently
if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0))
{
// the virtual linear PCM format
ioDescription.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked;
if(inNativeEndian)
{
#if TARGET_RT_BIG_ENDIAN
ioDescription.mFormatFlags |= kAudioFormatFlagIsBigEndian;
#endif
}
else
{
#if TARGET_RT_LITTLE_ENDIAN
ioDescription.mFormatFlags |= kAudioFormatFlagIsBigEndian;
#endif
}
ioDescription.mBytesPerPacket = SizeOf32(Float32) * ioDescription.mChannelsPerFrame;
ioDescription.mFramesPerPacket = 1;
ioDescription.mBytesPerFrame = SizeOf32(Float32) * ioDescription.mChannelsPerFrame;
ioDescription.mBitsPerChannel = 8 * SizeOf32(Float32);
}
}
void CAStreamBasicDescription::ResetFormat(AudioStreamBasicDescription& ioDescription)
{
ioDescription.mSampleRate = 0;
ioDescription.mFormatID = 0;
ioDescription.mBytesPerPacket = 0;
ioDescription.mFramesPerPacket = 0;
ioDescription.mBytesPerFrame = 0;
ioDescription.mChannelsPerFrame = 0;
ioDescription.mBitsPerChannel = 0;
ioDescription.mFormatFlags = 0;
}
void CAStreamBasicDescription::FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription)
{
if(fiszero(ioDescription.mSampleRate))
{
ioDescription.mSampleRate = inTemplateDescription.mSampleRate;
}
if(ioDescription.mFormatID == 0)
{
ioDescription.mFormatID = inTemplateDescription.mFormatID;
}
if(ioDescription.mFormatFlags == 0)
{
ioDescription.mFormatFlags = inTemplateDescription.mFormatFlags;
}
if(ioDescription.mBytesPerPacket == 0)
{
ioDescription.mBytesPerPacket = inTemplateDescription.mBytesPerPacket;
}
if(ioDescription.mFramesPerPacket == 0)
{
ioDescription.mFramesPerPacket = inTemplateDescription.mFramesPerPacket;
}
if(ioDescription.mBytesPerFrame == 0)
{
ioDescription.mBytesPerFrame = inTemplateDescription.mBytesPerFrame;
}
if(ioDescription.mChannelsPerFrame == 0)
{
ioDescription.mChannelsPerFrame = inTemplateDescription.mChannelsPerFrame;
}
if(ioDescription.mBitsPerChannel == 0)
{
ioDescription.mBitsPerChannel = inTemplateDescription.mBitsPerChannel;
}
}
void CAStreamBasicDescription::GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, UInt32 inMaxNameLength, bool inAbbreviate, bool inIncludeSampleRate)
{
if(inIncludeSampleRate)
{
int theCharactersWritten = snprintf(outName, inMaxNameLength, "%.0f ", inDescription.mSampleRate);
outName += theCharactersWritten;
inMaxNameLength -= static_cast<UInt32>(theCharactersWritten);
}
switch(inDescription.mFormatID)
{
case kAudioFormatLinearPCM:
{
const char* theEndianString = NULL;
if((inDescription.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0)
{
#if TARGET_RT_LITTLE_ENDIAN
theEndianString = "Big Endian";
#endif
}
else
{
#if TARGET_RT_BIG_ENDIAN
theEndianString = "Little Endian";
#endif
}
const char* theKindString = NULL;
if((inDescription.mFormatFlags & kAudioFormatFlagIsFloat) != 0)
{
theKindString = (inAbbreviate ? "Float" : "Floating Point");
}
else if((inDescription.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
{
theKindString = (inAbbreviate ? "SInt" : "Signed Integer");
}
else
{
theKindString = (inAbbreviate ? "UInt" : "Unsigned Integer");
}
const char* thePackingString = NULL;
if((inDescription.mFormatFlags & kAudioFormatFlagIsPacked) == 0)
{
if((inDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) != 0)
{
thePackingString = "High";
}
else
{
thePackingString = "Low";
}
}
const char* theMixabilityString = NULL;
if((inDescription.mFormatFlags & kIsNonMixableFlag) == 0)
{
theMixabilityString = "Mixable";
}
else
{
theMixabilityString = "Unmixable";
}
if(inAbbreviate)
{
if(theEndianString != NULL)
{
if(thePackingString != NULL)
{
snprintf(outName, inMaxNameLength, "%s %d Ch %s %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
}
else
{
snprintf(outName, inMaxNameLength, "%s %d Ch %s %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, theKindString, (int)inDescription.mBitsPerChannel);
}
}
else
{
if(thePackingString != NULL)
{
snprintf(outName, inMaxNameLength, "%s %d Ch %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)((inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8));
}
else
{
snprintf(outName, inMaxNameLength, "%s %d Ch %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theKindString, (int)inDescription.mBitsPerChannel);
}
}
}
else
{
if(theEndianString != NULL)
{
if(thePackingString != NULL)
{
snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
}
else
{
snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString);
}
}
else
{
if(thePackingString != NULL)
{
snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
}
else
{
snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString);
}
}
}
}
break;
case kAudioFormatAC3:
strlcpy(outName, "AC-3", sizeof(outName));
break;
case kAudioFormat60958AC3:
strlcpy(outName, "AC-3 for SPDIF", sizeof(outName));
break;
default:
CACopy4CCToCString(outName, inDescription.mFormatID);
break;
};
}
#if CoreAudio_Debug
#include "CALogMacros.h"
void CAStreamBasicDescription::PrintToLog(const AudioStreamBasicDescription& inDesc)
{
PrintFloat (" Sample Rate: ", inDesc.mSampleRate);
Print4CharCode (" Format ID: ", inDesc.mFormatID);
PrintHex (" Format Flags: ", inDesc.mFormatFlags);
PrintInt (" Bytes per Packet: ", inDesc.mBytesPerPacket);
PrintInt (" Frames per Packet: ", inDesc.mFramesPerPacket);
PrintInt (" Bytes per Frame: ", inDesc.mBytesPerFrame);
PrintInt (" Channels per Frame: ", inDesc.mChannelsPerFrame);
PrintInt (" Bits per Channel: ", inDesc.mBitsPerChannel);
}
#endif
bool operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
{
bool theAnswer = false;
bool isDone = false;
// note that if either side is 0, that field is skipped
// format ID is the first order sort
if((!isDone) && ((x.mFormatID != 0) && (y.mFormatID != 0)))
{
if(x.mFormatID != y.mFormatID)
{
// formats are sorted numerically except that linear
// PCM is always first
if(x.mFormatID == kAudioFormatLinearPCM)
{
theAnswer = true;
}
else if(y.mFormatID == kAudioFormatLinearPCM)
{
theAnswer = false;
}
else
{
theAnswer = x.mFormatID < y.mFormatID;
}
isDone = true;
}
}
// mixable is always better than non-mixable for linear PCM and should be the second order sort item
if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
{
if(((x.mFormatFlags & kIsNonMixableFlag) == 0) && ((y.mFormatFlags & kIsNonMixableFlag) != 0))
{
theAnswer = true;
isDone = true;
}
else if(((x.mFormatFlags & kIsNonMixableFlag) != 0) && ((y.mFormatFlags & kIsNonMixableFlag) == 0))
{
theAnswer = false;
isDone = true;
}
}
// floating point vs integer for linear PCM only
if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
{
if((x.mFormatFlags & kAudioFormatFlagIsFloat) != (y.mFormatFlags & kAudioFormatFlagIsFloat))
{
// floating point is better than integer
theAnswer = y.mFormatFlags & kAudioFormatFlagIsFloat;
isDone = true;
}
}
// bit depth
if((!isDone) && ((x.mBitsPerChannel != 0) && (y.mBitsPerChannel != 0)))
{
if(x.mBitsPerChannel != y.mBitsPerChannel)
{
// deeper bit depths are higher quality
theAnswer = x.mBitsPerChannel < y.mBitsPerChannel;
isDone = true;
}
}
// sample rate
if((!isDone) && fnonzero(x.mSampleRate) && fnonzero(y.mSampleRate))
{
if(fnotequal(x.mSampleRate, y.mSampleRate))
{
// higher sample rates are higher quality
theAnswer = x.mSampleRate < y.mSampleRate;
isDone = true;
}
}
// number of channels
if((!isDone) && ((x.mChannelsPerFrame != 0) && (y.mChannelsPerFrame != 0)))
{
if(x.mChannelsPerFrame != y.mChannelsPerFrame)
{
// more channels is higher quality
theAnswer = x.mChannelsPerFrame < y.mChannelsPerFrame;
//isDone = true;
}
}
return theAnswer;
}
UInt32 CAStreamBasicDescription::GetRegularizedFormatFlags(bool forHardware) const
{
UInt32 result = mFormatFlags;
if (IsPCM()) {
// First, if there are bits other than AllClear set, clear it because it's lying.
if (result & ~kAudioFormatFlagsAreAllClear)
result &= ~kAudioFormatFlagsAreAllClear;
// If not forHardware, remove the mixability flag.
if (!forHardware)
result &= ~kLinearPCMFormatFlagIsNonMixable;
// If the format has no extra bits, then it is packed.
if (!PackednessIsSignificant())
result |= kLinearPCMFormatFlagIsPacked;
// Remove the high-aligned flag if alignment is irrelevant.
if (!AlignmentIsSignificant())
result &= ~kLinearPCMFormatFlagIsAlignedHigh;
// Remove the signed integer bit if it's float
if (result & kLinearPCMFormatFlagIsFloat)
result &= ~kLinearPCMFormatFlagIsSignedInteger;
// If the bit depth is 8 bits or less and the format is packed, we don't care about endianness
if (mBitsPerChannel <= 8 && (result & kLinearPCMFormatFlagIsPacked))
result &= kAudioFormatFlagIsBigEndian;
// If there is 1 channel, we don't care about non-interleavedness.
if (mChannelsPerFrame == 1)
result &= ~kLinearPCMFormatFlagIsNonInterleaved;
// Finally, if the bits really are all 0, set the AllClear flag.
if (result == 0)
result = kAudioFormatFlagsAreAllClear;
}
return result;
}
// private
bool CAStreamBasicDescription::EquivalentFormatFlags(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y, bool forHardware, bool usingWildcards)
{
if (usingWildcards)
{
// if either of the formats is a wildcard, we don't care about the flags
// if either of the flags is a wildcard, we have matched
if (x.mFormatID == 0 || y.mFormatID == 0 || x.mFormatFlags == 0 || y.mFormatFlags == 0)
{
return true;
}
}
if (x.mFormatID != kAudioFormatLinearPCM) // we already know the formatID's match and have taken wildcards out of the picture.
return x.mFormatFlags == y.mFormatFlags;
// It is safe to down-cast from AudioStreamBasicDescription to its C++ wrapper.
// The cast could be avoided with a copy, but here, efficiency matters.
const CAStreamBasicDescription &a = *static_cast<const CAStreamBasicDescription *>(&x);
const CAStreamBasicDescription &b = *static_cast<const CAStreamBasicDescription *>(&y);
return a.GetRegularizedFormatFlags(forHardware) == b.GetRegularizedFormatFlags(forHardware);
}
bool CAStreamBasicDescription::IsExactlyEqual(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y)
{
// mReserved didn't exist in early versions of OS X; we want to ignore differences there.
// The structure is properly packed up until that point, so the shortcut of using memcmp()
// instead of individual field comparisons is safe.
return memcmp(&x, &y, offsetof(AudioStreamBasicDescription, mReserved)) == 0;
}
#define MATCH_WITH_WILDCARD(name) ((x.name) == 0 || (y.name) == 0 || (x.name) == (y.name))
bool CAStreamBasicDescription::IsEquivalent(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y, ComparisonOptions options)
{
if (options & kCompareUsingWildcards) {
return
// check the sample rate
(fiszero(x.mSampleRate) || fiszero(y.mSampleRate) || fequal(x.mSampleRate, y.mSampleRate))
// check the format ids
&& MATCH_WITH_WILDCARD(mFormatID)
// check the bytes per packet
&& MATCH_WITH_WILDCARD(mBytesPerPacket)
// check the frames per packet
&& MATCH_WITH_WILDCARD(mFramesPerPacket)
// check the bytes per frame
&& MATCH_WITH_WILDCARD(mBytesPerFrame)
// check the channels per frame
&& MATCH_WITH_WILDCARD(mChannelsPerFrame)
// check the bits per channel
&& MATCH_WITH_WILDCARD(mBitsPerChannel)
// Only if we get this far, do the work of matching the format flags
&& EquivalentFormatFlags(x, y, options & kCompareForHardware, /*usingWildcards=*/true);
} else {
return x.mSampleRate == y.mSampleRate
&& x.mFormatID == y.mFormatID
&& x.mBytesPerPacket == y.mBytesPerPacket
&& x.mFramesPerPacket == y.mFramesPerPacket
&& x.mChannelsPerFrame == y.mChannelsPerFrame
&& x.mBitsPerChannel == y.mBitsPerChannel
&& EquivalentFormatFlags(x, y, options & kCompareForHardware, /*usingWildcards=*/false);
}
}
// DEPRECATED.
bool operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
{
return CAStreamBasicDescription::IsEquivalent(x, y, CAStreamBasicDescription::kCompareUsingWildcards | CAStreamBasicDescription::kCompareForHardware);
}
// To be deprecated.
bool CAStreamBasicDescription::IsEqual(const AudioStreamBasicDescription &other, bool interpretingWildcards) const
{
if (interpretingWildcards)
return CAStreamBasicDescription::IsEquivalent(*this, other, CAStreamBasicDescription::kCompareUsingWildcards | CAStreamBasicDescription::kCompareForHardware);
return IsExactlyEqual(*this, other);
}
// DEPRECATED.
bool CAStreamBasicDescription::IsEqual(const AudioStreamBasicDescription &other) const
{
return CAStreamBasicDescription::IsEquivalent(*this, other, CAStreamBasicDescription::kCompareUsingWildcards | CAStreamBasicDescription::kCompareForHardware);
}
bool SanityCheck(const AudioStreamBasicDescription& x)
{
// This function returns false if there are sufficiently insane values in any field.
// It is very conservative so even some very unlikely values will pass.
// This is just meant to catch the case where the data from a file is corrupted.
return
(x.mSampleRate >= 0.)
&& (x.mSampleRate < 3e6) // SACD sample rate is 2.8224 MHz
&& (x.mBytesPerPacket < 1000000)
&& (x.mFramesPerPacket < 1000000)
&& (x.mBytesPerFrame < 1000000)
&& (x.mChannelsPerFrame > 0)
&& (x.mChannelsPerFrame <= 1024)
&& (x.mBitsPerChannel <= 1024)
&& (x.mFormatID != 0)
&& !(x.mFormatID == kAudioFormatLinearPCM && (x.mFramesPerPacket != 1 || x.mBytesPerPacket != x.mBytesPerFrame));
}
bool CAStreamBasicDescription::FromText(const char *inTextDesc, AudioStreamBasicDescription &fmt)
{
const char *p = inTextDesc;
memset(&fmt, 0, sizeof(fmt));
bool isPCM = true; // until proven otherwise
UInt32 pcmFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
if (p[0] == '-') // previously we required a leading dash on PCM formats
++p;
if (p[0] == 'B' && p[1] == 'E') {
pcmFlags |= kLinearPCMFormatFlagIsBigEndian;
p += 2;
} else if (p[0] == 'L' && p[1] == 'E') {
p += 2;
} else {
// default is native-endian
#if TARGET_RT_BIG_ENDIAN
pcmFlags |= kLinearPCMFormatFlagIsBigEndian;
#endif
}
if (p[0] == 'F') {
pcmFlags = (pcmFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger)) | kAudioFormatFlagIsFloat;
++p;
} else {
if (p[0] == 'U') {
pcmFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger);
++p;
}
if (p[0] == 'I')
++p;
else {
// it's not PCM; presumably some other format (NOT VALIDATED; use AudioFormat for that)
isPCM = false;
p = inTextDesc; // go back to the beginning
char buf[4] = { ' ',' ',' ',' ' };
for (int i = 0; i < 4; ++i) {
if (*p != '\\') {
if ((buf[i] = *p++) == '\0') {
// special-case for 'aac'
if (i != 3) return false;
--p; // keep pointing at the terminating null
buf[i] = ' ';
break;
}
} else {
// "\xNN" is a hex byte
if (*++p != 'x') return false;
int x;
if (sscanf(++p, "%02X", &x) != 1) return false;
buf[i] = static_cast<char>(x);
p += 2;
}
}
if (strchr("-@/#", buf[3])) {
// further special-casing for 'aac'
buf[3] = ' ';
--p;
}
memcpy(&fmt.mFormatID, buf, 4);
fmt.mFormatID = CFSwapInt32BigToHost(fmt.mFormatID);
}
}
if (isPCM) {
fmt.mFormatID = kAudioFormatLinearPCM;
fmt.mFormatFlags = pcmFlags;
fmt.mFramesPerPacket = 1;
fmt.mChannelsPerFrame = 1;
UInt32 bitdepth = 0, fracbits = 0;
while (isdigit(*p))
bitdepth = 10 * bitdepth + static_cast<UInt32>(*p++ - '0');
if (*p == '.') {
++p;
if (!isdigit(*p)) {
fprintf(stderr, "Expected fractional bits following '.'\n");
goto Bail;
}
while (isdigit(*p))
fracbits = 10 * fracbits + static_cast<UInt32>(*p++ - '0');
bitdepth += fracbits;
fmt.mFormatFlags |= (fracbits << kLinearPCMFormatFlagsSampleFractionShift);
}
fmt.mBitsPerChannel = bitdepth;
fmt.mBytesPerPacket = fmt.mBytesPerFrame = (bitdepth + 7) / 8;
if (bitdepth & 7) {
// assume unpacked. (packed odd bit depths are describable but not supported in AudioConverter.)
fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsPacked);
// alignment matters; default to high-aligned. use ':L_' for low.
fmt.mFormatFlags |= kLinearPCMFormatFlagIsAlignedHigh;
}
}
if (*p == '@') {
++p;
while (isdigit(*p))
fmt.mSampleRate = 10 * fmt.mSampleRate + (*p++ - '0');
}
if (*p == '/') {
UInt32 flags = 0;
while (true) {
char c = *++p;
if (c >= '0' && c <= '9')
flags = (flags << 4) | static_cast<UInt32>(c - '0');
else if (c >= 'A' && c <= 'F')
flags = (flags << 4) | static_cast<UInt32>(c - 'A' + 10);
else if (c >= 'a' && c <= 'f')
flags = (flags << 4) | static_cast<UInt32>(c - 'a' + 10);
else break;
}
fmt.mFormatFlags = flags;
}
if (*p == '#') {
++p;
while (isdigit(*p))
fmt.mFramesPerPacket = 10 * fmt.mFramesPerPacket + static_cast<UInt32>(*p++ - '0');
}
if (*p == ':') {
++p;
fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsPacked);
if (*p == 'L')
fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsAlignedHigh);
else if (*p == 'H')
fmt.mFormatFlags |= kLinearPCMFormatFlagIsAlignedHigh;
else
goto Bail;
++p;
UInt32 bytesPerFrame = 0;
while (isdigit(*p))
bytesPerFrame = 10 * bytesPerFrame + static_cast<UInt32>(*p++ - '0');
fmt.mBytesPerFrame = fmt.mBytesPerPacket = bytesPerFrame;
}
if (*p == ',') {
++p;
int ch = 0;
while (isdigit(*p))
ch = 10 * ch + (*p++ - '0');
fmt.mChannelsPerFrame = static_cast<UInt32>(ch);
if (*p == 'D') {
++p;
if (fmt.mFormatID != kAudioFormatLinearPCM) {
fprintf(stderr, "non-interleaved flag invalid for non-PCM formats\n");
goto Bail;
}
fmt.mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
} else {
if (*p == 'I') ++p; // default
if (fmt.mFormatID == kAudioFormatLinearPCM)
fmt.mBytesPerPacket = fmt.mBytesPerFrame *= static_cast<UInt32>(ch);
}
}
if (*p != '\0') {
fprintf(stderr, "extra characters at end of format string: %s\n", p);
goto Bail;
}
return true;
Bail:
fprintf(stderr, "Invalid format string: %s\n", inTextDesc);
fprintf(stderr, "Syntax of format strings is: \n");
return false;
}
const char *CAStreamBasicDescription::sTextParsingUsageString =
"format[@sample_rate_hz][/format_flags][#frames_per_packet][:LHbytesPerFrame][,channelsDI].\n"
"Format for PCM is [-][BE|LE]{F|I|UI}{bitdepth}; else a 4-char format code (e.g. aac, alac).\n";

View File

@ -1,448 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#ifndef __CAStreamBasicDescription_h__
#define __CAStreamBasicDescription_h__
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#include <CoreFoundation/CoreFoundation.h>
#else
#include "CoreAudioTypes.h"
#include "CoreFoundation.h"
#endif
#include "CADebugMacros.h"
#include <string.h> // for memset, memcpy
#include <stdio.h> // for FILE *
#pragma mark This file needs to compile on more earlier versions of the OS, so please keep that in mind when editing it
#ifndef ASBD_STRICT_EQUALITY
#define ASBD_STRICT_EQUALITY 0
#endif
#if __GNUC__ && ASBD_STRICT_EQUALITY
// not turning on the deprecation just yet
#define ASBD_EQUALITY_DEPRECATED __attribute__((deprecated("This method uses a possibly surprising wildcard comparison (i.e. 0 channels == 1 channel)")))
#else
#define ASBD_EQUALITY_DEPRECATED
#endif
#ifndef CA_CANONICAL_DEPRECATED
#define CA_CANONICAL_DEPRECATED
#endif
extern char *CAStringForOSType (OSType t, char *writeLocation, size_t bufsize);
// define Leopard specific symbols for backward compatibility if applicable
#if COREAUDIOTYPES_VERSION < 1050
typedef Float32 AudioSampleType;
enum { kAudioFormatFlagsCanonical = kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked };
#endif
#if COREAUDIOTYPES_VERSION < 1051
typedef Float32 AudioUnitSampleType;
enum {
kLinearPCMFormatFlagsSampleFractionShift = 7,
kLinearPCMFormatFlagsSampleFractionMask = (0x3F << kLinearPCMFormatFlagsSampleFractionShift),
};
#endif
// define the IsMixable format flag for all versions of the system
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3)
enum { kIsNonMixableFlag = kAudioFormatFlagIsNonMixable };
#else
enum { kIsNonMixableFlag = (1L << 6) };
#endif
//=============================================================================
// CAStreamBasicDescription
//
// This is a wrapper class for the AudioStreamBasicDescription struct.
// It adds a number of convenience routines, but otherwise adds nothing
// to the footprint of the original struct.
//=============================================================================
class CAStreamBasicDescription :
public AudioStreamBasicDescription
{
// Constants
public:
static const AudioStreamBasicDescription sEmpty;
enum CommonPCMFormat {
kPCMFormatOther = 0,
kPCMFormatFloat32 = 1,
kPCMFormatInt16 = 2,
kPCMFormatFixed824 = 3,
kPCMFormatFloat64 = 4,
kPCMFormatInt32 = 5
};
// options for IsEquivalent
enum {
kCompareDefault = 0,
kCompareUsingWildcards = 1 << 0, // treats fields with values of 0 as wildcards.
// too liberal if you need to represent 0 channels.
kCompareForHardware = 1 << 1, // formats are hardware formats (IsNonMixable flag is significant).
kCompareForHardwareUsingWildcards = kCompareForHardware + kCompareUsingWildcards // for convenience
};
typedef UInt32 ComparisonOptions;
// Construction/Destruction
public:
CAStreamBasicDescription();
CAStreamBasicDescription(const AudioStreamBasicDescription &desc);
CAStreamBasicDescription( double inSampleRate, UInt32 inFormatID,
UInt32 inBytesPerPacket, UInt32 inFramesPerPacket,
UInt32 inBytesPerFrame, UInt32 inChannelsPerFrame,
UInt32 inBitsPerChannel, UInt32 inFormatFlags);
CAStreamBasicDescription( double inSampleRate, UInt32 inNumChannels, CommonPCMFormat pcmf, bool inIsInterleaved) {
unsigned wordsize;
mSampleRate = inSampleRate;
mFormatID = kAudioFormatLinearPCM;
mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
mFramesPerPacket = 1;
mChannelsPerFrame = inNumChannels;
mBytesPerFrame = mBytesPerPacket = 0;
mReserved = 0;
switch (pcmf) {
default:
return;
case kPCMFormatFloat32:
wordsize = 4;
mFormatFlags |= kAudioFormatFlagIsFloat;
break;
case kPCMFormatFloat64:
wordsize = 8;
mFormatFlags |= kAudioFormatFlagIsFloat;
break;
case kPCMFormatInt16:
wordsize = 2;
mFormatFlags |= kAudioFormatFlagIsSignedInteger;
break;
case kPCMFormatInt32:
wordsize = 4;
mFormatFlags |= kAudioFormatFlagIsSignedInteger;
break;
case kPCMFormatFixed824:
wordsize = 4;
mFormatFlags |= kAudioFormatFlagIsSignedInteger | (24 << kLinearPCMFormatFlagsSampleFractionShift);
break;
}
mBitsPerChannel = wordsize * 8;
if (inIsInterleaved)
mBytesPerFrame = mBytesPerPacket = wordsize * inNumChannels;
else {
mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
mBytesPerFrame = mBytesPerPacket = wordsize;
}
}
// Assignment
CAStreamBasicDescription& operator=(const AudioStreamBasicDescription& v) { SetFrom(v); return *this; }
void SetFrom(const AudioStreamBasicDescription &desc)
{
memcpy(this, &desc, sizeof(AudioStreamBasicDescription));
}
bool FromText(const char *inTextDesc) { return FromText(inTextDesc, *this); }
static bool FromText(const char *inTextDesc, AudioStreamBasicDescription &outDesc);
// return true if parsing was successful
static const char *sTextParsingUsageString;
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//
// interrogation
bool IsPCM() const { return mFormatID == kAudioFormatLinearPCM; }
bool PackednessIsSignificant() const
{
Assert(IsPCM(), "PackednessIsSignificant only applies for PCM");
return (SampleWordSize() << 3) != mBitsPerChannel;
}
bool AlignmentIsSignificant() const
{
return PackednessIsSignificant() || (mBitsPerChannel & 7) != 0;
}
bool IsInterleaved() const
{
return !(mFormatFlags & kAudioFormatFlagIsNonInterleaved);
}
bool IsSignedInteger() const
{
return IsPCM() && (mFormatFlags & kAudioFormatFlagIsSignedInteger);
}
bool IsFloat() const
{
return IsPCM() && (mFormatFlags & kAudioFormatFlagIsFloat);
}
bool IsNativeEndian() const
{
return (mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian;
}
// for sanity with interleaved/deinterleaved possibilities, never access mChannelsPerFrame, use these:
UInt32 NumberInterleavedChannels() const { return IsInterleaved() ? mChannelsPerFrame : 1; }
UInt32 NumberChannelStreams() const { return IsInterleaved() ? 1 : mChannelsPerFrame; }
UInt32 NumberChannels() const { return mChannelsPerFrame; }
UInt32 SampleWordSize() const {
return (mBytesPerFrame > 0 && NumberInterleavedChannels()) ? mBytesPerFrame / NumberInterleavedChannels() : 0;
}
UInt32 FramesToBytes(UInt32 nframes) const { return nframes * mBytesPerFrame; }
UInt32 BytesToFrames(UInt32 nbytes) const {
Assert(mBytesPerFrame > 0, "bytesPerFrame must be > 0 in BytesToFrames");
return nbytes / mBytesPerFrame;
}
bool SameChannelsAndInterleaving(const CAStreamBasicDescription &a) const
{
return this->NumberChannels() == a.NumberChannels() && this->IsInterleaved() == a.IsInterleaved();
}
bool IdentifyCommonPCMFormat(CommonPCMFormat &outFormat, bool *outIsInterleaved=NULL) const
{ // return true if it's a valid PCM format.
outFormat = kPCMFormatOther;
// trap out patently invalid formats.
if (mFormatID != kAudioFormatLinearPCM || mFramesPerPacket != 1 || mBytesPerFrame != mBytesPerPacket || mBitsPerChannel/8 > mBytesPerFrame || mChannelsPerFrame == 0)
return false;
bool interleaved = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
if (outIsInterleaved != NULL) *outIsInterleaved = interleaved;
unsigned wordsize = mBytesPerFrame;
if (interleaved) {
if (wordsize % mChannelsPerFrame != 0) return false;
wordsize /= mChannelsPerFrame;
}
if ((mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian
&& wordsize * 8 == mBitsPerChannel) {
// packed and native endian, good
if (mFormatFlags & kLinearPCMFormatFlagIsFloat) {
// float: reject nonsense bits
if (mFormatFlags & (kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagsSampleFractionMask))
return false;
if (wordsize == 4)
outFormat = kPCMFormatFloat32;
if (wordsize == 8)
outFormat = kPCMFormatFloat64;
} else if (mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) {
// signed int
unsigned fracbits = (mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
if (wordsize == 4 && fracbits == 24)
outFormat = kPCMFormatFixed824;
else if (wordsize == 4 && fracbits == 0)
outFormat = kPCMFormatInt32;
else if (wordsize == 2 && fracbits == 0)
outFormat = kPCMFormatInt16;
}
}
return true;
}
bool IsCommonFloat32(bool *outIsInterleaved=NULL) const {
CommonPCMFormat fmt;
return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFloat32;
}
bool IsCommonFloat64(bool *outIsInterleaved=NULL) const {
CommonPCMFormat fmt;
return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFloat64;
}
bool IsCommonFixed824(bool *outIsInterleaved=NULL) const {
CommonPCMFormat fmt;
return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFixed824;
}
bool IsCommonInt16(bool *outIsInterleaved=NULL) const {
CommonPCMFormat fmt;
return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatInt16;
}
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//
// manipulation
CA_CANONICAL_DEPRECATED
void SetCanonical(UInt32 nChannels, bool interleaved)
// note: leaves sample rate untouched
{
mFormatID = kAudioFormatLinearPCM;
UInt32 sampleSize = SizeOf32(AudioSampleType);
mFormatFlags = kAudioFormatFlagsCanonical;
mBitsPerChannel = 8 * sampleSize;
mChannelsPerFrame = nChannels;
mFramesPerPacket = 1;
if (interleaved)
mBytesPerPacket = mBytesPerFrame = nChannels * sampleSize;
else {
mBytesPerPacket = mBytesPerFrame = sampleSize;
mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
}
}
CA_CANONICAL_DEPRECATED
bool IsCanonical() const
{
if (mFormatID != kAudioFormatLinearPCM) return false;
UInt32 reqFormatFlags;
UInt32 flagsMask = (kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagsSampleFractionMask);
bool interleaved = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
unsigned sampleSize = SizeOf32(AudioSampleType);
reqFormatFlags = kAudioFormatFlagsCanonical;
UInt32 reqFrameSize = interleaved ? (mChannelsPerFrame * sampleSize) : sampleSize;
return ((mFormatFlags & flagsMask) == reqFormatFlags
&& mBitsPerChannel == 8 * sampleSize
&& mFramesPerPacket == 1
&& mBytesPerFrame == reqFrameSize
&& mBytesPerPacket == reqFrameSize);
}
CA_CANONICAL_DEPRECATED
void SetAUCanonical(UInt32 nChannels, bool interleaved)
{
mFormatID = kAudioFormatLinearPCM;
#if CA_PREFER_FIXED_POINT
mFormatFlags = kAudioFormatFlagsCanonical | (kAudioUnitSampleFractionBits << kLinearPCMFormatFlagsSampleFractionShift);
#else
mFormatFlags = kAudioFormatFlagsCanonical;
#endif
mChannelsPerFrame = nChannels;
mFramesPerPacket = 1;
mBitsPerChannel = 8 * SizeOf32(AudioUnitSampleType);
if (interleaved)
mBytesPerPacket = mBytesPerFrame = nChannels * SizeOf32(AudioUnitSampleType);
else {
mBytesPerPacket = mBytesPerFrame = SizeOf32(AudioUnitSampleType);
mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
}
}
void ChangeNumberChannels(UInt32 nChannels, bool interleaved)
// alter an existing format
{
Assert(IsPCM(), "ChangeNumberChannels only works for PCM formats");
UInt32 wordSize = SampleWordSize(); // get this before changing ANYTHING
if (wordSize == 0)
wordSize = (mBitsPerChannel + 7) / 8;
mChannelsPerFrame = nChannels;
mFramesPerPacket = 1;
if (interleaved) {
mBytesPerPacket = mBytesPerFrame = nChannels * wordSize;
mFormatFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonInterleaved);
} else {
mBytesPerPacket = mBytesPerFrame = wordSize;
mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
}
}
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//
// other
// IsEqual: Deprecated because of widespread errors due to the default wildcarding behavior.
ASBD_EQUALITY_DEPRECATED
bool IsEqual(const AudioStreamBasicDescription &other) const;
bool IsEqual(const AudioStreamBasicDescription &other, bool interpretingWildcards) const;
// IsExactlyEqual: bit-for-bit. usually unnecessarily strict.
static bool IsExactlyEqual(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y);
// IsEquivalent: Returns whether the two formats are functionally the same, i.e. if one could
// be correctly passed as the other without an AudioConverter.
static bool IsEquivalent(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y) { return IsEquivalent(x, y, kCompareDefault); }
static bool IsEquivalent(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y, ComparisonOptions comparisonOptions);
// Member versions of IsExactlyEqual and IsEquivalent.
bool IsExactlyEqual(const AudioStreamBasicDescription &other) const { return IsExactlyEqual(*this, other); }
bool IsEquivalent(const AudioStreamBasicDescription &other) const { return IsEquivalent(*this, other); }
bool IsEquivalent(const AudioStreamBasicDescription &other, ComparisonOptions comparisonOptions) const { return IsEquivalent(*this, other, comparisonOptions); }
void Print() const {
Print (stdout);
}
void Print(FILE* file) const {
PrintFormat (file, "", "AudioStreamBasicDescription:");
}
void PrintFormat(FILE *f, const char *indent, const char *name) const {
char buf[256];
fprintf(f, "%s%s %s\n", indent, name, AsString(buf, sizeof(buf)));
}
void PrintFormat2(FILE *f, const char *indent, const char *name) const { // no trailing newline
char buf[256];
fprintf(f, "%s%s %s", indent, name, AsString(buf, sizeof(buf)));
}
char * AsString(char *buf, size_t bufsize, bool brief=false) const;
static void Print (const AudioStreamBasicDescription &inDesc)
{
CAStreamBasicDescription desc(inDesc);
desc.Print ();
}
OSStatus Save(CFPropertyListRef *outData) const;
OSStatus Restore(CFPropertyListRef &inData);
// Operations
static bool IsMixable(const AudioStreamBasicDescription& inDescription) { return (inDescription.mFormatID == kAudioFormatLinearPCM) && ((inDescription.mFormatFlags & kIsNonMixableFlag) == 0); }
CA_CANONICAL_DEPRECATED
static void NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription);
CA_CANONICAL_DEPRECATED
static void NormalizeLinearPCMFormat(bool inNativeEndian, AudioStreamBasicDescription& ioDescription);
static void VirtualizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription);
static void VirtualizeLinearPCMFormat(bool inNativeEndian, AudioStreamBasicDescription& ioDescription);
static void ResetFormat(AudioStreamBasicDescription& ioDescription);
static void FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription);
static void GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, UInt32 inMaxNameLength, bool inAbbreviate, bool inIncludeSampleRate = false);
#if CoreAudio_Debug
static void PrintToLog(const AudioStreamBasicDescription& inDesc);
#endif
UInt32 GetRegularizedFormatFlags(bool forHardware) const;
private:
static bool EquivalentFormatFlags(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y, bool forHardware, bool usingWildcards);
};
#define CAStreamBasicDescription_EmptyInit 0.0, 0, 0, 0, 0, 0, 0, 0, 0
#define CAStreamBasicDescription_Empty { CAStreamBasicDescription_EmptyInit }
// operator== is deprecated because it uses the deprecated IsEqual(other, true).
bool operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y);
ASBD_EQUALITY_DEPRECATED bool operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y);
#if TARGET_OS_MAC || (TARGET_OS_WIN32 && (_MSC_VER > 600))
ASBD_EQUALITY_DEPRECATED inline bool operator!=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x == y); }
ASBD_EQUALITY_DEPRECATED inline bool operator<=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return (x < y) || (x == y); }
ASBD_EQUALITY_DEPRECATED inline bool operator>=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x < y); }
ASBD_EQUALITY_DEPRECATED inline bool operator>(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !((x < y) || (x == y)); }
#endif
bool SanityCheck(const AudioStreamBasicDescription& x);
#endif // __CAStreamBasicDescription_h__

View File

@ -1,195 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#ifndef __CAThreadSafeList_h__
#define __CAThreadSafeList_h__
#include "CAAtomicStack.h"
// linked list of T's
// T must define operator ==
template <class T>
class TThreadSafeList {
private:
enum EEventType { kAdd, kRemove, kClear };
class Node {
public:
Node * mNext;
EEventType mEventType;
T mObject;
Node *& next() { return mNext; }
};
public:
class iterator {
public:
iterator() { }
iterator(Node *n) : mNode(n) { }
bool operator == (const iterator &other) const { return this->mNode == other.mNode; }
bool operator != (const iterator &other) const { return this->mNode != other.mNode; }
T & operator * () const { return mNode->mObject; }
iterator & operator ++ () { mNode = mNode->next(); return *this; } // preincrement
iterator operator ++ (int) { iterator tmp = *this; mNode = mNode->next(); return tmp; } // postincrement
private:
Node * mNode;
};
TThreadSafeList() { }
~TThreadSafeList()
{
mActiveList.free_all();
mPendingList.free_all();
mFreeList.free_all();
}
// These may be called on any thread
void deferred_add(const T &obj) // can be called on any thread
{
Node *node = AllocNode();
node->mEventType = kAdd;
node->mObject = obj;
mPendingList.push_atomic(node);
//mPendingList.dump("pending after add");
}
void deferred_remove(const T &obj) // can be called on any thread
{
Node *node = AllocNode();
node->mEventType = kRemove;
node->mObject = obj;
mPendingList.push_atomic(node);
//mPendingList.dump("pending after remove");
}
void deferred_clear() // can be called on any thread
{
Node *node = AllocNode();
node->mEventType = kClear;
mPendingList.push_atomic(node);
}
// These must be called from only one thread
void update() // must only be called from one thread
{
NodeStack reversed;
Node *event, *node, *next;
bool workDone = false;
// reverse the events so they are in order
event = mPendingList.pop_all();
while (event != NULL) {
next = event->mNext;
reversed.push_NA(event);
event = next;
workDone = true;
}
if (workDone) {
//reversed.dump("pending popped");
//mActiveList.dump("active before update");
// now process them
while ((event = reversed.pop_NA()) != NULL) {
switch (event->mEventType) {
case kAdd:
{
Node **pnode;
bool needToInsert = true;
for (pnode = mActiveList.phead(); *pnode != NULL; pnode = &node->mNext) {
node = *pnode;
if (node->mObject == event->mObject) {
//printf("already active!!!\n");
FreeNode(event);
needToInsert = false;
break;
}
}
if (needToInsert) {
// link the new event in at the end of the active list
*pnode = event;
event->mNext = NULL;
}
}
break;
case kRemove:
// find matching node in the active list, remove it
for (Node **pnode = mActiveList.phead(); *pnode != NULL; ) {
node = *pnode;
if (node->mObject == event->mObject) {
*pnode = node->mNext; // remove from linked list
FreeNode(node);
break;
}
pnode = &node->mNext;
}
// dispose the request node
FreeNode(event);
break;
case kClear:
for (node = mActiveList.head(); node != NULL; ) {
next = node->mNext;
FreeNode(node);
node = next;
}
FreeNode(event);
break;
default:
//printf("invalid node type %d!\n", event->mEventType);
break;
}
}
//mActiveList.dump("active after update");
}
}
iterator begin() const {
//mActiveList.dump("active at begin");
return iterator(mActiveList.head());
}
iterator end() const { return iterator(NULL); }
private:
Node * AllocNode()
{
Node *node = mFreeList.pop_atomic();
if (node == NULL)
node = (Node *)CA_malloc(sizeof(Node));
return node;
}
void FreeNode(Node *node)
{
mFreeList.push_atomic(node);
}
private:
class NodeStack : public TAtomicStack<Node> {
public:
void free_all() {
Node *node;
while ((node = this->pop_NA()) != NULL)
free(node);
}
Node ** phead() { return &this->mHead; }
Node * head() const { return this->mHead; }
};
NodeStack mActiveList; // what's actually in the container - only accessed on one thread
NodeStack mPendingList; // add or remove requests - threadsafe
NodeStack mFreeList; // free nodes for reuse - threadsafe
};
#endif // __CAThreadSafeList_h__

View File

@ -1,157 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#include "CAVectorUnit.h"
#if !TARGET_OS_WIN32
#include <sys/sysctl.h>
#elif HAS_IPP
#include "ippdefs.h"
#include "ippcore.h"
#endif
int gCAVectorUnitType = kVecUninitialized;
#if TARGET_OS_WIN32
// Use cpuid to check if SSE2 is available.
// Before calling this function make sure cpuid is available
static SInt32 IsSSE2Available()
{
int return_value;
{
int r_edx;
_asm
{
mov eax, 0x01
cpuid
mov r_edx, edx
}
return_value = (r_edx >> 26) & 0x1;
}
return return_value;
}
// Use cpuid to check if SSE3 is available.
// Before calling this function make sure cpuid is available
static SInt32 IsSSE3Available()
{
SInt32 return_value;
{
SInt32 r_ecx;
_asm
{
mov eax, 0x01
cpuid
mov r_ecx, ecx
}
return_value = r_ecx & 0x1;
}
return return_value;
}
// Return true if the cpuid instruction is available.
// The cpuid instruction is available if bit 21 in the EFLAGS register can be changed
// This function may not work on Intel CPUs prior to Pentium (didn't test)
static bool IsCpuidAvailable()
{
SInt32 return_value = 0x0;
_asm{
pushfd ; //push original EFLAGS
pop eax ; //get original EFLAGS
mov ecx, eax ; //save original EFLAGS
xor eax, 200000h ; //flip ID bit in EFLAGS
push eax ; //save new EFLAGS value on stack
popfd ; //replace current EFLAGS value
pushfd ; //get new EFLAGS
pop eax ; //store new EFLAGS in EAX
xor eax, ecx ;
je end_cpuid_identify ; //can't toggle ID bit
mov return_value, 0x1;
end_cpuid_identify:
nop;
}
return return_value;
}
#endif
SInt32 CAVectorUnit_Examine()
{
int result = kVecNone;
#if TARGET_OS_WIN32
#if HAS_IPP
// Initialize the static IPP library! This needs to be done before
// any IPP function calls, otherwise we may have a performance penalty
int status = ippStaticInit();
if ( status == ippStsNonIntelCpu )
{
IppCpuType cpuType = ippGetCpuType();
if ( cpuType >= ippCpuSSE || cpuType <= ippCpuSSE42 )
ippStaticInitCpu( cpuType );
}
#endif
{
// On Windows we use cpuid to detect the vector unit because it works on Intel and AMD.
// The IPP library does not detect SSE on AMD processors.
if (IsCpuidAvailable())
{
if(IsSSE3Available())
{
result = kVecSSE3;
}
else if(IsSSE2Available())
{
result = kVecSSE2;
}
}
}
#elif TARGET_OS_MAC
#if DEBUG
if (getenv("CA_NoVector")) {
fprintf(stderr, "CA_NoVector set; Vector unit optimized routines will be bypassed\n");
return result;
}
else
#endif
{
#if (TARGET_CPU_PPC || TARGET_CPU_PPC64)
int sels[2] = { CTL_HW, HW_VECTORUNIT };
int vType = 0; //0 == scalar only
size_t length = sizeof(vType);
int error = sysctl(sels, 2, &vType, &length, NULL, 0);
if (!error && vType > 0)
result = kVecAltivec;
#elif (TARGET_CPU_X86 || TARGET_CPU_X86_64)
static const struct { const char* kName; const int kVectype; } kStringVectypes[] = {
{ "hw.optional.avx1_0", kVecAVX1 }, { "hw.optional.sse3", kVecSSE3 }, { "hw.optional.sse2", kVecSSE2 }
};
static const size_t kNumStringVectypes = sizeof(kStringVectypes)/sizeof(kStringVectypes[0]);
int i = 0, answer = 0;
while(i != kNumStringVectypes)
{
size_t length = sizeof(answer);
int error = sysctlbyname(kStringVectypes[i].kName, &answer, &length, NULL, 0);
if (!error && answer)
{
result = kStringVectypes[i].kVectype;
break;
}
++i;
};
#elif CA_ARM_NEON
result = kVecNeon;
#endif
}
#endif
gCAVectorUnitType = result;
return result;
}

View File

@ -1,63 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#ifndef __CAVectorUnit_h__
#define __CAVectorUnit_h__
#include <TargetConditionals.h>
#include "CAVectorUnitTypes.h"
#include <stdlib.h>
#include <stdio.h>
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreFoundation/CFBase.h>
#else
#include "CFBase.h"
#endif
// Unify checks for vector units.
// Allow setting an environment variable "CA_NoVector" to turn off vectorized code at runtime (very useful for performance testing).
extern int gCAVectorUnitType;
#ifdef __cplusplus
extern "C" {
#endif
extern SInt32 CAVectorUnit_Examine(); // expensive. use GetType() for lazy initialization and caching.
static inline SInt32 CAVectorUnit_GetType()
{
int x = gCAVectorUnitType;
return (x != kVecUninitialized) ? x : CAVectorUnit_Examine();
}
static inline Boolean CAVectorUnit_HasVectorUnit()
{
return CAVectorUnit_GetType() > kVecNone;
}
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
class CAVectorUnit {
public:
static SInt32 GetVectorUnitType() { return CAVectorUnit_GetType(); }
static bool HasVectorUnit() { return GetVectorUnitType() > kVecNone; }
static bool HasAltivec() { return GetVectorUnitType() == kVecAltivec; }
static bool HasSSE2() { return GetVectorUnitType() >= kVecSSE2; }
static bool HasSSE3() { return GetVectorUnitType() >= kVecSSE3; }
static bool HasAVX1() { return GetVectorUnitType() >= kVecAVX1; }
static bool HasNeon() { return GetVectorUnitType() == kVecNeon; }
};
#endif
#endif // __CAVectorUnit_h__

View File

@ -1,22 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#ifndef __CAVectorUnitTypes_h__
#define __CAVectorUnitTypes_h__
enum {
kVecUninitialized = -1,
kVecNone = 0,
kVecAltivec = 1,
kVecSSE2 = 100,
kVecSSE3 = 101,
kVecAVX1 = 110,
kVecNeon = 200
};
#endif

View File

@ -1,50 +0,0 @@
/*
File: CAXException.cpp
Abstract:
Version: 1.2
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2010 Apple Inc. All Rights Reserved.
*/
#include "CAXException.h"
CAXException::WarningHandler CAXException::sWarningHandler = NULL;

View File

@ -1,323 +0,0 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
Part of Core Audio Public Utility Classes
*/
#ifndef __CAXException_h__
#define __CAXException_h__
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreFoundation/CoreFoundation.h>
#else
#include <ConditionalMacros.h>
#include <CoreFoundation.h>
#endif
#include "CADebugMacros.h"
#include <ctype.h>
//#include <stdio.h>
#include <string.h>
class CAX4CCString {
public:
CAX4CCString(OSStatus error) {
// see if it appears to be a 4-char-code
UInt32 beErr = CFSwapInt32HostToBig(error);
char *str = mStr;
memcpy(str + 1, &beErr, 4);
if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) {
str[0] = str[5] = '\'';
str[6] = '\0';
} else if (error > -200000 && error < 200000)
// no, format it as an integer
snprintf(str, sizeof(mStr), "%d", (int)error);
else
snprintf(str, sizeof(mStr), "0x%x", (int)error);
}
const char *get() const { return mStr; }
operator const char *() const { return mStr; }
private:
char mStr[16];
};
class CAX4CCStringNoQuote {
public:
CAX4CCStringNoQuote(OSStatus error) {
// see if it appears to be a 4-char-code
UInt32 beErr = CFSwapInt32HostToBig(error);
char *str = mStr;
memcpy(str, &beErr, 4);
if (isprint(str[0]) && isprint(str[1]) && isprint(str[2]) && isprint(str[3])) {
str[4] = '\0';
} else if (error > -200000 && error < 200000)
// no, format it as an integer
snprintf(str, sizeof(mStr), "%d", (int)error);
else
snprintf(str, sizeof(mStr), "0x%x", (int)error);
}
const char *get() const { return mStr; }
operator const char *() const { return mStr; }
private:
char mStr[16];
};
// An extended exception class that includes the name of the failed operation
class CAXException {
public:
CAXException(const char *operation, OSStatus err) :
mError(err)
{
if (operation == NULL)
mOperation[0] = '\0';
else if (strlen(operation) >= sizeof(mOperation)) {
memcpy(mOperation, operation, sizeof(mOperation) - 1);
mOperation[sizeof(mOperation) - 1] = '\0';
} else
strlcpy(mOperation, operation, sizeof(mOperation));
}
char *FormatError(char *str, size_t strsize) const
{
return FormatError(str, strsize, mError);
}
char mOperation[256];
const OSStatus mError;
// -------------------------------------------------
typedef void (*WarningHandler)(const char *msg, OSStatus err);
static char *FormatError(char *str, size_t strsize, OSStatus error)
{
strlcpy(str, CAX4CCString(error), strsize);
return str;
}
static void Warning(const char *s, OSStatus error)
{
if (sWarningHandler)
(*sWarningHandler)(s, error);
}
static void SetWarningHandler(WarningHandler f) { sWarningHandler = f; }
private:
static WarningHandler sWarningHandler;
};
#if DEBUG || CoreAudio_Debug
#define XThrowIfError(error, operation) \
do { \
OSStatus __err = error; \
if (__err) { \
DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), operation);\
__THROW_STOP; \
throw CAXException(operation, __err); \
} \
} while (0)
#define XThrowIf(condition, error, operation) \
do { \
if (condition) { \
OSStatus __err = error; \
DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), operation);\
__THROW_STOP; \
throw CAXException(operation, __err); \
} \
} while (0)
#define XRequireNoError(error, label) \
do { \
OSStatus __err = error; \
if (__err) { \
DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), #error);\
STOP; \
goto label; \
} \
} while (0)
#define XAssert(assertion) \
do { \
if (!(assertion)) { \
DebugMessageN3("%s:%d: error: failed assertion: %s", __FILE__, __LINE__, #assertion); \
__ASSERT_STOP; \
} \
} while (0)
#define XAssertNoError(error) \
do { \
OSStatus __err = error; \
if (__err) { \
DebugMessageN4("%s:%d: error %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), #error);\
__ASSERT_STOP; \
} \
} while (0)
#define ca_require_noerr(errorCode, exceptionLabel) \
do \
{ \
int evalOnceErrorCode = (errorCode); \
if ( __builtin_expect(0 != evalOnceErrorCode, 0) ) \
{ \
DebugMessageN5("ca_require_noerr: [%s, %d] (goto %s;) %s:%d", \
#errorCode, evalOnceErrorCode, \
#exceptionLabel, \
__FILE__, \
__LINE__); \
goto exceptionLabel; \
} \
} while ( 0 )
#define ca_verify_noerr(errorCode) \
do \
{ \
int evalOnceErrorCode = (errorCode); \
if ( __builtin_expect(0 != evalOnceErrorCode, 0) ) \
{ \
DebugMessageN4("ca_verify_noerr: [%s, %d] %s:%d", \
#errorCode, evalOnceErrorCode, \
__FILE__, \
__LINE__); \
} \
} while ( 0 )
#define ca_debug_string(message) \
do \
{ \
DebugMessageN3("ca_debug_string: %s %s:%d", \
message, \
__FILE__, \
__LINE__); \
} while ( 0 )
#define ca_verify(assertion) \
do \
{ \
if ( __builtin_expect(!(assertion), 0) ) \
{ \
DebugMessageN3("ca_verify: %s %s:%d", \
#assertion, \
__FILE__, \
__LINE__); \
} \
} while ( 0 )
#define ca_require(assertion, exceptionLabel) \
do \
{ \
if ( __builtin_expect(!(assertion), 0) ) \
{ \
DebugMessageN4("ca_require: %s %s %s:%d", \
#assertion, \
#exceptionLabel, \
__FILE__, \
__LINE__); \
goto exceptionLabel; \
} \
} while ( 0 )
#define ca_check(assertion) \
do \
{ \
if ( __builtin_expect(!(assertion), 0) ) \
{ \
DebugMessageN3("ca_check: %s %s:%d", \
#assertion, \
__FILE__, \
__LINE__); \
} \
} while ( 0 )
#else
#define XThrowIfError(error, operation) \
do { \
OSStatus __err = error; \
if (__err) { \
throw CAXException(operation, __err); \
} \
} while (0)
#define XThrowIf(condition, error, operation) \
do { \
if (condition) { \
OSStatus __err = error; \
throw CAXException(operation, __err); \
} \
} while (0)
#define XRequireNoError(error, label) \
do { \
OSStatus __err = error; \
if (__err) { \
goto label; \
} \
} while (0)
#define XAssert(assertion) \
do { \
if (!(assertion)) { \
} \
} while (0)
#define XAssertNoError(error) \
do { \
/*OSStatus __err =*/ error; \
} while (0)
#define ca_require_noerr(errorCode, exceptionLabel) \
do \
{ \
if ( __builtin_expect(0 != (errorCode), 0) ) \
{ \
goto exceptionLabel; \
} \
} while ( 0 )
#define ca_verify_noerr(errorCode) \
do \
{ \
if ( 0 != (errorCode) ) \
{ \
} \
} while ( 0 )
#define ca_debug_string(message)
#define ca_verify(assertion) \
do \
{ \
if ( !(assertion) ) \
{ \
} \
} while ( 0 )
#define ca_require(assertion, exceptionLabel) \
do \
{ \
if ( __builtin_expect(!(assertion), 0) ) \
{ \
goto exceptionLabel; \
} \
} while ( 0 )
#define ca_check(assertion) \
do \
{ \
if ( !(assertion) ) \
{ \
} \
} while ( 0 )
#endif
#define XThrow(error, operation) XThrowIf(true, error, operation)
#define XThrowIfErr(error) XThrowIfError(error, #error)
#endif // __CAXException_h__