#include "oalSource.h"
#include "oalBuffer.h"
#include "oalImp.h"
#define LOG_PLAYBACK 0
#define LOG_VERBOSE 0
#define LOG_BUFFER_QUEUEING 0
#define LOG_DOPPLER 0
#define LOG_MESSAGE_QUEUE 0
#define CALCULATE_POSITION 1 // this should be true except for testing
#define MIXER_PARAMS_UNDEFINED 0
#if MIXER_PARAMS_UNDEFINED
typedef struct MixerDistanceParams {
Float32 mReferenceDistance;
Float32 mMaxDistance;
Float32 mMaxAttenuation;
} MixerDistanceParams;
enum {
kAudioUnitProperty_3DMixerDistanceParams = 3010
};
#endif
inline bool zapBadness(Float32& inValue)
{
Float32 absInValue = fabs(inValue);
if (!(absInValue > 1e-15 && absInValue < 1e15)){
inValue = 0.0;
return true;
}
return false;
}
inline bool zapBadnessForDopplerShift(Float32& inValue)
{
Float32 absInValue = fabs(inValue);
if (isnan(inValue) || (inValue == 0.0))
inValue = 1.0;
else if (absInValue > 1e15)
inValue = 16.0;
else if (absInValue < 1e-15)
inValue = .125;
return false;
}
#pragma mark ***** PUBLIC *****
OALSource::OALSource (ALuint inSelfToken, OALContext *inOwningContext)
: mSelfToken (inSelfToken),
mSafeForDeletion(false),
mOwningContext(inOwningContext),
mIsSuspended(false),
mCalculateDistance(true),
mResetBusFormat(true),
mResetBus(false),
mResetPitch(true),
mBufferQueueActive(NULL),
mBufferQueueInactive(NULL),
mQueueLength(0),
mBuffersQueuedForClear(0),
mCurrentBufferIndex(0),
mQueueIsProcessed(true),
mInUseFlag(0),
mSourceLock("OAL:SourceLock"),
mCurrentPlayBus (kSourceNeedsBus),
mACMap(NULL),
mOutputSilence(false),
mLooping(AL_FALSE),
mSourceRelative(AL_FALSE),
mSourceType(AL_UNDETERMINED),
mConeInnerAngle(360.0),
mConeOuterAngle(360.0),
mConeOuterGain(0.0),
mConeGainScaler(1.0),
mAttenuationGainScaler(1.0),
mReadIndex(0.0),
mTempSourceStorageBufferSize(2048), mState(AL_INITIAL),
mGain(1.0),
mPitch(1.0), mDopplerScaler(1.0),
mRollOffFactor(kDefaultRolloff),
mReferenceDistance(kDefaultReferenceDistance),
mMaxDistance(kDefaultMaximumDistance), mMinGain(0.0),
mMaxGain(1.0),
mRampState(kNoRamping),
mBufferCountToUnqueueInPostRender(0),
mTransitioningToFlushQ(false),
mASAReverbSendLevel(0.0),
mASAOcclusion(0.0),
mASAObstruction(0.0),
mRogerBeepNode(0),
mRogerBeepAU(0),
mASARogerBeepEnable(false),
mASARogerBeepOn(true), mASARogerBeepGain(0.0),
mASARogerBeepSensitivity(0),
mASARogerBeepType(0),
mASARogerBeepPreset(0),
mDistortionNode(0),
mDistortionAU(0),
mASADistortionEnable(false),
mASADistortionOn(true), mASADistortionMix(0.0),
mASADistortionType(0),
mASADistortionPreset(0),
mSourceNotifications(NULL)
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::OALSource() - OALSource = %ld", (long int) mSelfToken);
#endif
mPosition[0] = 0.0;
mPosition[1] = 0.0;
mPosition[2] = 0.0;
mVelocity[0] = 0.0;
mVelocity[1] = 0.0;
mVelocity[2] = 0.0;
mConeDirection[0] = 0.0;
mConeDirection[1] = 0.0;
mConeDirection[2] = 0.0;
mBufferQueueActive = new BufferQueue();
mBufferQueueActive->Reserve(512);
mBufferQueueInactive = new BufferQueue();
mBufferQueueInactive->Reserve(512);
mACMap = new ACMap();
mReferenceDistance = mOwningContext->GetDefaultReferenceDistance();
mMaxDistance = mOwningContext->GetDefaultMaxDistance();
if (Get3DMixerVersion() < k3DMixerVersion_2_0)
{
mTempSourceStorage = (AudioBufferList *) malloc ((offsetof(AudioBufferList, mBuffers)) + (2 * sizeof(AudioBuffer)));
mTempSourceStorage->mBuffers[0].mDataByteSize = mTempSourceStorageBufferSize;
mTempSourceStorage->mBuffers[0].mData = malloc(mTempSourceStorageBufferSize);
mTempSourceStorage->mBuffers[1].mDataByteSize = mTempSourceStorageBufferSize;
mTempSourceStorage->mBuffers[1].mData = malloc(mTempSourceStorageBufferSize);
}
else
{
mTempSourceStorage = NULL;
}
}
OALSource::~OALSource()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::~OALSource() - OALSource = %ld", (long int) mSelfToken);
#endif
if (mCurrentPlayBus != kSourceNeedsBus)
{
ReleaseNotifyAndRenderProcs();
mOwningContext->SetBusAsAvailable (mCurrentPlayBus);
mCurrentPlayBus = kSourceNeedsBus;
}
FlushBufferQueue();
ClearMessageQueue();
if (mTempSourceStorage)
free(mTempSourceStorage);
delete (mBufferQueueInactive);
delete (mBufferQueueActive);
if (mACMap)
{
mACMap->RemoveAllConverters();
delete (mACMap);
}
if (mSourceNotifications)
delete mSourceNotifications;
}
void OALSource::SetUpDeconstruction()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::SetUpDeconstruction() - OALSource = %ld", (long int) mSelfToken);
#endif
try {
OALRenderLocker::RenderLocker locked(mRenderLocker, InRenderThread());
CAGuard::Locker sourceLock(mSourceLock);
switch (mState)
{
case AL_PLAYING:
case kTransitionToStop:
case kTransitionToPlay:
case kTransitionToPause:
case kTransitionToRewind:
case kTransitionToRetrigger:
case kTransitionToResume:
{
#if LOG_MESSAGE_QUEUE
DebugMessageN1("OALSource::SetUpDeconstruction ADDING : kMQ_Stop - OALSource = %ld", (long int) mSelfToken);
#endif
AddPlaybackMessage(kMQ_DeconstructionStop, NULL, 0);
break;
}
default:
mSafeForDeletion = true;
break;
}
SetPlaybackState(kTransitionToStop);
mTransitioningToFlushQ = true;
}
catch (OSStatus result) {
DebugMessageN2("SetUpDeconstruction FAILED source = %d, err = %d\n", (int) mSelfToken, (int)result);
throw (result);
}
}
void OALSource::Suspend ()
{
}
void OALSource::Unsuspend ()
{
}
void OALSource::SetPitch (float inPitch)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetPitch() - OALSource:inPitch = %ld:%f", (long int) mSelfToken, inPitch);
#endif
if (inPitch < 0.0f)
throw ((OSStatus) AL_INVALID_VALUE);
CAGuard::Locker sourceLock(mSourceLock);
if ((inPitch == mPitch) && (mResetPitch == false))
return;
mPitch = inPitch;
if (Get3DMixerVersion() < k3DMixerVersion_2_0)
return;
Float32 newPitch = mPitch * mDopplerScaler;
if (mCurrentPlayBus != kSourceNeedsBus)
{
BufferInfo *oalBuffer = mBufferQueueActive->Get(mCurrentBufferIndex);
if (oalBuffer != NULL)
{
#if LOG_GRAPH_AND_MIXER_CHANGES
DebugMessageN2("OALSource::SetPitch: k3DMixerParam_PlaybackRate called - OALSource:mPitch = %ld:%f\n", mSelfToken, mPitch );
#endif
OSStatus result = AudioUnitSetParameter (mOwningContext->GetMixerUnit(), k3DMixerParam_PlaybackRate, kAudioUnitScope_Input, mCurrentPlayBus, newPitch, 0);
if (result != noErr)
DebugMessageN3("OALSource::SetPitch: k3DMixerParam_PlaybackRate called - OALSource = %ld mPitch = %f result = %d\n", (long int) mSelfToken, mPitch, (int)result );
}
mResetPitch = false;
}
else
mResetPitch = true; }
void OALSource::SetGain (float inGain)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetGain() - OALSource:inGain = %ld:%f", (long int) mSelfToken, inGain);
#endif
if (inGain < 0.0f)
throw ((OSStatus) AL_INVALID_VALUE);
CAGuard::Locker sourceLock(mSourceLock);
if (mGain != inGain)
{
mGain = inGain;
UpdateBusGain();
}
}
void OALSource::SetMinGain (Float32 inMinGain)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetMinGain - OALSource:inMinGain = %ld:%f\n", (long int) mSelfToken, inMinGain);
#endif
if ((inMinGain < 0.0f) || (inMinGain > 1.0f))
throw ((OSStatus) AL_INVALID_VALUE);
CAGuard::Locker sourceLock(mSourceLock);
if (mMinGain != inMinGain)
{
mMinGain = inMinGain;
UpdateMinBusGain();
}
}
void OALSource::SetMaxGain (Float32 inMaxGain)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetMaxGain - OALSource:inMaxGain = %ld:%f\n", (long int) mSelfToken, inMaxGain);
#endif
if ((inMaxGain < 0.0f) || (inMaxGain > 1.0f))
throw ((OSStatus) AL_INVALID_VALUE);
CAGuard::Locker sourceLock(mSourceLock);
if (mMaxGain != inMaxGain)
{
mMaxGain = inMaxGain;
UpdateMaxBusGain();
}
}
Float32 OALSource::GetMaxAttenuation(Float32 inRefDistance, Float32 inMaxDistance, Float32 inRolloff)
{
#if LOG_VERBOSE
DebugMessageN4("OALSource::GetMaxAttenuation() - OALSource:inRefDistance:inMaxDistance:inRolloff = %ld:%f:%f:%f", (long int) mSelfToken, inRefDistance, inMaxDistance, inRolloff);
#endif
Float32 returnValue = 20 * log10(inRefDistance / (inRefDistance + (inRolloff * (inMaxDistance - inRefDistance))));
if (returnValue < 0.0)
returnValue *= -1.0;
else
returnValue = 0.0;
return returnValue;
}
OSStatus OALSource::SetDistanceParams(bool inChangeReferenceDistance, bool inChangeMaxDistance)
{
#if LOG_VERBOSE
DebugMessageN3("OALSource::SetDistanceParams() - OALSource:inChangeReferenceDistance:inChangeMaxDistance = %ld:%d:%d", (long int) mSelfToken, inChangeReferenceDistance, inChangeMaxDistance);
#endif
OSStatus result = noErr;
CAGuard::Locker sourceLock(mSourceLock);
if (Get3DMixerVersion() < k3DMixerVersion_2_0)
{
mOwningContext->SetDistanceAttenuation(mCurrentPlayBus, mReferenceDistance, mMaxDistance, mRollOffFactor);
}
else
{
MixerDistanceParams distanceParams;
UInt32 propSize = sizeof(distanceParams);
result = AudioUnitGetProperty(mOwningContext->GetMixerUnit(), kAudioUnitProperty_3DMixerDistanceParams, kAudioUnitScope_Input, mCurrentPlayBus, &distanceParams, &propSize);
if (result == noErr)
{
Float32 rollOff = mRollOffFactor;
if (mOwningContext->IsDistanceScalingRequired())
{
distanceParams.mReferenceDistance = (mReferenceDistance/mMaxDistance) * kDistanceScalar;
distanceParams.mMaxDistance = kDistanceScalar;
rollOff *= (kDistanceScalar/mMaxDistance);
}
else
{
if (inChangeReferenceDistance)
distanceParams.mReferenceDistance = mReferenceDistance;
else if (inChangeMaxDistance)
distanceParams.mMaxDistance = mMaxDistance;
}
distanceParams.mMaxAttenuation = GetMaxAttenuation(distanceParams.mReferenceDistance, distanceParams.mMaxDistance, rollOff);
if ((mReferenceDistance == mMaxDistance) && (Get3DMixerVersion() < k3DMixerVersion_2_2))
distanceParams.mMaxDistance = distanceParams.mReferenceDistance + .01;
result = AudioUnitSetProperty(mOwningContext->GetMixerUnit(), kAudioUnitProperty_3DMixerDistanceParams, kAudioUnitScope_Input, mCurrentPlayBus, &distanceParams, sizeof(distanceParams));
}
}
return result;
}
void OALSource::SetReferenceDistance (Float32 inReferenceDistance)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetReferenceDistance - OALSource:inReferenceDistance = %ld:%f\n", (long int) mSelfToken, inReferenceDistance);
#endif
if (inReferenceDistance < 0.0f)
throw ((OSStatus) AL_INVALID_VALUE);
CAGuard::Locker sourceLock(mSourceLock);
if (inReferenceDistance == mReferenceDistance)
return;
mReferenceDistance = inReferenceDistance;
if (!mOwningContext->DoSetDistance())
return;
if (mCurrentPlayBus != kSourceNeedsBus)
{
SetDistanceParams(true, false);
}
}
void OALSource::SetMaxDistance (Float32 inMaxDistance)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetMaxDistance - OALSource:inMaxDistance = %ld:%f\n", (long int) mSelfToken, inMaxDistance);
#endif
if (inMaxDistance < 0.0f)
throw ((OSStatus) AL_INVALID_VALUE);
CAGuard::Locker sourceLock(mSourceLock);
if (inMaxDistance == mMaxDistance)
return;
mMaxDistance = inMaxDistance;
if (!mOwningContext->DoSetDistance())
return;
if (mCurrentPlayBus != kSourceNeedsBus)
{
SetDistanceParams(false, true);
}
}
void OALSource::SetRollOffFactor (Float32 inRollOffFactor)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetRollOffFactor - OALSource:inRollOffFactor = %ld:%f\n", (long int) mSelfToken, inRollOffFactor);
#endif
if (inRollOffFactor < 0.0f)
throw ((OSStatus) AL_INVALID_VALUE);
CAGuard::Locker sourceLock(mSourceLock);
if (inRollOffFactor == mRollOffFactor)
return;
mRollOffFactor = inRollOffFactor;
if (!mOwningContext->DoSetDistance())
return;
if (mCurrentPlayBus != kSourceNeedsBus)
{
SetDistanceParams(false, false);
}
}
void OALSource::SetLooping (UInt32 inLooping)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetLooping called - OALSource:inLooping = %ld:%ld\n", (long int) mSelfToken, (long int) inLooping);
#endif
CAGuard::Locker sourceLock(mSourceLock);
mLooping = inLooping;
}
void OALSource::SetPosition (Float32 inX, Float32 inY, Float32 inZ)
{
#if LOG_VERBOSE
DebugMessageN4("OALSource::SetPosition called - OALSource:X:Y:Z = %ld:%f:%f:%f\n", (long int) mSelfToken, inX, inY, inZ);
#endif
if (isnan(inX) || isnan(inY) || isnan(inZ))
throw ((OSStatus) AL_INVALID_VALUE);
CAGuard::Locker sourceLock(mSourceLock);
mPosition[0] = inX;
mPosition[1] = inY;
mPosition[2] = inZ;
mCalculateDistance = true; }
void OALSource::SetVelocity (Float32 inX, Float32 inY, Float32 inZ)
{
#if LOG_VERBOSE
DebugMessageN4("OALSource::SetVelocity called - OALSource:inX:inY:inY = %ld:%f:%f:%f", (long int) mSelfToken, inX, inY, inZ);
#endif
CAGuard::Locker sourceLock(mSourceLock);
mVelocity[0] = inX;
mVelocity[1] = inY;
mVelocity[2] = inZ;
mCalculateDistance = true; }
void OALSource::SetDirection (Float32 inX, Float32 inY, Float32 inZ)
{
#if LOG_VERBOSE
DebugMessageN4("OALSource::SetDirection called - OALSource:inX:inY:inY = %ld:%f:%f:%f", (long int) mSelfToken, inX, inY, inZ);
#endif
CAGuard::Locker sourceLock(mSourceLock);
mConeDirection[0] = inX;
mConeDirection[1] = inY;
mConeDirection[2] = inZ;
mCalculateDistance = true; }
void OALSource::SetSourceRelative (UInt32 inSourceRelative)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetSourceRelative called - OALSource:inSourceRelative = %ld:%ld", (long int) mSelfToken, (long int) inSourceRelative);
#endif
if ((inSourceRelative != AL_FALSE) && (inSourceRelative != AL_TRUE))
throw ((OSStatus) AL_INVALID_VALUE);
CAGuard::Locker sourceLock(mSourceLock);
mSourceRelative = inSourceRelative;
mCalculateDistance = true; }
void OALSource::SetChannelParameters ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::SetChannelParameters called - OALSource = %ld\n", (long int) mSelfToken);
#endif
SetReferenceDistance(mReferenceDistance);
SetMaxDistance(mMaxDistance);
SetRollOffFactor(mRollOffFactor);
mCalculateDistance = true;
}
void OALSource::SetConeInnerAngle (Float32 inConeInnerAngle)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetConeInnerAngle called - OALSource:inConeInnerAngle = %ld:%f\n", (long int) mSelfToken, inConeInnerAngle);
#endif
CAGuard::Locker sourceLock(mSourceLock);
if (mConeInnerAngle != inConeInnerAngle)
{
mConeInnerAngle = inConeInnerAngle;
mCalculateDistance = true;
}
}
void OALSource::SetConeOuterAngle (Float32 inConeOuterAngle)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetConeOuterAngle called - OALSource:inConeOuterAngle = %ld:%f\n", (long int) mSelfToken, inConeOuterAngle);
#endif
CAGuard::Locker sourceLock(mSourceLock);
if (mConeOuterAngle != inConeOuterAngle)
{
mConeOuterAngle = inConeOuterAngle;
mCalculateDistance = true;
}
}
void OALSource::SetConeOuterGain (Float32 inConeOuterGain)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetConeOuterGain called - OALSource:inConeOuterGain = %ld:%f\n", (long int) mSelfToken, inConeOuterGain);
#endif
if (inConeOuterGain < 0.0f)
throw ((OSStatus) AL_INVALID_VALUE);
if (inConeOuterGain <= 1.0)
{
CAGuard::Locker sourceLock(mSourceLock);
if (mConeOuterGain != inConeOuterGain)
{
mConeOuterGain = inConeOuterGain;
mCalculateDistance = true;
}
}
}
Float32 OALSource::GetPitch ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetPitch called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mPitch;
}
Float32 OALSource::GetDopplerScaler ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetDopplerScaler called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mDopplerScaler;
}
Float32 OALSource::GetGain ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetGain called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mGain;
}
Float32 OALSource::GetMinGain ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetMinGain called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mMinGain;
}
Float32 OALSource::GetMaxGain ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetMaxGain called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mMaxGain;
}
Float32 OALSource::GetReferenceDistance ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetReferenceDistance called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mReferenceDistance;
}
Float32 OALSource::GetMaxDistance ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetMaxDistance called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mMaxDistance;
}
Float32 OALSource::GetRollOffFactor ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetRollOffFactor called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mRollOffFactor;
}
UInt32 OALSource::GetLooping ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetLooping called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mLooping;
}
void OALSource::GetPosition (Float32 &inX, Float32 &inY, Float32 &inZ)
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetPosition called - OALSource = %ld\n", (long int) mSelfToken);
#endif
inX = mPosition[0];
inY = mPosition[1];
inZ = mPosition[2];
}
void OALSource::GetVelocity (Float32 &inX, Float32 &inY, Float32 &inZ)
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetVelocity called - OALSource = %ld\n", (long int) mSelfToken);
#endif
inX = mVelocity[0];
inY = mVelocity[1];
inZ = mVelocity[2];
}
void OALSource::GetDirection (Float32 &inX, Float32 &inY, Float32 &inZ)
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetDirection called - OALSource = %ld\n", (long int) mSelfToken);
#endif
inX = mConeDirection[0];
inY = mConeDirection[1];
inZ = mConeDirection[2];
}
UInt32 OALSource::GetSourceRelative ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetSourceRelative called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mSourceRelative;
}
UInt32 OALSource::GetSourceType ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetSourceType called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mSourceType;
}
Float32 OALSource::GetConeInnerAngle ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetConeInnerAngle called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mConeInnerAngle;
}
Float32 OALSource::GetConeOuterAngle ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetConeOuterAngle called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mConeOuterAngle;
}
Float32 OALSource::GetConeOuterGain ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetConeOuterGain called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mConeOuterGain;
}
UInt32 OALSource::GetState()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetState called - OALSource = %ld\n", (long int) mSelfToken);
#endif
switch(mState)
{
case kTransitionToPlay:
case kTransitionToRetrigger:
case kTransitionToResume:
return AL_PLAYING;
break;
case kTransitionToStop:
return AL_STOPPED;
break;
case kTransitionToPause:
return AL_PAUSED;
break;
case kTransitionToRewind:
return AL_INITIAL;
break;
default:
break;
}
return mState;
}
ALuint OALSource::GetToken()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetToken called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mSelfToken;
}
UInt32 OALSource::GetQLength()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetQLength called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mQueueLength;
}
UInt32 OALSource::GetBuffersProcessed()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetBuffersProcessed called - OALSource = %ld\n", (long int) mSelfToken);
#endif
if (mState == AL_INITIAL)
return 0;
if(IsSourceTransitioningToFlushQ())
return 0;
if ((mState == AL_INITIAL) ||
(mState == AL_STOPPED) ||
(mState == kTransitionToStop) ||
(mState == kTransitionToRewind) )
return GetQLength();
if (mQueueIsProcessed)
{
OALRenderLocker::RenderLocker locked(mRenderLocker, InRenderThread());
CAGuard::Locker sourceLock(mSourceLock);
ClearActiveQueue();
}
return mBufferQueueInactive->GetQueueSize();
}
void OALSource::SetBuffer (ALuint inBufferToken, OALBuffer *inBuffer)
{
#if LOG_VERBOSE
DebugMessageN3("OALSource::SetBuffer called - OALSource:inBufferToken:inBuffer = %ld:%ld:%p\n", (long int) mSelfToken, (long int) inBufferToken, inBuffer);
#endif
if (inBuffer == NULL)
return;
OALRenderLocker::RenderLocker locked(mRenderLocker, InRenderThread());
CAGuard::Locker sourceLock(mSourceLock);
switch (mState)
{
case AL_PLAYING:
case AL_PAUSED:
case kTransitionToPlay:
case kTransitionToRetrigger:
case kTransitionToResume:
case kTransitionToPause:
throw (OSStatus)AL_INVALID_OPERATION;
break;
case kTransitionToStop:
case kTransitionToRewind:
{
if (inBufferToken == 0)
{
mSourceType = AL_UNDETERMINED;
mTransitioningToFlushQ = true;
}
#if LOG_MESSAGE_QUEUE
DebugMessageN1("OALSource::SetBuffer - kMQ_SetBuffer added to MQ - OALSource = %ld", (long int) mSelfToken);
#endif
AddPlaybackMessage(kMQ_SetBuffer, inBuffer, 0);
break;
}
default:
{
FlushBufferQueue();
if (inBufferToken != 0)
{
AppendBufferToQueue(inBufferToken, inBuffer);
mSourceType = AL_STATIC;
}
else
mSourceType = AL_UNDETERMINED;
}
}
}
void OALSource::FlushBufferQueue()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::FlushBufferQueue called - OALSource = %ld\n", (long int) mSelfToken);
#endif
UInt32 count = mBufferQueueInactive->GetQueueSize();
for (UInt32 i = 0; i < count; i++)
{
mBufferQueueInactive->RemoveQueueEntryByIndex(this, 0, true);
mBuffersQueuedForClear = 0;
}
count = mBufferQueueActive->GetQueueSize();
for (UInt32 i = 0; i < count; i++)
{
mBufferQueueActive->RemoveQueueEntryByIndex(this, 0, true);
}
SetQueueLength();
}
ALuint OALSource::GetBuffer()
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::GetBuffer called - OALSource:currentBuffer = %ld:%ld\n", (long int)mSelfToken, (long int)mBufferQueueActive->GetBufferTokenByIndex(mCurrentBufferIndex));
#endif
OALRenderLocker::RenderLocker locked(mRenderLocker, InRenderThread());
CAGuard::Locker sourceLock(mSourceLock);
ALuint bufferID = 0;
if (mSourceType == AL_STATIC)
{
if (mBufferQueueActive->GetQueueSize() > 0)
bufferID = mBufferQueueActive->GetBufferTokenByIndex(0);
else if (mBufferQueueInactive->GetQueueSize() > 0)
bufferID = mBufferQueueInactive->GetBufferTokenByIndex(0);
}
return bufferID;
}
void OALSource::AddToQueue(ALuint inBufferToken, OALBuffer *inBuffer)
{
#if LOG_VERBOSE
DebugMessageN3("OALSource::AddToQueue called - OALSource:inBufferToken:inBuffer = %ld:%ld:%p\n", (long int) mSelfToken, (long int) inBufferToken, inBuffer);
#endif
OALRenderLocker::RenderLocker locked(mRenderLocker, InRenderThread());
CAGuard::Locker sourceLock(mSourceLock);
if (mSourceType == AL_STATIC)
throw (OSStatus)AL_INVALID_OPERATION;
if (mSourceType == AL_UNDETERMINED)
mSourceType = AL_STREAMING;
AppendBufferToQueue(inBufferToken, inBuffer);
}
void OALSource::AppendBufferToQueue(ALuint inBufferToken, OALBuffer *inBuffer)
{
#if LOG_VERBOSE
DebugMessageN3("OALSource::AppendBufferToQueue called (START) - OALSource:inBufferToken:inBuffer = %ld:%ld:%p", (long int)mSelfToken, (long int)inBufferToken, inBuffer);
#endif
OSStatus result = noErr;
#if LOG_BUFFER_QUEUEING
DebugMessageN2("OALSource::AppendBufferToQueue called (START) - OALSource:inBufferToken = %ld:%ld", (long int)mSelfToken, (long int)inBufferToken);
#endif
try {
if (mBufferQueueActive->Empty())
{
mCurrentBufferIndex = 0; mQueueIsProcessed = false;
}
if (inBuffer->HasBeenConverted())
{
mBufferQueueActive->AppendBuffer(this, inBufferToken, inBuffer, 0);
SetQueueLength();
}
else
{
ALuint outToken = 0;
mACMap->GetACForFormat(inBuffer->GetFormat(), outToken);
if (outToken == 0)
{
AudioConverterRef converter = 0;
CAStreamBasicDescription inFormat;
inFormat.SetFrom(*(inBuffer->GetFormat()));
if (inFormat.NumberChannels() == 1)
inFormat.mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
CAStreamBasicDescription outFormat;
outFormat.mChannelsPerFrame = inFormat.NumberChannels();
outFormat.mSampleRate = inFormat.mSampleRate;
outFormat.mFormatID = kAudioFormatLinearPCM;
outFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;
outFormat.mBytesPerPacket = sizeof (Float32);
outFormat.mFramesPerPacket = 1;
outFormat.mBytesPerFrame = sizeof (Float32);
outFormat.mBitsPerChannel = sizeof (Float32) * 8;
result = AudioConverterNew(&inFormat, &outFormat, &converter);
THROW_RESULT
ACInfo info;
info.mInputFormat = *(inBuffer->GetFormat());
info.mConverter = converter;
ALuint newACToken = GetNewToken();
mACMap->Add(newACToken, &info);
mBufferQueueActive->AppendBuffer(this, inBufferToken, inBuffer, newACToken);
SetQueueLength();
}
else
{
mBufferQueueActive->AppendBuffer(this, inBufferToken, inBuffer, outToken);
SetQueueLength();
}
}
inBuffer->UseThisBuffer(this);
}
catch (OSStatus result) {
DebugMessageN1("APPEND BUFFER FAILED %ld\n", (long int) mSelfToken);
throw (result);
}
#if LOG_BUFFER_QUEUEING
DebugMessageN2("OALSource::AppendBufferToQueue called (END) - OALSource:QLength = %ld:%ld", (long int)mSelfToken, mBufferQueueInactive->Size() + mBufferQueueActive->Size());
#endif
return;
}
void OALSource::RemoveBuffersFromQueue(UInt32 inCount, ALuint *outBufferTokens)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::RemoveBuffersFromQueue called - OALSource:inCount = %ld:%ld\n", (long int) mSelfToken, (long int) inCount);
#endif
if (inCount == 0)
return;
#if LOG_BUFFER_QUEUEING
DebugMessageN2("OALSource::RemoveBuffersFromQueue called (START) - OALSource:inCount = %ld:%ld", (long int)mSelfToken, inCount);
#endif
try {
OALRenderLocker::RenderLocker locked(mRenderLocker, InRenderThread());
CAGuard::Locker sourceLock(mSourceLock);
if (inCount > GetQLength())
throw ((OSStatus) AL_INVALID_OPERATION);
if (outBufferTokens == NULL)
throw ((OSStatus) AL_INVALID_OPERATION);
if ((mState == AL_PLAYING) || (mState == AL_PAUSED))
{
if (mLooping == true)
throw ((OSStatus) AL_INVALID_OPERATION);
else if (inCount > (UInt32)mBufferQueueInactive->GetQueueSize())
throw ((OSStatus) AL_INVALID_OPERATION);
}
else if ((mState == AL_STOPPED) || (mState == AL_INITIAL))
{
ClearActiveQueue();
if (inCount > (UInt32)mBufferQueueInactive->GetQueueSize())
{
DebugMessageN3(" OALSource::RemoveBuffersFromQueue mState == AL_STOPPED - OALSource:GetQLength():mBufferQueueInactive->Size() = %d:%d:%d", (int) mSelfToken, (int)GetQLength(), (int)mBufferQueueInactive->GetQueueSize());
throw ((OSStatus) AL_INVALID_OPERATION);
}
}
else if((mState == kTransitionToStop) || (mState == kTransitionToRewind))
{
#if LOG_BUFFER_QUEUEING
DebugMessageN2(" RemoveBuffersFromQueue kTransitionState - OALSource:inCount = %ld:%ld", (long int)mSelfToken, inCount);
#endif
#if LOG_MESSAGE_QUEUE
DebugMessageN1(" RemoveBuffersFromQueue ADDING : kMQ_ClearBuffersFromQueue - OALSource = %ld", (long int) mSelfToken);
#endif
AddPlaybackMessage(kMQ_ClearBuffersFromQueue, NULL, inCount);
}
for (UInt32 i = mBuffersQueuedForClear; i < mBuffersQueuedForClear+inCount; i++)
{
if ((mState == kTransitionToStop) || (mState == kTransitionToRewind))
{
if (i < (UInt32)mBufferQueueInactive->GetQueueSize())
{
outBufferTokens[i-mBuffersQueuedForClear] = mBufferQueueInactive->GetBufferTokenByIndex(i);
}
else
{
outBufferTokens[i-mBuffersQueuedForClear] = mBufferQueueActive->GetBufferTokenByIndex(i - mBufferQueueInactive->GetQueueSize());
}
}
else
{
ALuint outToken = 0;
outToken = mBufferQueueInactive->RemoveQueueEntryByIndex(this, 0, true);
mBuffersQueuedForClear = 0;
SetQueueLength();
#if LOG_MESSAGE_QUEUE
DebugMessageN1(" Just Removed Buffer Id from inactive Q = %ld", (long int) outToken);
#endif
outBufferTokens[i] = outToken;
}
}
if ((mState == kTransitionToStop) || (mState == kTransitionToRewind))
{
mBuffersQueuedForClear+= inCount;
SetQueueLength();
}
if (GetQLength() == 0)
mSourceType = AL_UNDETERMINED;
}
catch (OSStatus result) {
DebugMessageN1(" REMOVE BUFFER FAILED, OALSource = %ld\n", (long int) mSelfToken);
throw (result);
}
#if LOG_BUFFER_QUEUEING
DebugMessageN2(" OALSource:RemoveBuffersFromQueue called (END) - OALSource:QLength = %ld:%ld", (long int)mSelfToken, mBufferQueueInactive->Size() + mBufferQueueActive->Size());
#endif
return;
}
void OALSource::PostRenderRemoveBuffersFromQueue(UInt32 inBuffersToUnqueue)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::PostRenderRemoveBuffersFromQueue called - OALSource:inBuffersToUnqueue = %ld:%ld\n", (long int) mSelfToken, (long int) inBuffersToUnqueue);
#endif
#if LOG_BUFFER_QUEUEING
DebugMessageN2("OALSource::PostRenderRemoveBuffersFromQueue called (START) - OALSource:inCount = %ld:%ld", (long int)mSelfToken, inBuffersToUnqueue);
#endif
try {
ClearActiveQueue();
if (inBuffersToUnqueue > (UInt32)mBufferQueueInactive->GetQueueSize())
{
DebugMessageN3(" OALSource::PostRenderRemoveBuffersFromQueue mState == AL_STOPPED - OALSource:GetQLength():mBufferQueueInactive->Size() = %d:%d:%d", (int) mSelfToken, (int)GetQLength(), (int)mBufferQueueInactive->GetQueueSize());
throw ((OSStatus) AL_INVALID_OPERATION);
}
for (UInt32 i = 0; i < inBuffersToUnqueue; i++)
{
mBufferQueueInactive->RemoveQueueEntryByIndex(this, 0, true);
mBuffersQueuedForClear = 0;
SetQueueLength();
}
if (GetQLength() == 0)
mSourceType = AL_UNDETERMINED;
}
catch (OSStatus result) {
DebugMessageN1(" REMOVE BUFFER FAILED, OALSource = %ld\n", (long int) mSelfToken);
throw (result);
}
#if LOG_BUFFER_QUEUEING
DebugMessageN2(" OALSource:PostRenderRemoveBuffersFromQueue called (END) - OALSource:QLength = %ld:%ld\n", (long int)mSelfToken, mBufferQueueInactive->Size() + mBufferQueueActive->Size());
#endif
return;
}
void OALSource::PostRenderSetBuffer (ALuint inBufferToken, OALBuffer *inBuffer)
{
#if LOG_VERBOSE
DebugMessageN3("OALSource::PostRenderSetBuffer - OALSource:inBufferToken:inBuffer = %ld:%ld:%p", (long int) mSelfToken, (long int) inBufferToken, inBuffer);
#endif
FlushBufferQueue();
if (inBufferToken != 0)
{
AppendBufferToQueue(inBufferToken, inBuffer);
mSourceType = AL_STATIC;
}
else
{
mSourceType = AL_UNDETERMINED;
mTransitioningToFlushQ = false;
}
}
void OALSource::SetupMixerBus()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::SetupMixerBus called - OALSource = %ld\n", (long int) mSelfToken);
#endif
OSStatus result = noErr;
CAStreamBasicDescription desc;
UInt32 propSize = 0;
BufferInfo* buffer = mBufferQueueActive->Get(mCurrentBufferIndex);
try {
if (buffer == NULL)
throw (OSStatus)-1;
if (mCurrentPlayBus == kSourceNeedsBus)
{
mCurrentPlayBus = (buffer->mBuffer->GetNumberChannels() == 1) ? mOwningContext->GetAvailableMonoBus(mSelfToken) : mOwningContext->GetAvailableStereoBus(mSelfToken);
if (mCurrentPlayBus == -1)
throw (OSStatus) -1;
if (Get3DMixerVersion() >= k3DMixerVersion_2_0)
{
Float32 rollOff = mRollOffFactor;
Float32 refDistance = mReferenceDistance;
Float32 maxDistance = mMaxDistance;
if (mOwningContext->IsDistanceScalingRequired())
{
refDistance = (mReferenceDistance/mMaxDistance) * kDistanceScalar;
maxDistance = kDistanceScalar;
rollOff *= (kDistanceScalar/mMaxDistance);
}
Float32 testAttenuation = GetMaxAttenuation(mReferenceDistance, mMaxDistance, mRollOffFactor);
MixerDistanceParams distanceParams;
propSize = sizeof(distanceParams);
result = AudioUnitGetProperty(mOwningContext->GetMixerUnit(), kAudioUnitProperty_3DMixerDistanceParams, kAudioUnitScope_Input, mCurrentPlayBus, &distanceParams, &propSize);
if ((result == noErr) && ((distanceParams.mReferenceDistance != refDistance) ||
(distanceParams.mMaxDistance != maxDistance) ||
(distanceParams.mMaxAttenuation != testAttenuation)))
{
distanceParams.mMaxAttenuation = testAttenuation;
if (mOwningContext->IsDistanceScalingRequired())
{
distanceParams.mReferenceDistance = (mReferenceDistance/mMaxDistance) * kDistanceScalar;
distanceParams.mMaxDistance = kDistanceScalar;
distanceParams.mMaxAttenuation = testAttenuation;
}
else
{
distanceParams.mReferenceDistance = mReferenceDistance;
distanceParams.mMaxDistance = mMaxDistance;
}
if ((mReferenceDistance == mMaxDistance) && (Get3DMixerVersion() < k3DMixerVersion_2_2))
distanceParams.mMaxDistance = distanceParams.mReferenceDistance + .01;
result = AudioUnitSetProperty(mOwningContext->GetMixerUnit(), kAudioUnitProperty_3DMixerDistanceParams, kAudioUnitScope_Input, mCurrentPlayBus, &distanceParams, sizeof(distanceParams));
}
}
else
{
mOwningContext->SetDistanceAttenuation(mCurrentPlayBus, mReferenceDistance, mMaxDistance, mRollOffFactor);
}
UpdateBusReverb();
UpdateBusOcclusion();
UpdateBusObstruction();
}
propSize = sizeof(desc);
result = AudioUnitGetProperty(mOwningContext->GetMixerUnit(), kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, mCurrentPlayBus, &desc, &propSize);
mResetPitch = true;
mCalculateDistance = true;
if (desc.mSampleRate != buffer->mBuffer->GetSampleRate())
mResetBusFormat = true;
ChangeChannelSettings();
UpdateBusGain();
}
catch (OSStatus result) {
DebugMessageN2(" SetupMixerBus FAILED, OALSource:error = %d:%d\n", (int) mSelfToken, (int)result);
throw (result);
}
catch (...) {
DebugMessageN1(" SetupMixerBus FAILED, OALSource = %ld\n", (long int) mSelfToken);
throw;
}
return;
}
void OALSource::ResetMixerBus()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::ResetMixerBus() - OALSource = %ld", (long int) mSelfToken);
#endif
OSStatus result = noErr;
try {
if (mCurrentPlayBus != kSourceNeedsBus)
{
result = AudioUnitReset(mOwningContext->GetMixerUnit(), kAudioUnitScope_Input, mCurrentPlayBus);
THROW_RESULT
}
}
catch (OSStatus result) {
DebugMessageN2(" ResetMixerBus FAILED, OALSource:error = %d:%d\n", (int) mSelfToken, (int)result);
throw (result);
}
catch (...) {
DebugMessageN1(" ResetMixerBus FAILED, OALSource = %ld\n", (long int) mSelfToken);
throw;
}
return;
}
void OALSource::SetupRogerBeepAU()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::SetupRogerBeepAU called - OALSource = %ld\n", (long int) mSelfToken);
#endif
ComponentDescription desc;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
desc.componentType = kAudioUnitType_Effect;
desc.componentSubType = kRogerBeepType;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
OSStatus result = AUGraphNewNode (mOwningContext->GetGraph(), &desc, 0, NULL, &mRogerBeepNode);
THROW_RESULT
result = AUGraphGetNodeInfo (mOwningContext->GetGraph(), mRogerBeepNode, 0, 0, 0, &mRogerBeepAU);
THROW_RESULT
}
void OALSource::SetupDistortionAU()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::SetupDistortionAU called - OALSource = %ld\n", (long int) mSelfToken);
#endif
ComponentDescription desc;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
desc.componentType = kAudioUnitType_Effect;
desc.componentSubType = kDistortionType;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
OSStatus result = AUGraphNewNode (mOwningContext->GetGraph(), &desc, 0, NULL, &mDistortionNode);
THROW_RESULT
result = AUGraphGetNodeInfo (mOwningContext->GetGraph(), mDistortionNode, 0, 0, 0, &mDistortionAU);
THROW_RESULT
}
bool OALSource::PrepBufferQueueForPlayback()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::PrepBufferQueueForPlayback called - OALSource = %ld\n", (long int) mSelfToken);
#endif
BufferInfo *buffer = NULL;
JoinBufferLists();
if (mBufferQueueActive->Empty())
return false;
buffer = NextPlayableBufferInActiveQ();
if (buffer == NULL)
return false;
#if LOG_PLAYBACK
DebugMessage("OALSource::PrepBufferQueueForPlayback called - Format of 1st buffer in the Q =\n");
buffer->mBuffer->PrintFormat();
#endif
{
volatile UInt32 X;
UInt32 *start = (UInt32 *)buffer->mBuffer->GetDataPtr();
UInt32 *end = (UInt32 *)(buffer->mBuffer->GetDataPtr() + (buffer->mBuffer->GetDataSize() &0xFFFFFFFC));
while (start < end)
{
X = *start;
start += 1024;
}
}
if (buffer->mBuffer->HasBeenConverted() == false)
AudioConverterReset(mACMap->Get(buffer->mACToken));
return true;
}
void OALSource::Play()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::Play called - OALSource = %ld\n", (long int) mSelfToken);
#endif
#if LOG_PLAYBACK
DebugMessageN2("OALSource::Play called - OALSource:mState = %ld:%ld\n", (long int) mSelfToken, mState);
#endif
try {
OALRenderLocker::RenderLocker locked(mRenderLocker, InRenderThread());
CAGuard::Locker sourceLock(mSourceLock);
if (GetQLength() == 0)
return;
switch (mState)
{
case AL_PLAYING:
case kTransitionToPlay:
case kTransitionToResume:
case kTransitionToRetrigger:
if (mRampState != kRampingComplete)
{
mRampState = kRampDown;
#if LOG_MESSAGE_QUEUE
DebugMessageN1("OALSource::Play (AL_PLAYING state) - kMQ_Retrigger added to MQ - OALSource = %ld", (long int) mSelfToken);
#endif
AddPlaybackMessage(kMQ_Retrigger, NULL, 0);
SetPlaybackState(kTransitionToRetrigger);
}
break;
case AL_PAUSED:
Resume();
break;
case kTransitionToPause:
#if LOG_MESSAGE_QUEUE
DebugMessageN1("OALSource::Play (kTransitionToPause state) - kMQ_Resume added to MQ - OALSource = %ld", (long int) mSelfToken);
#endif
AddPlaybackMessage((UInt32) kMQ_Resume, NULL, 0);
SetPlaybackState(kTransitionToResume);
break;
case kTransitionToStop:
case kTransitionToRewind:
if (mRampState != kRampingComplete)
{
mRampState = kRampDown;
#if LOG_MESSAGE_QUEUE
DebugMessageN1("OALSource::Play (kTransitionToStop/kTransitionToRewind state) - kMQ_Play added to MQ - OALSource = %ld", (long int) mSelfToken);
#endif
AddPlaybackMessage(kMQ_Play, NULL, 0);
SetPlaybackState(kTransitionToPlay);
}
break;
default:
{
PrepBufferQueueForPlayback();
SetupMixerBus();
CAStreamBasicDescription format;
UInt32 propSize = sizeof(format);
OSStatus result = noErr;
if(mASARogerBeepEnable || mASADistortionEnable)
{
mRenderElement = 0;
result = AudioUnitGetProperty(mOwningContext->GetMixerUnit(), kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, mCurrentPlayBus, &format, &propSize);
THROW_RESULT
if(mASARogerBeepEnable)
{
result = AudioUnitSetProperty (mRogerBeepAU, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &format, sizeof(format));
THROW_RESULT
result = AudioUnitSetProperty (mRogerBeepAU, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &format, sizeof(format));
THROW_RESULT
result = AudioUnitInitialize(mRogerBeepAU);
THROW_RESULT
result = AUGraphConnectNodeInput(mOwningContext->GetGraph(), mRogerBeepNode, 0, mOwningContext->GetMixerNode(), mCurrentPlayBus);
THROW_RESULT
if(!mASADistortionEnable)
{
result = AUGraphGetNodeInfo (mOwningContext->GetGraph(), mRogerBeepNode, 0, 0, 0, &mRenderUnit);
THROW_RESULT;
}
}
if(mASADistortionEnable)
{
result = AudioUnitSetProperty (mDistortionAU, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &format, sizeof(format));
THROW_RESULT
result = AudioUnitSetProperty (mDistortionAU, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &format, sizeof(format));
THROW_RESULT
result = AudioUnitInitialize(mDistortionAU);
THROW_RESULT
result = AUGraphGetNodeInfo (mOwningContext->GetGraph(), mDistortionNode, 0, 0, 0, &mRenderUnit);
THROW_RESULT
if(mASARogerBeepEnable)
result = AUGraphConnectNodeInput(mOwningContext->GetGraph(), mDistortionNode, 0, mRogerBeepNode, 0);
else
result = AUGraphConnectNodeInput(mOwningContext->GetGraph(), mDistortionNode, 0, mOwningContext->GetMixerNode(), mCurrentPlayBus);
THROW_RESULT
}
result = AUGraphUpdate(mOwningContext->GetGraph(), NULL);
THROW_RESULT
}
else
{
mRenderUnit = mOwningContext->GetMixerUnit();
mRenderElement = mCurrentPlayBus;
}
THROW_RESULT
SetPlaybackState(AL_PLAYING,true);
if (mRampState != kRampingComplete)
mRampState = kRampUp;
mResetBus = true;
mQueueIsProcessed = false;
AddNotifyAndRenderProcs();
}
}
}
catch (OSStatus result) {
DebugMessageN2("PLAY FAILED source = %ld, err = %ld\n", (long int) mSelfToken, (long int)result);
throw (result);
}
}
void OALSource::Rewind()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::Rewind called - OALSource = %ld\n", (long int) mSelfToken);
#endif
#if LOG_PLAYBACK
DebugMessageN2("OALSource::Rewind called - OALSource:mState = %ld:%ld\n", (long int) mSelfToken, mState);
#endif
OALRenderLocker::RenderLocker locked(mRenderLocker, InRenderThread());
CAGuard::Locker sourceLock(mSourceLock);
switch (mState)
{
case AL_PLAYING:
{
#if LOG_MESSAGE_QUEUE
DebugMessageN1("Rewind(AL_PLAYING) ADDING : kMQ_Rewind - OALSource = %ld", (long int) mSelfToken);
#endif
SetPlaybackState(kTransitionToRewind);
if (mRampState != kRampingComplete)
mRampState = kRampDown;
AddPlaybackMessage(kMQ_Rewind, NULL, 0);
break;
}
case AL_PAUSED:
if (mCurrentPlayBus != kSourceNeedsBus)
{
mOwningContext->SetBusAsAvailable (mCurrentPlayBus);
mCurrentPlayBus = kSourceNeedsBus;
}
JoinBufferLists(); SetPlaybackState(AL_INITIAL,true);
break;
case AL_STOPPED:
JoinBufferLists(); SetPlaybackState(AL_INITIAL,true);
break;
case kTransitionToPlay:
case kTransitionToResume:
case kTransitionToRetrigger:
case kTransitionToStop:
case kTransitionToPause:
{
#if LOG_MESSAGE_QUEUE
DebugMessageN1("OALSource::Rewind - kMQ_Rewind added to MQ - OALSource = %ld", (long int) mSelfToken);
#endif
SetPlaybackState(kTransitionToRewind);
AddPlaybackMessage((UInt32) kMQ_Rewind, NULL, 0);
break;
}
case AL_INITIAL:
case kTransitionToRewind:
break;
}
}
void OALSource::Pause()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::Pause called - OALSource = %ld\n", (long int) mSelfToken);
#endif
#if LOG_PLAYBACK
DebugMessageN2("OALSource::Pause called - OALSource:mState = %ld:%ld\n", (long int) mSelfToken, mState);
#endif
OALRenderLocker::RenderLocker locked(mRenderLocker, InRenderThread());
CAGuard::Locker sourceLock(mSourceLock);
switch (mState)
{
case AL_PLAYING:
{
if (mRampState != kRampingComplete)
mRampState = kRampDown;
#if LOG_MESSAGE_QUEUE
DebugMessageN1("Pause(AL_PLAYING) ADDING : kMQ_Pause - OALSource = %ld", (long int) mSelfToken);
#endif
AddPlaybackMessage(kMQ_Pause, NULL, 0);
SetPlaybackState(kTransitionToPause);
}
case AL_INITIAL:
case AL_STOPPED:
case AL_PAUSED:
case kTransitionToPause:
case kTransitionToStop:
case kTransitionToRewind:
break;
case kTransitionToPlay:
case kTransitionToResume:
case kTransitionToRetrigger:
{
#if LOG_MESSAGE_QUEUE
DebugMessageN1("OALSource::Pause - kMQ_Pause added to MQ - OALSource = %ld", (long int) mSelfToken);
#endif
AddPlaybackMessage((UInt32) kMQ_Pause, NULL, 0);
SetPlaybackState(kTransitionToPause);
break;
}
default:
break;
}
}
void OALSource::Resume()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::Resume called - OALSource = %ld\n", (long int) mSelfToken);
#endif
#if LOG_PLAYBACK
DebugMessageN2("OALSource::Resume called - OALSource:mState = %ld:%ld\n", (long int) mSelfToken, mState);
#endif
OALRenderLocker::RenderLocker locked(mRenderLocker, InRenderThread());
CAGuard::Locker sourceLock(mSourceLock);
switch (mState)
{
case AL_PLAYING:
case AL_INITIAL:
case AL_STOPPED:
case kTransitionToPlay:
case kTransitionToResume:
case kTransitionToRetrigger:
case kTransitionToStop:
case kTransitionToRewind:
break;
case AL_PAUSED:
if (mRampState != kRampingComplete)
mRampState = kRampUp;
AddNotifyAndRenderProcs();
SetPlaybackState(AL_PLAYING,true);
break;
case kTransitionToPause:
#if LOG_MESSAGE_QUEUE
DebugMessageN1("OALSource::Resume - kMQ_Resume added to MQ - OALSource = %ld", (long int) mSelfToken);
#endif
AddPlaybackMessage((UInt32) kMQ_Resume, NULL, 0);
SetPlaybackState(kTransitionToResume);
break;
}
}
void OALSource::Stop()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::Stop called - OALSource = %ld\n", (long int) mSelfToken);
#endif
#if LOG_PLAYBACK
DebugMessageN2("OALSource::Stop called - OALSource:mState = %ld:%ld\n", (long int) mSelfToken, mState);
#endif
OALRenderLocker::RenderLocker locked(mRenderLocker, InRenderThread());
CAGuard::Locker sourceLock(mSourceLock);
switch (mState)
{
case AL_PAUSED:
if (mCurrentPlayBus != kSourceNeedsBus)
{
mOwningContext->SetBusAsAvailable (mCurrentPlayBus);
mCurrentPlayBus = kSourceNeedsBus;
SetPlaybackState(AL_STOPPED,true);
if(mBufferQueueActive->GetQueueSize() > 0)
{
if (mSourceNotifications)
mSourceNotifications->CallSourceNotifications(AL_BUFFERS_PROCESSED);
}
}
break;
case AL_PLAYING:
{
#if LOG_MESSAGE_QUEUE
DebugMessageN1("OALSource::Stop (AL_PLAYING state) ADDING : kMQ_Stop - OALSource = %ld", (long int) mSelfToken);
#endif
SetPlaybackState(kTransitionToStop);
if (mRampState != kRampingComplete)
mRampState = kRampDown;
AddPlaybackMessage(kMQ_Stop, NULL, 0);
}
break;
case kTransitionToStop:
case kTransitionToRewind:
break;
case kTransitionToPlay:
case kTransitionToResume:
case kTransitionToRetrigger:
case kTransitionToPause:
{
#if LOG_MESSAGE_QUEUE
DebugMessageN1("OALSource::Stop (kTransitionState state) ADDING : kMQ_Stop - OALSource = %ld", (long int) mSelfToken);
#endif
AddPlaybackMessage(kMQ_Stop, NULL, 0);
SetPlaybackState(kTransitionToStop);
break;
}
default:
break;
}
}
UInt32 OALSource::SecondsToFrames(Float32 inSeconds)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SecondsToFrames called - OALSource:inSeconds = %ld:%f\n", (long int) mSelfToken, inSeconds);
#endif
BufferInfo *curBufferInfo = mBufferQueueActive->Get(mCurrentBufferIndex);
UInt32 frames = 0;
if (curBufferInfo)
frames = (UInt32)(inSeconds * curBufferInfo->mBuffer->GetSampleRate());
if ((SInt32) frames < (SInt32) inSeconds)
throw (OSStatus) AL_INVALID_VALUE;
return frames;
}
UInt32 OALSource::BytesToFrames(Float32 inBytes)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::BytesToFrames called - OALSource:inBytes = %ld:%f\n", (long int) mSelfToken, inBytes);
#endif
BufferInfo *curBufferInfo = mBufferQueueActive->Get(mCurrentBufferIndex);
if (curBufferInfo)
{
UInt32 frameIndex = (UInt32)(inBytes / curBufferInfo->mBuffer->GetBytesPerPacket()); frameIndex *= curBufferInfo->mBuffer->GetFramesPerPacket(); return frameIndex;
}
return 0;
}
UInt32 OALSource::FramesToSecondsInt(UInt32 inFrames)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::FramesToSecondsInt called - OALSource:inFrames = %ld:%d\n", (long int) mSelfToken, inFrames);
#endif
BufferInfo *curBufferInfo = mBufferQueueActive->Get(mCurrentBufferIndex);
if (curBufferInfo == NULL)
curBufferInfo = mBufferQueueInactive->Get(0);
if (curBufferInfo)
return (UInt32)(inFrames / curBufferInfo->mBuffer->GetSampleRate());
return 0;
}
Float32 OALSource::FramesToSecondsFloat(UInt32 inFrames)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::FramesToSecondsFloat called - OALSource:inFrames = %ld:%f\n", (long int) mSelfToken, inFrames);
#endif
BufferInfo *curBufferInfo = mBufferQueueActive->Get(mCurrentBufferIndex);
if (curBufferInfo == NULL)
curBufferInfo = mBufferQueueInactive->Get(0);
if (curBufferInfo)
return (inFrames / curBufferInfo->mBuffer->GetSampleRate());
return 0;
}
UInt32 OALSource::FramesToBytes(UInt32 inFrames)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::FramesToBytes called - OALSource:inFrames = %ld:%d\n", (long int) mSelfToken, inFrames);
#endif
BufferInfo *curBufferInfo = mBufferQueueActive->Get(mCurrentBufferIndex);
if (curBufferInfo == NULL)
curBufferInfo = mBufferQueueInactive->Get(0);
if (curBufferInfo)
{
if(curBufferInfo->mBuffer->GetFramesPerPacket() != 0)
return (inFrames / curBufferInfo->mBuffer->GetFramesPerPacket()) * curBufferInfo->mBuffer->GetBytesPerPacket();
}
return 0;
}
UInt32 OALSource::GetQueueFrameOffset()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetQueueFrameOffset called - OALSource = %ld\n", (long int) mSelfToken);
#endif
UInt32 inInactiveQFrames = mBufferQueueInactive->GetQueueSizeInFrames();
UInt32 inActiveQFrames = 0;
for (UInt32 i = 0; i < mCurrentBufferIndex; i++)
{
inActiveQFrames += mBufferQueueActive->GetBufferFrameCount(i);
}
inActiveQFrames += mBufferQueueActive->GetCurrentFrame(mCurrentBufferIndex);
return inActiveQFrames + inInactiveQFrames;
}
UInt32 OALSource::GetQueueOffset(UInt32 inOffsetType)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::GetQueueOffset called - OALSource:GetQueueOffset = %ld:%d\n", (long int) mSelfToken, inOffsetType);
#endif
CAGuard::Locker sourceLock(mSourceLock);
switch (inOffsetType)
{
case kSecondsOffset:
return (FramesToSecondsInt(GetQueueFrameOffset()));
break;
case kSampleOffset:
return (GetQueueFrameOffset());
break;
case kByteOffset:
return (FramesToBytes(GetQueueFrameOffset()));
break;
default:
break;
}
return 0;
}
Float32 OALSource::GetQueueOffsetSecondsFloat()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::GetQueueOffsetSecondsFloat called - OALSource = %ld\n", (long int) mSelfToken);
#endif
CAGuard::Locker sourceLock(mSourceLock);
return (FramesToSecondsFloat(GetQueueFrameOffset()));
}
void OALSource::SetQueueOffset(UInt32 inOffsetType, Float32 inOffset)
{
#if LOG_VERBOSE
DebugMessageN3("OALSource::SetQueueOffset called - OALSource:inOffsetType:inOffset = %ld:%d:%f\n", (long int) mSelfToken, inOffsetType, inOffset);
#endif
#if LOG_PLAYBACK
DebugMessageN1("OALSource::SetQueueOffset - OALSource = %ld", (long int) mSelfToken);
#endif
UInt32 frameOffset = 0;
if (inOffset < 0.0f)
throw (OSStatus)AL_INVALID_VALUE;
OALRenderLocker::RenderLocker locked(mRenderLocker, InRenderThread());
CAGuard::Locker sourceLock(mSourceLock);
switch (inOffsetType)
{
case kSecondsOffset:
frameOffset = SecondsToFrames(inOffset);
break;
case kSampleOffset:
frameOffset = (UInt32) inOffset; break;
case kByteOffset:
frameOffset = BytesToFrames(inOffset);
break;
default:
return;
break;
}
switch (mState)
{
case AL_INITIAL:
case AL_STOPPED:
case AL_PAUSED:
{
Rewind(); AdvanceQueueToFrameIndex(frameOffset);
}
break;
case AL_PLAYING:
case kTransitionToStop:
case kTransitionToRewind:
case kTransitionToPause:
case kTransitionToResume:
case kTransitionToRetrigger:
case kTransitionToPlay:
{
if (frameOffset > mBufferQueueActive->GetQueueSizeInFrames())
throw (OSStatus)AL_INVALID_VALUE;
mRampState = kRampDown;
mPlaybackHeadPosition = frameOffset;
#if LOG_MESSAGE_QUEUE
DebugMessageN1("OALSource::SetQueueOffset - kMQ_SetFramePosition added to MQ - OALSource = %ld", (long int) mSelfToken);
#endif
AddPlaybackMessage(kMQ_SetFramePosition, NULL, 0);
break;
}
default:
break;
}
}
void OALSource::AdvanceQueueToFrameIndex(UInt32 inFrameOffset)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::AdvanceQueueToFrameIndex called - OALSource:inFrameOffset = %ld:%d", (long int) mSelfToken, inFrameOffset);
#endif
UInt32 totalQueueFrames = mBufferQueueActive->GetQueueSizeInFrames();
if (inFrameOffset > totalQueueFrames)
throw (OSStatus)AL_INVALID_VALUE;
UInt32 frameStartOfCurrentBuffer = 0;
UInt32 count = mBufferQueueActive->GetQueueSize();
for (UInt32 i = 0; i < count; i++)
{
BufferInfo* curBufferInfo = mBufferQueueActive->Get(0); UInt32 bufferFrameCount = curBufferInfo->mBuffer->GetFrameCount();
if (frameStartOfCurrentBuffer + bufferFrameCount > inFrameOffset)
{
mBufferQueueActive->SetFirstBufferOffset(inFrameOffset - frameStartOfCurrentBuffer) ;
break; }
else
{
mBufferQueueActive->SetBufferAsProcessed(0);
mBufferQueueActive->RemoveQueueEntryByIndex(this, 0, false);
mBufferQueueInactive->AppendBuffer(this, curBufferInfo->mBufferToken, curBufferInfo->mBuffer, curBufferInfo->mACToken);
SetQueueLength();
if (mSourceNotifications)
mSourceNotifications->CallSourceNotifications(AL_BUFFERS_PROCESSED);
}
frameStartOfCurrentBuffer += bufferFrameCount;
}
return;
}
#pragma mark ***** Source Notify Ext*****
ALenum OALSource::AddNotification(ALuint notificationID, alSourceNotificationProc notifyProc, ALvoid* userData)
{
#if LOG_VERBOSE
DebugMessageN4("OALSource::AddNotification called - OALSource:notificationID:notifyProc:userData = %ld:%ld:%p:%p\n", (long int) mSelfToken, (long int) notificationID, notifyProc, userData);
#endif
ALenum err = AL_NO_ERROR;
if (mSourceNotifications == NULL)
mSourceNotifications = new SourceNotifications(mSelfToken);
err = mSourceNotifications->AddSourceNotification(notificationID, notifyProc, userData);
return err;
}
void OALSource::RemoveNotification(ALuint notificationID, alSourceNotificationProc notifyProc, ALvoid* userData)
{
#if LOG_VERBOSE
DebugMessageN4("OALSource::RemoveNotification called - OALSource:notificationID:notifyProc:userData = %ld:%ld:%p:%p\n", (long int) mSelfToken, (long int) notificationID, notifyProc, userData);
#endif
if (mSourceNotifications == NULL)
return;
mSourceNotifications->RemoveSourceNotification(notificationID, notifyProc, userData);
}
void CallSourceNotification(void* inMessage)
{
#if LOG_VERBOSE
DebugMessage("OALSource::CallSourceNotification called");
#endif
SourceNotificationDispatchMessage* message = (SourceNotificationDispatchMessage*) inMessage;
message->mProc(message->mSourceToken, message->mID, message->mUserData);
message->flagForDeletion = true;
}
#pragma mark ***** PRIVATE *****
void OALSource::SwapBufferQueues()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::SwapBufferQueues called - OALSource = %ld\n", (long int) mSelfToken);
#endif
BufferQueue* tQ = mBufferQueueActive;
mBufferQueueActive = mBufferQueueInactive;
mBufferQueueInactive = tQ;
mBufferQueueActive->SetQueueSize();
mBufferQueueInactive->SetQueueSize();
SetQueueLength();
mBufferQueueActive->ResetBuffers(); mCurrentBufferIndex = 0; mQueueIsProcessed = false;
}
void OALSource::AddPlaybackMessage(UInt32 inMessage, OALBuffer* inDeferredAppendBuffer, UInt32 inBuffersToUnqueue)
{
#if LOG_VERBOSE
DebugMessageN4("OALSource::AddPlaybackMessage called - OALSource:inMessage:inDeferredAppendBuffer:inBuffersToUnqueue = %ld:%ld:%p:%ld\n", (long int) mSelfToken, (long int) inMessage, inDeferredAppendBuffer, (long int) inBuffersToUnqueue);
#endif
PlaybackMessage* pbm = new PlaybackMessage((UInt32) inMessage, inDeferredAppendBuffer, inBuffersToUnqueue);
mMessageQueue.push_atomic(pbm);
}
void OALSource::ClearMessageQueue()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::ClearMessageQueue called - OALSource = %ld\n", (long int) mSelfToken);
#endif
PlaybackMessage *messages = mMessageQueue.pop_all_reversed();
while (messages != NULL)
{
PlaybackMessage *lastMessage = messages;
messages = messages->next();
delete (lastMessage); }
}
void OALSource::SetPlaybackState(ALuint inState, bool sendSourceStateChangeNotification)
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::SetPlaybackState called - OALSource = %ld\n", (long int) mSelfToken);
#endif
#if LOG_PLAYBACK
DebugMessageN2("OALSource::SetPlaybackState called - inState = %d - OALSource = %ld", inState, (long int) mSelfToken);
#endif
mState = inState;
if (mSourceNotifications && sendSourceStateChangeNotification)
mSourceNotifications->CallSourceNotifications(AL_SOURCE_STATE);
}
#pragma mark ***** Buffer Queue Methods *****
void OALSource::ClearActiveQueue()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::ClearActiveQueue called - OALSource = %ld\n", (long int) mSelfToken);
#endif
while (mBufferQueueActive->GetQueueSize() > 0)
{
BufferInfo *staleBufferInfo = mBufferQueueActive->Get(0);
if (staleBufferInfo)
{
mBufferQueueActive->SetBufferAsProcessed(0);
mBufferQueueInactive->AppendBuffer(this, staleBufferInfo->mBufferToken, staleBufferInfo->mBuffer, staleBufferInfo->mACToken);
mBufferQueueActive->RemoveQueueEntryByIndex(this, 0, false);
SetQueueLength();
}
}
mCurrentBufferIndex = 0;
mQueueIsProcessed = false;
}
void OALSource::LoopToBeginning()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::LoopToBeginning called - OALSource = %ld\n", (long int) mSelfToken);
#endif
ClearActiveQueue();
SwapBufferQueues();
if ((mSourceNotifications) && mLooping)
mSourceNotifications->CallSourceNotifications(AL_QUEUE_HAS_LOOPED);
}
void OALSource::JoinBufferLists()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::JoinBufferLists called - OALSource = %ld\n", (long int) mSelfToken);
#endif
ClearActiveQueue();
SwapBufferQueues();
return;
}
void OALSource::UpdateQueue ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::UpdateQueue called - OALSource = %ld\n", (long int) mSelfToken);
#endif
if (mCurrentBufferIndex > 0)
{
BufferInfo *bufferInfo = NULL;
for (UInt32 i = 0; i < mCurrentBufferIndex; i++)
{
bufferInfo = mBufferQueueActive->Get(0);
if (bufferInfo)
{
mBufferQueueInactive->AppendBuffer(this, bufferInfo->mBufferToken, bufferInfo->mBuffer, bufferInfo->mACToken);
mBufferQueueActive->RemoveQueueEntryByIndex(this, 0, false);
SetQueueLength();
if (mSourceNotifications)
mSourceNotifications->CallSourceNotifications(AL_BUFFERS_PROCESSED);
}
}
mCurrentBufferIndex = 0;
}
}
bool OALSource::IsSourceTransitioningToFlushQ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::IsSourceTransitioningToFlushQ called - OALSource = %ld\n", (long int) mSelfToken);
#endif
return mTransitioningToFlushQ;
}
#pragma mark ***** Mixer Bus Methods *****
void OALSource::DisconnectFromBus()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::DisconnectFromBus called - OALSource = %ld\n", (long int) mSelfToken);
#endif
try {
ReleaseNotifyAndRenderProcs();
OSStatus result = noErr;
if(mRogerBeepNode || mDistortionNode)
{
if(mRogerBeepNode && mDistortionNode)
result = AUGraphDisconnectNodeInput(mOwningContext->GetGraph(), mRogerBeepNode, 0);
result = AUGraphDisconnectNodeInput(mOwningContext->GetGraph(), mOwningContext->GetMixerNode(), mCurrentPlayBus);
result = AUGraphUpdate(mOwningContext->GetGraph(), NULL);
}
if (mCurrentPlayBus != kSourceNeedsBus)
{
mOwningContext->SetBusAsAvailable (mCurrentPlayBus);
mCurrentPlayBus = kSourceNeedsBus;
}
}
catch (OSStatus result) {
}
}
void OALSource::ChangeChannelSettings()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::ChangeChannelSettings called - OALSource = %ld\n", (long int) mSelfToken);
#endif
#if CALCULATE_POSITION
bool coneGainChange = false;
bool attenuationGainChange = false;
if (mCalculateDistance == true)
{
BufferInfo *bufferInfo = mBufferQueueActive->Get(mCurrentBufferIndex);
if (bufferInfo)
{
#if LOG_GRAPH_AND_MIXER_CHANGES
DebugMessageN1("OALSource::ChangeChannelSettings: k3DMixerParam_Azimuth/k3DMixerParam_Distance called - OALSource = %ld\n", mSelfToken);
#endif
if ( bufferInfo->mBuffer->GetNumberChannels() == 1)
{
Float32 rel_azimuth, rel_distance, rel_elevation, dopplerShift;
CalculateDistanceAndAzimuth(&rel_distance, &rel_azimuth, &rel_elevation, &dopplerShift);
if (dopplerShift != mDopplerScaler)
{
mDopplerScaler = dopplerShift;
mResetPitch = true;
}
AudioUnitSetParameter(mOwningContext->GetMixerUnit(), k3DMixerParam_Azimuth, kAudioUnitScope_Input, mCurrentPlayBus, rel_azimuth, 0);
AudioUnitSetParameter(mOwningContext->GetMixerUnit(), k3DMixerParam_Elevation, kAudioUnitScope_Input, mCurrentPlayBus, rel_elevation, 0);
mAttenuationGainScaler = 1.0;
if (!mOwningContext->DoSetDistance())
{
AudioUnitSetParameter(mOwningContext->GetMixerUnit(), k3DMixerParam_Distance, kAudioUnitScope_Input, mCurrentPlayBus, mReferenceDistance, 0);
switch (mOwningContext->GetDistanceModel())
{
case AL_LINEAR_DISTANCE:
case AL_LINEAR_DISTANCE_CLAMPED:
if (mOwningContext->GetDistanceModel() == AL_LINEAR_DISTANCE_CLAMPED)
{
if (rel_distance < mReferenceDistance) rel_distance = mReferenceDistance;
if (rel_distance > mMaxDistance) rel_distance = mMaxDistance;
}
mAttenuationGainScaler = (1 - mRollOffFactor * (rel_distance - mReferenceDistance) / (mMaxDistance-mReferenceDistance));
DebugMessageN1("AL_LINEAR_DISTANCE scaler = %f\n", mAttenuationGainScaler);
attenuationGainChange = true;
break;
case AL_EXPONENT_DISTANCE:
case AL_EXPONENT_DISTANCE_CLAMPED:
if (mOwningContext->GetDistanceModel() == AL_EXPONENT_DISTANCE_CLAMPED)
{
if (rel_distance < mReferenceDistance) rel_distance = mReferenceDistance;
if (rel_distance > mMaxDistance) rel_distance = mMaxDistance;
}
mAttenuationGainScaler = pow((rel_distance / mReferenceDistance), (-mRollOffFactor));
DebugMessageN1("AL_EXPONENT_DISTANCE scaler = %f\n", mAttenuationGainScaler);
attenuationGainChange = true;
break;
case AL_NONE:
mAttenuationGainScaler = 1.0;
break; }
}
else
{
if (mOwningContext->IsDistanceScalingRequired()) rel_distance *= (kDistanceScalar/mMaxDistance);
AudioUnitSetParameter(mOwningContext->GetMixerUnit(), k3DMixerParam_Distance, kAudioUnitScope_Input, mCurrentPlayBus, rel_distance, 0);
}
coneGainChange = ConeAttenuation();
}
}
mCalculateDistance = false;
}
#endif // end CALCULATE_POSITION
UpdateBusGain();
SetPitch (mPitch);
UpdateBusFormat();
}
void OALSource::UpdateBusGain ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::UpdateBusGain called - OALSource = %ld\n", (long int) mSelfToken);
#endif
if (mCurrentPlayBus != kSourceNeedsBus)
{
Float32 busGain = mGain;
busGain *= mConeGainScaler;
busGain *= mAttenuationGainScaler;
if (busGain > 1.0)
busGain = 1.0;
else if (busGain < 0.0)
busGain = 0.0;
mOutputSilence = busGain > 0.0 ? false : true;
if (busGain > 0.0)
{
Float32 db = 20.0 * log10(busGain); if (db < -120.0)
db = -120.0;
OSStatus result = AudioUnitSetParameter ( mOwningContext->GetMixerUnit(), k3DMixerParam_Gain, kAudioUnitScope_Input, mCurrentPlayBus, db, 0);
THROW_RESULT
}
}
}
void OALSource::UpdateMinBusGain ()
{
#if VERBOSE
DebugMessageN1("OALSource::UpdateMinBusGain called - OALSource = %ld", (long int) mSelfToken);
#endif
if (mCurrentPlayBus != kSourceNeedsBus)
{
OSStatus result = AudioUnitSetParameter ( mOwningContext->GetMixerUnit(), k3DMixerParam_MinGain, kAudioUnitScope_Input, mCurrentPlayBus, mMinGain, 0);
THROW_RESULT
}
}
void OALSource::UpdateMaxBusGain ()
{
#if VERBOSE
DebugMessageN1("OALSource::UpdateMaxBusGain called - OALSource = %ld", (long int) mSelfToken);
#endif
if (mCurrentPlayBus != kSourceNeedsBus)
{
OSStatus result = AudioUnitSetParameter ( mOwningContext->GetMixerUnit(), k3DMixerParam_MaxGain, kAudioUnitScope_Input, mCurrentPlayBus, mMaxGain, 0);
THROW_RESULT
}
}
void OALSource::UpdateBusFormat ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::UpdateBusFormat - OALSource = %ld\n", (long int) mSelfToken);
#endif
if (Get3DMixerVersion() < k3DMixerVersion_2_0) return;
if (mResetBusFormat)
{
CAStreamBasicDescription desc;
UInt32 propSize = sizeof(desc);
OSStatus result = AudioUnitGetProperty(mOwningContext->GetMixerUnit(), kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, mCurrentPlayBus, &desc, &propSize);
if (result == noErr)
{
BufferInfo *buffer = mBufferQueueActive->Get(mCurrentBufferIndex);
if (buffer != NULL)
{
desc.mSampleRate = buffer->mBuffer->GetSampleRate();
AudioUnitSetProperty(mOwningContext->GetMixerUnit(), kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, mCurrentPlayBus, &desc, sizeof(desc));
mResetBusFormat = false;
}
}
}
}
void OALSource::UpdateBusReverb ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::UpdateBusReverb - OALSource = %ld\n", (long int) mSelfToken);
#endif
if (mCurrentPlayBus != kSourceNeedsBus)
{
if (mOwningContext->GetReverbState() == 0) return;
AudioUnitSetParameter(mOwningContext->GetMixerUnit(), 5 , kAudioUnitScope_Input, mCurrentPlayBus, mASAReverbSendLevel * 100.0, 0);
}
}
void OALSource::UpdateBusOcclusion ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::UpdateBusOcclusion - OALSource = %ld\n", (long int) mSelfToken);
#endif
if (mCurrentPlayBus != kSourceNeedsBus)
{
if (Get3DMixerVersion() < k3DMixerVersion_2_2) return;
AudioUnitSetParameter(mOwningContext->GetMixerUnit(), 7 , kAudioUnitScope_Input, mCurrentPlayBus, mASAOcclusion, 0);
}
}
void OALSource::UpdateBusObstruction ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::UpdateBusObstruction - OALSource = %ld\n", (long int) mSelfToken);
#endif
if (mCurrentPlayBus != kSourceNeedsBus)
{
if (Get3DMixerVersion() < k3DMixerVersion_2_2) return;
AudioUnitSetParameter(mOwningContext->GetMixerUnit(), 8 , kAudioUnitScope_Input, mCurrentPlayBus, mASAObstruction, 0);
}
}
#pragma mark ***** Render Proc Methods *****
void OALSource::AddNotifyAndRenderProcs()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::AddNotifyAndRenderProcs - OALSource = %ld\n", (long int) mSelfToken);
#endif
if (mCurrentPlayBus == kSourceNeedsBus)
return;
OSStatus result = noErr;
mPlayCallback.inputProc = SourceInputProc;
mPlayCallback.inputProcRefCon = this;
result = AudioUnitSetProperty ( mRenderUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
mRenderElement, &mPlayCallback, sizeof(mPlayCallback));
THROW_RESULT
}
void OALSource::ReleaseNotifyAndRenderProcs()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::ReleaseNotifyAndRenderProcs - OALSource = %ld\n", (long int) mSelfToken);
#endif
OSStatus result = noErr;
mPlayCallback.inputProc = 0;
mPlayCallback.inputProcRefCon = 0;
result = AudioUnitSetProperty ( mRenderUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
mRenderElement, &mPlayCallback, sizeof(mPlayCallback));
THROW_RESULT
}
#if USE_AU_TRACER
static UInt32 tracerStart = 0xca3d0000;
static UInt32 tracerEnd = 0xca3d0004;
#include <sys/syscall.h>
#include <unistd.h>
#endif
OSStatus OALSource::SourceInputProc ( void *inRefCon,
AudioUnitRenderActionFlags *inActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
#if LOG_VERBOSE
DebugMessage("OALSource::ReleaseNotifyAndRenderProcs");
#endif
OALSource* THIS = (OALSource*)inRefCon;
THIS->SetInUseFlag();
if (THIS->mOutputSilence)
*inActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
else
*inActionFlags &= 0xEF;
#if USE_AU_TRACER
syscall(180, tracerStart, inBusNumber, ioData->mNumberBuffers, 0, 0);
#endif
OSStatus result = noErr;
if (Get3DMixerVersion() >= k3DMixerVersion_2_0)
result = THIS->DoRender (ioData); else
result = THIS->DoSRCRender (ioData);
#if USE_AU_TRACER
syscall(180, tracerEnd, inBusNumber, ioData->mNumberBuffers, 0, 0);
#endif
THIS->ClearInUseFlag();
return (result);
}
OSStatus OALSource::DoPreRender ()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::DoPreRender - OALSource = %ld\n", (long int) mSelfToken);
#endif
BufferInfo *bufferInfo = NULL;
OSStatus err = noErr;
OALRenderLocker::RenderTryer tried(mRenderLocker);
if (!tried.Acquired())
return err;
bufferInfo = mBufferQueueActive->Get(mCurrentBufferIndex);
if (bufferInfo == NULL)
{
mQueueIsProcessed = true;
err = -1; }
return (err);
}
OSStatus OALSource::ACComplexInputDataProc ( AudioConverterRef inAudioConverter,
UInt32 *ioNumberDataPackets,
AudioBufferList *ioData,
AudioStreamPacketDescription **outDataPacketDescription,
void* inUserData)
{
#if LOG_VERBOSE
DebugMessage("OALSource::DoPreRender - OALSource = %ld\n");
#endif
OSStatus err = noErr;
OALSource* THIS = (OALSource*)inUserData;
BufferInfo *bufferInfo = THIS->mBufferQueueActive->Get(THIS->mCurrentBufferIndex);
UInt32 sourcePacketsLeft = 0;
if (bufferInfo == NULL)
{
ioData->mBuffers[0].mData = NULL; ioData->mBuffers[0].mDataByteSize = 0; *ioNumberDataPackets = 0;
return -1;
}
sourcePacketsLeft = (bufferInfo->mBuffer->GetDataSize() - bufferInfo->mOffset) / bufferInfo->mBuffer->GetBytesPerPacket();
if (sourcePacketsLeft == 0)
{
bufferInfo->mProcessedState = kProcessed; bufferInfo->mOffset = 0;
THIS->mCurrentBufferIndex++;
BufferInfo *nextBufferInfo = THIS->NextPlayableBufferInActiveQ();
if ((nextBufferInfo != NULL) || (THIS->mLooping == true))
{
if (nextBufferInfo == NULL)
{
THIS->LoopToBeginning();
}
err = OALSourceError_CallConverterAgain;
}
else
{
THIS->mBufferQueueActive->SetBufferAsProcessed(THIS->mCurrentBufferIndex);
THIS->mQueueIsProcessed = true; }
ioData->mBuffers[0].mData = NULL; ioData->mBuffers[0].mDataByteSize = 0; *ioNumberDataPackets = 0;
}
else
{
if (sourcePacketsLeft < *ioNumberDataPackets)
*ioNumberDataPackets = sourcePacketsLeft;
ioData->mBuffers[0].mData = bufferInfo->mBuffer->GetDataPtr() + bufferInfo->mOffset; ioData->mBuffers[0].mDataByteSize = *ioNumberDataPackets * bufferInfo->mBuffer->GetBytesPerPacket();
bufferInfo->mOffset += ioData->mBuffers[0].mDataByteSize;
}
return (err);
}
BufferInfo* OALSource::NextPlayableBufferInActiveQ(){
#if LOG_VERBOSE
DebugMessageN1("OALSource::NextPlayableBufferInActiveQ - OALSource = %ld\n", (long int) mSelfToken);
#endif
BufferInfo* bufferInfo = NULL;
bool done = false;
while (!done)
{
bufferInfo = mBufferQueueActive->Get(mCurrentBufferIndex);
if (bufferInfo == NULL)
{
done = true; }
else if (bufferInfo->mBufferToken == AL_NONE)
{
bufferInfo->mProcessedState = kProcessed; mCurrentBufferIndex++;
}
else if (bufferInfo->mBuffer->GetDataPtr() == NULL)
{
bufferInfo->mProcessedState = kProcessed; mCurrentBufferIndex++;
}
else
return bufferInfo;
}
return NULL;
}
OSStatus OALSource::DoRender (AudioBufferList *ioData)
{
OSStatus err = noErr;
UInt32 packetsRequestedFromRenderProc = ioData->mBuffers[0].mDataByteSize / sizeof(Float32);
UInt32 packetsObtained = 0;
UInt32 packetCount;
struct {
AudioBufferList abl;
AudioBuffer buffer;
}t;
AudioBufferList * tBufferList = (AudioBufferList *) &t.abl;
UInt32 dataByteSize = ioData->mBuffers[0].mDataByteSize;
BufferInfo *bufferInfo = NULL;
tBufferList->mNumberBuffers = ioData->mNumberBuffers;
tBufferList->mBuffers[0].mNumberChannels = ioData->mBuffers[0].mNumberChannels;
tBufferList->mBuffers[0].mDataByteSize = ioData->mBuffers[0].mDataByteSize;
tBufferList->mBuffers[0].mData = ioData->mBuffers[0].mData;
if (tBufferList->mNumberBuffers > 1)
{
tBufferList->mBuffers[1].mNumberChannels = ioData->mBuffers[1].mNumberChannels;
tBufferList->mBuffers[1].mDataByteSize = ioData->mBuffers[1].mDataByteSize;
tBufferList->mBuffers[1].mData = ioData->mBuffers[1].mData;
}
OALRenderLocker::RenderTryer tried(mRenderLocker);
if (!tried.Acquired())
{
for (UInt32 i = 0; i < ioData->mNumberBuffers; i++)
memset(ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize);
return noErr;
}
if(mResetBus)
{
ResetMixerBus();
mResetBus = false;
}
UpdateQueue();
bufferInfo = NextPlayableBufferInActiveQ();
if ((bufferInfo == NULL) && (mLooping == true))
{
SwapBufferQueues();
bufferInfo = NextPlayableBufferInActiveQ(); if (bufferInfo == NULL)
goto Finished;
if (mSourceNotifications)
mSourceNotifications->CallSourceNotifications(AL_QUEUE_HAS_LOOPED);
}
else if (bufferInfo == NULL)
{
mQueueIsProcessed = true;
goto Finished; }
ChangeChannelSettings();
while ((packetsObtained < packetsRequestedFromRenderProc) && (mQueueIsProcessed == false))
{
BufferInfo *bufferInfo = NextPlayableBufferInActiveQ(); if (bufferInfo == NULL)
{
mQueueIsProcessed = true;
goto Finished;
}
bufferInfo->mProcessedState = kInProgress;
UInt32 byteCount = packetsObtained * sizeof(Float32);
tBufferList->mBuffers[0].mDataByteSize = dataByteSize - byteCount;
tBufferList->mBuffers[0].mData = (Byte *) ioData->mBuffers[0].mData + byteCount;
if (tBufferList->mNumberBuffers > 1)
{
tBufferList->mBuffers[1].mDataByteSize = tBufferList->mBuffers[0].mDataByteSize;
tBufferList->mBuffers[1].mData = (Byte *) ioData->mBuffers[1].mData + byteCount;
}
if (bufferInfo->mBuffer->HasBeenConverted() == false)
{
AudioConverterRef converter = mACMap->Get(bufferInfo->mACToken);
packetCount = packetsRequestedFromRenderProc - packetsObtained;
err = AudioConverterFillComplexBuffer(converter, ACComplexInputDataProc, this, &packetCount, tBufferList, NULL);
packetsObtained += packetCount;
if (mQueueIsProcessed == true)
{
AudioConverterReset(converter);
}
else if ((packetsObtained < packetsRequestedFromRenderProc) && (err == noErr))
{
AudioConverterReset(converter);
}
}
else
{
UInt32 bytesRemaining = bufferInfo->mBuffer->GetDataSize() - bufferInfo->mOffset;
UInt32 framesRemaining = bytesRemaining / sizeof(Float32);
UInt32 bytesToCopy = 0;
UInt32 framesToCopy = packetsRequestedFromRenderProc - packetsObtained;
if (framesRemaining < framesToCopy)
framesToCopy = framesRemaining;
bytesToCopy = framesToCopy * sizeof(Float32);
memcpy(tBufferList->mBuffers->mData, bufferInfo->mBuffer->GetDataPtr() + bufferInfo->mOffset, bytesToCopy);
bufferInfo->mOffset += bytesToCopy;
packetsObtained += framesToCopy;
if (bufferInfo->mOffset == bufferInfo->mBuffer->GetDataSize())
{
mCurrentBufferIndex++;
BufferInfo *nextBufferInfo = NextPlayableBufferInActiveQ(); if ((nextBufferInfo != NULL) || (mLooping == true))
{
if (nextBufferInfo == NULL)
LoopToBeginning();
}
else
{
mQueueIsProcessed = true; }
}
}
}
Finished:
if (packetsObtained < packetsRequestedFromRenderProc)
{
UInt32 byteCount = packetsObtained * sizeof(Float32);
tBufferList->mBuffers[0].mDataByteSize = dataByteSize - byteCount;
tBufferList->mBuffers[0].mData = (Byte *) ioData->mBuffers[0].mData + byteCount;
memset(tBufferList->mBuffers[0].mData, 0, tBufferList->mBuffers[0].mDataByteSize);
if (tBufferList->mNumberBuffers > 1)
{
tBufferList->mBuffers[1].mDataByteSize = tBufferList->mBuffers[0].mDataByteSize;
tBufferList->mBuffers[1].mData = (Byte *) ioData->mBuffers[1].mData + byteCount;
memset(tBufferList->mBuffers[1].mData, 0, tBufferList->mBuffers[1].mDataByteSize);
}
}
if (mRampState == kRampDown)
{
RampDown(ioData);
mRampState = kRampingComplete;
}
else if (mRampState == kRampUp)
{
RampUp(ioData);
mRampState = kRampingComplete;
}
return (noErr);
}
OSStatus OALSource::DoPostRender ()
{
bool renderProcsRemoved = false;
PlaybackMessage* lastMessage;
OALRenderLocker::RenderTryer tried(mRenderLocker);
if (!tried.Acquired())
return noErr;
try {
if (mRampState == kRampingComplete)
{
#if LOG_MESSAGE_QUEUE
DebugMessageN1("FLUSHING MESSAGE QUEUE START - OALSource = %ld", (long int) mSelfToken);
#endif
PlaybackMessage *messages = mMessageQueue.pop_all_reversed();
while (messages != NULL)
{
switch (messages->mMessageID)
{
case kMQ_Stop:
#if LOG_MESSAGE_QUEUE
DebugMessage(" MQ:kMQ_Stop");
#endif
if (mState != AL_STOPPED)
{
DisconnectFromBus();
SetPlaybackState(AL_STOPPED, true);
UInt32 count = mBufferQueueActive->GetQueueSize();
ClearActiveQueue();
if((count > 0) && mSourceNotifications)
{
mSourceNotifications->CallSourceNotifications(AL_BUFFERS_PROCESSED);
}
}
break;
case kMQ_Retrigger:
#if LOG_MESSAGE_QUEUE
DebugMessage(" MQ:kMQ_Retrigger");
#endif
LoopToBeginning();
if (renderProcsRemoved)
{
AddNotifyAndRenderProcs();
renderProcsRemoved = false;
}
if (mState != AL_PLAYING) {
SetPlaybackState(AL_PLAYING, true);
}
break;
case kMQ_Rewind:
#if LOG_MESSAGE_QUEUE
DebugMessage(" MQ:kMQ_Rewind");
#endif
if (mState != AL_INITIAL)
{
JoinBufferLists();
DisconnectFromBus();
SetPlaybackState(AL_INITIAL, true);
mQueueIsProcessed = false;
}
break;
case kMQ_ClearBuffersFromQueue:
#if LOG_MESSAGE_QUEUE
DebugMessage(" MQ:kMQ_ClearBuffersFromQueue");
#endif
PostRenderRemoveBuffersFromQueue(messages->mBuffersToUnqueueInPostRender);
break;
case kMQ_SetBuffer:
#if LOG_MESSAGE_QUEUE
DebugMessageN1(" MQ:kMQ_SetBuffer: mAppendBuffer->GetToken() = %ld", (long int) messages->mAppendBuffer->GetToken());
#endif
PostRenderSetBuffer(messages->mAppendBuffer->GetToken(), messages->mAppendBuffer);
SetPlaybackState(AL_STOPPED, true);
break;
case kMQ_Play:
#if LOG_MESSAGE_QUEUE
DebugMessage(" MQ:kMQ_Play");
#endif
Play();
break;
case kMQ_Pause:
#if LOG_MESSAGE_QUEUE
DebugMessage(" MQ:kMQ_Pause");
#endif
SetPlaybackState(AL_PAUSED, true);
ReleaseNotifyAndRenderProcs();
renderProcsRemoved = true;
break;
case kMQ_SetFramePosition:
#if LOG_MESSAGE_QUEUE
DebugMessage(" MQ:kMQ_SetFramePosition");
#endif
LoopToBeginning();
AdvanceQueueToFrameIndex(mPlaybackHeadPosition);
mPlaybackHeadPosition = 0;
break;
case kMQ_DeconstructionStop:
{
#if LOG_MESSAGE_QUEUE
DebugMessage(" MQ:kMQ_DeconstructionStop");
#endif
DisconnectFromBus();
SetPlaybackState(AL_STOPPED, true);
FlushBufferQueue(); mSafeForDeletion = true;
ClearMessageQueue();
goto Finished; }
}
lastMessage = messages;
messages = messages->next();
delete (lastMessage); }
mRampState = kNoRamping;
#if LOG_MESSAGE_QUEUE
DebugMessageN1("FLUSHING MESSAGE QUEUE END - OALSource = %ld", (long int) mSelfToken);
#endif
}
Finished:
if (mQueueIsProcessed)
{
DisconnectFromBus();
SetPlaybackState(AL_STOPPED,true);
UInt32 count = mBufferQueueActive->GetQueueSize();
ClearActiveQueue();
if((count > 0) && mSourceNotifications)
{
mSourceNotifications->CallSourceNotifications(AL_BUFFERS_PROCESSED);
}
}
}
catch(...){
DebugMessageN1("OALSource::DoPostRender:ERROR - OALSource = %ld", (long int) mSelfToken);
}
return noErr;
}
void OALSource::RampDown (AudioBufferList *ioData)
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::RampDown - OALSource = %ld\n", (long int) mSelfToken);
#endif
UInt32 sampleCount = (ioData->mBuffers[0].mDataByteSize / sizeof (Float32));
Float32 slope = 1.0/sampleCount;
for (UInt32 i = 0; i < ioData->mNumberBuffers; i++)
{
Float32 scalar = 1.0;
Float32 *sample = (Float32*) ioData->mBuffers[i].mData;
for (UInt32 count = sampleCount; count > 0 ; count--)
{
*sample *= scalar;
scalar -= slope;
sample++;
}
}
}
void OALSource::RampUp (AudioBufferList *ioData)
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::RampUp - OALSource = %ld\n", (long int) mSelfToken);
#endif
UInt32 sampleCount = (ioData->mBuffers[0].mDataByteSize / sizeof (Float32));
Float32 slope = 1.0/sampleCount;
for (UInt32 i = 0; i < ioData->mNumberBuffers; i++)
{
Float32 scalar = 0.0;
Float32 *sample = (Float32*) ioData->mBuffers[i].mData;
for (UInt32 count = sampleCount; count > 0 ; count--)
{
*sample *= scalar;
scalar += slope;
sample++;
}
}
}
OSStatus OALSource::DoSRCRender( AudioBufferList *ioData )
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::DoSRCRender - OALSource = %ld\n", (long int) mSelfToken);
#endif
BufferInfo *bufferInfo = NULL;
OALRenderLocker::RenderTryer tried(mRenderLocker);
if (!tried.Acquired())
{
for (UInt32 i = 0; i < ioData->mNumberBuffers; i++)
memset(ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize);
return noErr;
}
if(mResetBus)
{
ResetMixerBus();
mResetBus = false;
}
bufferInfo = NextPlayableBufferInActiveQ();
if (bufferInfo == NULL)
{
mQueueIsProcessed = true;
return -1; }
UpdateQueue();
bufferInfo = mBufferQueueActive->Get(mCurrentBufferIndex);
if ((bufferInfo == NULL) && (mLooping == true))
{
SwapBufferQueues();
if (mSourceNotifications)
mSourceNotifications->CallSourceNotifications(AL_QUEUE_HAS_LOOPED);
}
else if (bufferInfo == NULL)
{
mQueueIsProcessed = true;
return -1; }
ChangeChannelSettings();
double srcSampleRate; srcSampleRate = bufferInfo->mBuffer->GetSampleRate();
double dstSampleRate; dstSampleRate = mOwningContext->GetMixerRate();
double ratio; ratio = (srcSampleRate / dstSampleRate) * mPitch * mDopplerScaler;
int nchannels; nchannels = ioData->mNumberBuffers;
if (ratio == 1.0)
{
return (DoRender(ioData));
}
UInt32 inFramesToProcess; inFramesToProcess = ioData->mBuffers[0].mDataByteSize / sizeof(Float32);
float readIndex; readIndex = mReadIndex;
int readUntilIndex; readUntilIndex = (int) (2.0 + readIndex + inFramesToProcess * ratio );
int framesToPull; framesToPull = readUntilIndex - 2;
if (framesToPull == 0)
return -1;
mTempSourceStorage->mBuffers[0].mDataByteSize = framesToPull * sizeof(UInt32);
mTempSourceStorage->mBuffers[1].mDataByteSize = framesToPull * sizeof(UInt32);
if (mTempSourceStorageBufferSize < (framesToPull * sizeof(UInt32)))
{
if (mTempSourceStorage->mBuffers[0].mData != NULL)
free(mTempSourceStorage->mBuffers[0].mData);
if (mTempSourceStorage->mBuffers[1].mData != NULL)
free(mTempSourceStorage->mBuffers[1].mData);
mTempSourceStorageBufferSize = (framesToPull * sizeof(UInt32));
mTempSourceStorage->mBuffers[0].mData = malloc(mTempSourceStorageBufferSize);
mTempSourceStorage->mBuffers[1].mData = malloc(mTempSourceStorageBufferSize);
}
mTempSourceStorage->mNumberBuffers = ioData->mNumberBuffers;
for (UInt32 i = 0; i < mTempSourceStorage->mNumberBuffers; i++)
{
mTempSourceStorage->mBuffers[i].mDataByteSize = framesToPull * sizeof(UInt32);
}
OSStatus result; result = DoRender(mTempSourceStorage);
if (result != noErr )
return result;
float *pullL; pullL = (float *) mTempSourceStorage->mBuffers[0].mData;
float *pullR; pullR = nchannels > 1 ? (float *) mTempSourceStorage->mBuffers[1].mData: NULL;
float tempL[4];
float tempR[4];
tempL[0] = mCachedInputL1;
tempL[1] = mCachedInputL2;
tempL[2] = pullL[0];
if (pullR)
{
tempR[0] = mCachedInputR1;
tempR[1] = mCachedInputR2;
tempR[2] = pullR[0];
}
float *sourceL; sourceL = tempL;
float *sourceR; sourceR = tempR;
if(!pullR)
sourceR = NULL;
mCachedInputL1 = pullL[framesToPull - 2];
mCachedInputL2 = pullL[framesToPull - 1];
if(pullR)
{
mCachedInputR1 = pullR[framesToPull - 2];
mCachedInputR2 = pullR[framesToPull - 1];
}
int n; n = inFramesToProcess;
float *destL; destL = (float *) ioData->mBuffers[0].mData;
float *destR; destR = (float *) ioData->mBuffers[1].mData;
if (!sourceR)
{
while (readIndex < 2.0 && n > 0)
{
int iReadIndex = (int)readIndex;
int iReadIndex2 = iReadIndex + 1;
float frac = readIndex - float(iReadIndex);
float s1 = sourceL[iReadIndex];
float s2 = sourceL[iReadIndex2];
float left = s1 + frac * (s2-s1);
*destL++ = left;
readIndex += ratio;
n--;
}
readIndex -= 2.0;
sourceL = pullL;
while (n--)
{
int iReadIndex = (int)readIndex;
int iReadIndex2 = iReadIndex + 1;
float frac = readIndex - float(iReadIndex);
float s1 = sourceL[iReadIndex];
float s2 = sourceL[iReadIndex2];
float left = s1 + frac * (s2-s1);
*destL++ = left;
readIndex += ratio;
}
readIndex += 2.0;
}
else
{
while(readIndex < 2.0 && n > 0)
{
int iReadIndex = (int)readIndex;
int iReadIndex2 = iReadIndex + 1;
float frac = readIndex - float(iReadIndex);
float s1 = sourceL[iReadIndex];
float s2 = sourceL[iReadIndex2];
float left = s1 + frac * (s2-s1);
float s3 = sourceR[iReadIndex];
float s4 = sourceR[iReadIndex2];
float right = s3 + frac * (s4-s3);
*destL++ = left;
*destR++ = right;
readIndex += ratio;
n--;
}
readIndex -= 2.0;
sourceL = pullL;
sourceR = pullR;
while (n--)
{
int iReadIndex = (int)readIndex;
int iReadIndex2 = iReadIndex + 1;
float frac = readIndex - float(iReadIndex);
float s1 = sourceL[iReadIndex];
float s2 = sourceL[iReadIndex2];
float left = s1 + frac * (s2-s1);
float s3 = sourceR[iReadIndex];
float s4 = sourceR[iReadIndex2];
float right = s3 + frac * (s4-s3);
*destL++ = left;
*destR++ = right;
readIndex += ratio;
}
readIndex += 2.0;
}
readIndex -= float(framesToPull);
mReadIndex = readIndex;
return noErr;
}
Float32 MAG(ALfloat *inVector)
{
return sqrt(inVector[0] * inVector[0] + inVector[1] * inVector[1] + inVector[2] * inVector[2]);
}
void aluCrossproduct(ALfloat *inVector1,ALfloat *inVector2,ALfloat *outVector)
{
outVector[0]=(inVector1[1]*inVector2[2]-inVector1[2]*inVector2[1]);
outVector[1]=(inVector1[2]*inVector2[0]-inVector1[0]*inVector2[2]);
outVector[2]=(inVector1[0]*inVector2[1]-inVector1[1]*inVector2[0]);
}
Float32 aluDotproduct(ALfloat *inVector1,ALfloat *inVector2)
{
return (inVector1[0]*inVector2[0]+inVector1[1]*inVector2[1]+inVector1[2]*inVector2[2]);
}
void aluNormalize(ALfloat *inVector)
{
ALfloat length,inverse_length;
length=(ALfloat)sqrt(aluDotproduct(inVector,inVector));
if (length != 0)
{
inverse_length=(1.0f/length);
inVector[0]*=inverse_length;
inVector[1]*=inverse_length;
inVector[2]*=inverse_length;
}
}
void aluMatrixVector(ALfloat *vector,ALfloat matrix[3][3])
{
ALfloat result[3];
result[0]=vector[0]*matrix[0][0]+vector[1]*matrix[1][0]+vector[2]*matrix[2][0];
result[1]=vector[0]*matrix[0][1]+vector[1]*matrix[1][1]+vector[2]*matrix[2][1];
result[2]=vector[0]*matrix[0][2]+vector[1]*matrix[1][2]+vector[2]*matrix[2][2];
memcpy(vector,result,sizeof(result));
}
inline bool IsZeroVector(Float32* inVector)
{
if ((inVector[0] == 0.0) && (inVector[1] == 0.0) && (inVector[2] == 0.0))
return true;
else
return false;
}
#define LOG_SOURCE_CONES 0
bool OALSource::ConeAttenuation()
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::ConeAttenuation - OALSource = %ld\n", (long int) mSelfToken);
#endif
if ( IsZeroVector(mConeDirection) ||
((mConeInnerAngle == 360.0) && (mConeOuterAngle == 360.0)) )
{
if (mConeGainScaler != 1.0)
{
mConeGainScaler = 1.0;
return true; }
return false; }
Float32 vsl[3]; Float32 coneDirection[3];
Float32 angle;
mOwningContext->GetListenerPosition(&vsl[0], &vsl[1], &vsl[2]);
vsl[0] -= mPosition[0];
vsl[1] -= mPosition[1];
vsl[2] -= mPosition[2];
aluNormalize(vsl);
coneDirection[0] = mConeDirection[0];
coneDirection[1] = mConeDirection[1];
coneDirection[2] = mConeDirection[2];
aluNormalize(coneDirection);
angle = 180.0 * acos (aluDotproduct(vsl, coneDirection))/M_PI;
Float32 absAngle = fabs(angle);
Float32 absInnerAngle = fabs(mConeInnerAngle)/2.0; Float32 absOuterAngle = fabs(mConeOuterAngle)/2.0; Float32 newScaler;
if (absAngle <= absInnerAngle)
{
newScaler = 1.0;
#if LOG_SOURCE_CONES
DebugMessage("ConeAttenuation - Listener is within the inner angle, no Attenuation required");
#endif
}
else if (absAngle >= absOuterAngle)
{
#if LOG_SOURCE_CONES
DebugMessageN1("ConeAttenuation - Listener is outside the outer angle, scaler equals the Outer Cone Gain = %f", mConeOuterGain);
#endif
newScaler = mConeOuterGain;
}
else
{
Float32 x = (absAngle - absInnerAngle ) / (absOuterAngle - absInnerAngle );
newScaler = 1.0 * (1.0 - x) + mConeOuterGain * x;
#if LOG_SOURCE_CONES
DebugMessageN1("ConeAttenuation - Listener is between inner and outer angles, scaler equals = %f", newScaler);
#endif
}
if (newScaler != mConeGainScaler)
{
mConeGainScaler = newScaler;
return true; }
return false; }
void OALSource::CalculateDistanceAndAzimuth(Float32 *outDistance, Float32 *outAzimuth, Float32 *outElevation, Float32 *outDopplerShift)
{
#if LOG_VERBOSE
DebugMessageN1("OALSource::CalculateDistanceAndAzimuth - OALSource = %ld\n", (long int) mSelfToken);
#endif
Float32 ListenerOrientation[6],
ListenerPosition[3],
ListenerVelocity[3],
Angle = 0.0,
Distance = 2.0,
Elevation = 0.0,
Distance_squared = 4.0,
front_back,
SourceToListener[3],
ProjectedSource[3],
UpProjection,
Look_Norm[3],
RightEarVector[3], Up[3],
tPosition[3],
dopplerShift = 1.0;
*outDopplerShift = dopplerShift;
SourceToListener[0]=0; SourceToListener[1]=0; SourceToListener[2]=0; Up[0]=0; Up[1]=0; Up[2]=0;
tPosition[0] = mPosition[0];
tPosition[1] = mPosition[1];
tPosition[2] = mPosition[2];
mOwningContext->GetListenerPosition(&ListenerPosition[0], &ListenerPosition[1], &ListenerPosition[2]);
mOwningContext->GetListenerVelocity(&ListenerVelocity[0], &ListenerVelocity[1], &ListenerVelocity[2]);
mOwningContext->GetListenerOrientation(&ListenerOrientation[0], &ListenerOrientation[1], &ListenerOrientation[2],
&ListenerOrientation[3], &ListenerOrientation[4], &ListenerOrientation[5]);
BufferInfo *bufferInfo = mBufferQueueActive->Get(mCurrentBufferIndex);
if (bufferInfo == NULL)
{
*outDistance = 0.0;
*outAzimuth = 0.0;
*outElevation = 0.0;
return; }
if (bufferInfo->mBuffer->GetNumberChannels() == 1)
{
if (mSourceRelative == AL_FALSE)
{
tPosition[0] -= ListenerPosition[0];
tPosition[1] -= ListenerPosition[1];
tPosition[2] -= ListenerPosition[2];
}
aluCrossproduct(&ListenerOrientation[0],&ListenerOrientation[3],RightEarVector); aluNormalize(RightEarVector); Look_Norm[0] = ListenerOrientation[0];
Look_Norm[1] = ListenerOrientation[1];
Look_Norm[2] = ListenerOrientation[2];
aluNormalize(Look_Norm);
Distance_squared = aluDotproduct(tPosition,tPosition);
Distance = sqrt(Distance_squared);
Angle = 0.0f;
if(Distance>0.0f){
SourceToListener[0]=tPosition[0];
SourceToListener[1]=tPosition[1];
SourceToListener[2]=tPosition[2];
aluNormalize(SourceToListener);
aluCrossproduct(RightEarVector, Look_Norm, Up);
UpProjection = aluDotproduct(SourceToListener,Up);
ProjectedSource[0] = SourceToListener[0] - UpProjection*Up[0];
ProjectedSource[1] = SourceToListener[1] - UpProjection*Up[1];
ProjectedSource[2] = SourceToListener[2] - UpProjection*Up[2];
aluNormalize(ProjectedSource);
Angle = 180.0 * acos (aluDotproduct(ProjectedSource, RightEarVector))/M_PI;
zapBadness(Angle);
front_back = aluDotproduct(ProjectedSource,Look_Norm);
if(front_back<0.0f)
Angle = 360.0f - Angle;
if((Angle>=0.0f)&&(Angle<=270.0f))
Angle = 90.0f - Angle;
else
Angle = 450.0f - Angle;
}
Elevation = 90.0 - 180.0 * acos( aluDotproduct(SourceToListener, Up) )/ 3.141592654f;
zapBadness(Elevation);
if(SourceToListener[0]==0.0 && SourceToListener[1]==0.0 && SourceToListener[2]==0.0 )
Elevation = 0.0;
if (Elevation > 90.0)
Elevation = 180.0 - Elevation;
if (Elevation < -90.0)
Elevation = -180.0 - Elevation;
Float32 dopplerFactor = mOwningContext->GetDopplerFactor();
if (dopplerFactor > 0.0)
{
Float32 speedOfSound = mOwningContext->GetSpeedOfSound();
Float32 SourceVelocity[3];
GetVelocity (SourceVelocity[0], SourceVelocity[1], SourceVelocity[2]);
bool SourceHasVelocity = !IsZeroVector(SourceVelocity);
bool ListenerHasVelocity = !IsZeroVector(ListenerVelocity);
if (SourceHasVelocity || ListenerHasVelocity)
{
Float32 NUvls = (aluDotproduct(SourceToListener, ListenerVelocity))/MAG(SourceToListener);
Float32 NUvss = (aluDotproduct(SourceToListener, SourceVelocity))/MAG(SourceToListener);
NUvls = -NUvls; NUvss = -NUvss;
NUvls = fmin(NUvls, speedOfSound/dopplerFactor);
NUvss = fmin(NUvss, speedOfSound/dopplerFactor);
dopplerShift = ( (speedOfSound - dopplerFactor * NUvls) / (speedOfSound - dopplerFactor * NUvss) );
zapBadnessForDopplerShift(dopplerShift);
if (dopplerShift > 16.0)
dopplerShift = 16.0;
else if(dopplerShift < 0.125)
dopplerShift = 0.125;
#if LOG_DOPPLER
DebugMessageN1("CalculateDistanceAndAzimuth: dopplerShift after scaling = %f\n", dopplerShift);
#endif
*outDopplerShift = dopplerShift;
}
}
}
else
{
Angle=0.0;
Distance=0.0;
}
if ((Get3DMixerVersion() < k3DMixerVersion_2_0) && (mReferenceDistance > 1.0))
{
Distance = Distance/mReferenceDistance;
if (Distance > mMaxDistance/mReferenceDistance)
Distance = mMaxDistance/mReferenceDistance; }
*outDistance = Distance;
*outAzimuth = Angle;
*outElevation = Elevation;
}
#pragma mark ***** ASA Extension Methods *****
void OALSource::SetReverbSendLevel(Float32 inReverbLevel)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetReverbSendLevel - OALSource:inReverbLevel = %ld:%f\n", (long int) mSelfToken, inReverbLevel);
#endif
#if LOG_GRAPH_AND_MIXER_CHANGES
DebugMessageN2("OALSource::SetReverbSendLevel - OALSource:inReverbLevel = %ld:%f\n", (long int) mSelfToken, inReverbLevel);
#endif
if (inReverbLevel < 0.0f || inReverbLevel > 1.0f)
throw (OSStatus)AL_INVALID_VALUE;
CAGuard::Locker sourceLock(mSourceLock);
if (inReverbLevel == mASAReverbSendLevel)
return;
mASAReverbSendLevel = inReverbLevel;
UpdateBusReverb();
}
void OALSource::SetOcclusion(Float32 inOcclusion)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetOcclusion - OALSource:inOcclusion = %ld:%f\n", (long int) mSelfToken, inOcclusion);
#endif
#if LOG_GRAPH_AND_MIXER_CHANGES
DebugMessageN2("OALSource::SetOcclusion - OALSource:inOcclusion = %ld:%f\n", (long int) mSelfToken, inOcclusion);
#endif
if (inOcclusion < -100.0f || inOcclusion > 0.0f)
throw (OSStatus)AL_INVALID_VALUE;
if (inOcclusion == mASAOcclusion)
return;
mASAOcclusion = inOcclusion;
UpdateBusOcclusion();
}
void OALSource::SetObstruction(Float32 inObstruction)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetObstruction - OALSource:inObstruction = %ld:%f\n", (long int) mSelfToken, inObstruction);
#endif
#if LOG_GRAPH_AND_MIXER_CHANGES
DebugMessageN2("OALSource::SetObstruction - OALSource:inObstruction = %ld:%f\n", (long int) mSelfToken, inObstruction);
#endif
if (inObstruction < -100.0f || inObstruction > 0.0f)
throw (OSStatus)AL_INVALID_VALUE;
CAGuard::Locker sourceLock(mSourceLock);
if (inObstruction == mASAObstruction)
return;
mASAObstruction = inObstruction;
UpdateBusObstruction();
}
void OALSource::SetRogerBeepEnable(Boolean inEnable)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetRogerBeepEnable - OALSource:inEnable = %ld:%d\n", (long int) mSelfToken, inEnable);
#endif
#if LOG_GRAPH_AND_MIXER_CHANGES
DebugMessageN2("OALSource::SetRogerBeepEnable - OALSource:inEnable = %ld:%d\n", (long int) mSelfToken, inEnable);
#endif
CAGuard::Locker sourceLock(mSourceLock);
if ((mState == AL_PLAYING) || (mState == AL_PAUSED))
throw (OSStatus) AL_INVALID_OPERATION;
if (inEnable == mASARogerBeepEnable)
return;
mASARogerBeepEnable = inEnable;
if (mASARogerBeepEnable)
{
SetupRogerBeepAU();
UInt32 propSize = sizeof(UInt32);
UInt32 bypassValue;
if(AudioUnitGetProperty(mRogerBeepAU, kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0, &bypassValue, &propSize) == noErr)
mASARogerBeepOn = bypassValue ? 0 : 1;
Float32 paramValue;
if(AudioUnitGetParameter(mRogerBeepAU, 6, kAudioUnitScope_Global, 0, ¶mValue) == noErr)
mASARogerBeepGain = paramValue;
if(AudioUnitGetParameter(mRogerBeepAU, 4, kAudioUnitScope_Global, 0, ¶mValue) == noErr)
mASARogerBeepSensitivity = (UInt32)paramValue;
if(AudioUnitGetParameter(mRogerBeepAU, 5 , kAudioUnitScope_Global, 0, ¶mValue) == noErr)
mASARogerBeepType = (UInt32)paramValue;
SetRogerBeepOn(false);
}
else
{
if(mRogerBeepNode)
AUGraphRemoveNode(mOwningContext->GetGraph(), mRogerBeepNode);
mRogerBeepNode = 0;
mRogerBeepAU = 0;
}
}
void OALSource::SetRogerBeepOn(Boolean inOn)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetRogerBeepOn - OALSource:inOn = %ld:%d\n", (long int) mSelfToken, inOn);
#endif
#if LOG_GRAPH_AND_MIXER_CHANGES
DebugMessageN2("OALSource::SetRogerBeepOn - OALSource:inOn = %ld:%d\n", (long int) mSelfToken, inOn);
#endif
CAGuard::Locker sourceLock(mSourceLock);
if (inOn == mASARogerBeepOn)
return;
mASARogerBeepOn = inOn;
UInt32 bypassValue = mASARogerBeepOn ? 0 : 1;
AudioUnitSetProperty(mRogerBeepAU, kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0, &bypassValue, sizeof(UInt32));
}
void OALSource::SetRogerBeepGain(Float32 inGain)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetRogerBeepGain - OALSource:inGain = %ld:%f\n", (long int) mSelfToken, inGain);
#endif
#if LOG_GRAPH_AND_MIXER_CHANGES
DebugMessageN2("OALSource::SetRogerBeepGain - OALSource:inGain = %ld:%f\n", (long int) mSelfToken, inGain);
#endif
if (inGain < -100.0f || inGain > 20.0f)
throw (OSStatus)AL_INVALID_VALUE;
if(!mASARogerBeepEnable)
throw (OSStatus) AL_INVALID_OPERATION;
if (inGain == mASARogerBeepGain)
return;
mASARogerBeepGain = inGain;
AudioUnitSetParameter(mRogerBeepAU, 6, kAudioUnitScope_Global, 0, inGain, 0 );
}
void OALSource::SetRogerBeepSensitivity(SInt32 inSensitivity)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetRogerBeepSensitivity - OALSource:inSensitivity = %ld:%d\n", (long int) mSelfToken, inSensitivity);
#endif
#if LOG_GRAPH_AND_MIXER_CHANGES
DebugMessageN2("OALSource::SetRogerBeepSensitivity - OALSource:inSensitivity = %ld:%d\n", (long int) mSelfToken, inSensitivity);
#endif
if (inSensitivity < 0 || inSensitivity > 2)
throw (OSStatus)AL_INVALID_VALUE;
CAGuard::Locker sourceLock(mSourceLock);
if(!mASARogerBeepEnable)
throw (OSStatus)AL_INVALID_OPERATION;
if (inSensitivity == mASARogerBeepSensitivity)
return;
mASARogerBeepSensitivity = inSensitivity;
AudioUnitSetParameter(mRogerBeepAU, 4, kAudioUnitScope_Global, 0, inSensitivity, 0 );
}
void OALSource::SetRogerBeepType(SInt32 inType)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetRogerBeepType - OALSource:inType = %ld:%d\n", (long int) mSelfToken, inType);
#endif
#if LOG_GRAPH_AND_MIXER_CHANGES
DebugMessageN2("OALSource::SetRogerBeepType - OALSource:inType = %ld:%d\n", (long int) mSelfToken, inType);
#endif
if (inType < 0 || inType > 3)
throw (OSStatus)AL_INVALID_VALUE;
CAGuard::Locker sourceLock(mSourceLock);
if(!mASARogerBeepEnable)
throw (OSStatus)AL_INVALID_OPERATION;
if (inType == mASARogerBeepType)
return;
mASARogerBeepType = inType;
AudioUnitSetParameter(mRogerBeepAU, 5 , kAudioUnitScope_Global, 0, inType, 0 );
}
void OALSource::SetRogerBeepPreset(FSRef* inRef)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetRogerBeepPreset - OALSource:inRef = %ld:%p\n", (long int) mSelfToken, inRef);
#endif
CAGuard::Locker sourceLock(mSourceLock);
try {
Boolean status;
SInt32 result = 0;
CFURLRef fileURL = CFURLCreateFromFSRef (kCFAllocatorDefault, inRef);
if (fileURL)
{
CFDataRef resourceData = NULL;
status = CFURLCreateDataAndPropertiesFromResource (kCFAllocatorDefault, fileURL, &resourceData, NULL, NULL, &result);
CFRelease (fileURL);
if (status == false || result)
throw (OSStatus) -1;
else
{
CFStringRef errString = NULL;
CFPropertyListRef theData = NULL;
theData = CFPropertyListCreateFromXMLData (kCFAllocatorDefault, resourceData, kCFPropertyListImmutable, &errString);
CFRelease (resourceData);
if (errString)
CFRelease (errString);
if (theData == NULL || errString)
{
if (theData)
CFRelease (theData);
throw (OSStatus) -1;
}
else
{
result = AudioUnitSetProperty(mRogerBeepAU, kAudioUnitProperty_ClassInfo, kAudioUnitScope_Global, 0, &theData, sizeof(theData) );
CFRelease (theData);
THROW_RESULT
}
}
}
else
throw (OSStatus) -1;
}
catch (OSStatus result) {
throw result;
}
catch (...) {
throw (OSStatus) -1;
}
return;
}
void OALSource::SetDistortionEnable(Boolean inEnable)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetDistortionEnable - OALSource:inEnable = %ld:%d\n", (long int) mSelfToken, inEnable);
#endif
#if LOG_GRAPH_AND_MIXER_CHANGES
DebugMessageN2("OALSource::SetDistortionEnable - OALSource:inEnable = %ld:%d\n", (long int) mSelfToken, inEnable);
#endif
CAGuard::Locker sourceLock(mSourceLock);
if (inEnable == mASADistortionEnable)
return;
mASADistortionEnable = inEnable;
if (mASADistortionEnable)
{
SetupDistortionAU();
UInt32 propSize = sizeof(UInt32);
UInt32 bypassValue;
if(AudioUnitGetProperty(mDistortionAU, kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0, &bypassValue, &propSize) == noErr)
mASADistortionOn = bypassValue ? 0 : 1;
Float32 paramValue;
if(AudioUnitGetParameter(mDistortionAU, 15, kAudioUnitScope_Global, 0, ¶mValue) == noErr)
mASADistortionMix = paramValue;
AUPreset distortionType;
propSize = sizeof(distortionType);
if(AudioUnitGetProperty(mDistortionAU, kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global, 0, &distortionType, &propSize) == noErr)
{
if(distortionType.presetName) CFRelease(distortionType.presetName);
mASADistortionType = distortionType.presetNumber;
}
SetDistortionOn(false);
}
else
{
if(mDistortionNode)
AUGraphRemoveNode(mOwningContext->GetGraph(), mDistortionNode);
mDistortionNode = 0;
mDistortionAU = 0;
}
}
void OALSource::SetDistortionOn(Boolean inOn)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetDistortionOn - OALSource:inOn = %ld:%d\n", (long int) mSelfToken, inOn);
#endif
#if LOG_GRAPH_AND_MIXER_CHANGES
DebugMessageN2("OALSource::SetDistortionOn - OALSource:inOn = %ld:%d\n", (long int) mSelfToken, inOn);
#endif
CAGuard::Locker sourceLock(mSourceLock);
if (inOn == mASADistortionOn)
return;
mASADistortionOn = inOn;
UInt32 bypassValue = mASADistortionOn ? 0 : 1;
AudioUnitSetProperty(mDistortionAU, kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0, &bypassValue, sizeof(UInt32));
}
void OALSource::SetDistortionMix(Float32 inMix)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetDistortionMix - OALSource:inMix = %ld:%f\n", (long int) mSelfToken, inMix);
#endif
#if LOG_GRAPH_AND_MIXER_CHANGES
DebugMessageN2("OALSource::SetDistortionMix - OALSource:inMix = %ld:%f\n", (long int) mSelfToken, inMix);
#endif
if (inMix < 0.0f || inMix > 100.0f)
throw (OSStatus)AL_INVALID_VALUE;
CAGuard::Locker sourceLock(mSourceLock);
if(!mASADistortionEnable)
throw (OSStatus)AL_INVALID_OPERATION;
if (inMix == mASADistortionMix)
return;
mASADistortionMix = inMix;
AudioUnitSetParameter(mDistortionAU, 15, kAudioUnitScope_Global, 0, inMix, 0 );
}
void OALSource::SetDistortionType(SInt32 inType)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetDistortionMix - OALSource:inType = %ld:%df\n", (long int) mSelfToken, inType);
#endif
#if LOG_GRAPH_AND_MIXER_CHANGES
DebugMessageN2("OALSource::SetDistortionType: OALSource: = %u : inType %d\n", mSelfToken, inType );
#endif
CAGuard::Locker sourceLock(mSourceLock);
if(!mASADistortionEnable)
throw (OSStatus)AL_INVALID_OPERATION;
if (inType == mASADistortionType)
return;
mASADistortionType = inType;
AUPreset distortionType;
distortionType.presetNumber = mASADistortionType;
distortionType.presetName = NULL;
AudioUnitSetProperty(mDistortionAU, kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global, 0, &distortionType, sizeof(AUPreset));
}
void OALSource::SetDistortionPreset(FSRef* inRef)
{
#if LOG_VERBOSE
DebugMessageN2("OALSource::SetDistortionPreset - OALSource:inRef = %ld:%p\n", (long int) mSelfToken, inRef);
#endif
CAGuard::Locker sourceLock(mSourceLock);
try {
Boolean status;
SInt32 result = 0;
CFURLRef fileURL = CFURLCreateFromFSRef (kCFAllocatorDefault, inRef);
if (fileURL)
{
CFDataRef resourceData = NULL;
status = CFURLCreateDataAndPropertiesFromResource (kCFAllocatorDefault, fileURL, &resourceData, NULL, NULL, &result);
CFRelease (fileURL);
if (status == false || result)
throw (OSStatus) -1;
else
{
CFStringRef errString = NULL;
CFPropertyListRef theData = NULL;
theData = CFPropertyListCreateFromXMLData (kCFAllocatorDefault, resourceData, kCFPropertyListImmutable, &errString);
CFRelease (resourceData);
if (errString)
CFRelease (errString);
if (theData == NULL || errString)
{
if (theData)
CFRelease (theData);
throw (OSStatus) -1;
}
else
{
result = AudioUnitSetProperty(mDistortionAU, kAudioUnitProperty_ClassInfo, kAudioUnitScope_Global, 0, &theData, sizeof(theData) );
CFRelease (theData);
THROW_RESULT
}
}
}
else
throw (OSStatus) -1;
}
catch (OSStatus result) {
throw result;
}
catch (...) {
throw (OSStatus) -1;
}
return;
}
#pragma mark _____BufferQueue_____
UInt32 BufferQueue::GetCurrentFrame(UInt32 inBufferIndex)
{
#if LOG_VERBOSE
DebugMessageN1("BufferQueue::GetCurrentFrame - inBufferIndex = %d", inBufferIndex);
#endif
iterator it = begin();
std::advance(it, inBufferIndex);
if (it != end())
return (it->mBuffer->GetBytesPerPacket() == 0) ? 0 : it->mOffset/it->mBuffer->GetBytesPerPacket();
return 0;
}
void BufferQueue::AppendBuffer(OALSource* thisSource, ALuint inBufferToken, OALBuffer *inBuffer, ALuint inACToken)
{
#if LOG_VERBOSE
DebugMessageN4("BufferQueue::AppendBuffer - thisSource:inBufferToken:inBuffer:inACToken = %d:%d:%p:%d", thisSource->GetToken(), inBufferToken, inBuffer, inACToken);
#endif
BufferInfo newBuffer;
newBuffer.mBufferToken = inBufferToken;
newBuffer.mBuffer = inBuffer;
newBuffer.mOffset = 0;
newBuffer.mProcessedState = kPendingProcessing;
newBuffer.mACToken = inACToken;
push_back(value_type (newBuffer));
SetQueueSize();
}
ALuint BufferQueue::RemoveQueueEntryByIndex(OALSource* thisSource, UInt32 inIndex, bool inReleaseIt)
{
#if LOG_VERBOSE
DebugMessageN3("BufferQueue::RemoveQueueEntryByIndex - thisSource:inIndex:inReleaseIt:inACToken = %d:%d:%d", thisSource->GetToken(), inIndex, inReleaseIt);
#endif
iterator it = begin();
ALuint outBufferToken = 0;
std::advance(it, inIndex);
if (it != end())
{
outBufferToken = it->mBufferToken;
if (inReleaseIt)
it->mBuffer->ReleaseBuffer(thisSource); erase(it);
}
SetQueueSize();
return (outBufferToken);
}
UInt32 BufferQueue::GetQueueSizeInFrames()
{
#if LOG_VERBOSE
DebugMessage("BufferQueue::GetQueueSizeInFrames");
#endif
iterator it = begin();
UInt32 totalFrames = 0;
while (it != end())
{
totalFrames += it->mBuffer->GetFrameCount();
++it;
}
return (totalFrames);
}
UInt32 BufferQueue::GetBufferFrameCount(UInt32 inBufferIndex)
{
#if LOG_VERBOSE
DebugMessageN1("BufferQueue::GetBufferFrameCount - inBufferIndex = %d",inBufferIndex);
#endif
iterator it = begin();
std::advance(it, inBufferIndex);
if (it != end())
return (it->mBuffer->GetFrameCount());
return 0;
}
ALuint BufferQueue::GetBufferTokenByIndex(UInt32 inBufferIndex)
{
#if LOG_VERBOSE
DebugMessageN1("BufferQueue::GetBufferTokenByIndex - inBufferIndex = %d",inBufferIndex);
#endif
iterator it = begin();
std::advance(it, inBufferIndex);
if (it != end())
return (it->mBuffer->GetToken());
return 0;
}
void BufferQueue::SetFirstBufferOffset(UInt32 inFrameOffset)
{
#if LOG_VERBOSE
DebugMessageN1("BufferQueue::SetFirstBufferOffset - inFrameOffset = %d",inFrameOffset);
#endif
iterator it = begin();
if (it == end())
return;
UInt32 packetOffset = FrameOffsetToPacketOffset(inFrameOffset);
UInt32 packetSize = GetPacketSize();
it->mOffset = packetOffset * packetSize;
}
UInt32 BufferQueue::GetPacketSize()
{
#if LOG_VERBOSE
DebugMessage("BufferQueue::GetPacketSize");
#endif
iterator it = begin();
if (it != end())
return(it->mBuffer->GetBytesPerPacket());
return (0);
}
UInt32 BufferQueue::FrameOffsetToPacketOffset(UInt32 inFrameOffset)
{
#if LOG_VERBOSE
DebugMessageN1("BufferQueue::FrameOffsetToPacketOffset - inFrameOffset = %d",inFrameOffset);
#endif
return inFrameOffset;
}