1/********************************************************************************************************************************** 2* 3* OpenAL cross platform audio library 4* Copyright (c) 2004, Apple Computer, Inc., Copyright (c) 2012, Apple Inc. All rights reserved. 5* 6* Redistribution and use in source and binary forms, with or without modification, are permitted provided 7* that the following conditions are met: 8* 9* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 10* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 11* disclaimer in the documentation and/or other materials provided with the distribution. 12* 3. Neither the name of Apple Inc. ("Apple") nor the names of its contributors may be used to endorse or promote 13* products derived from this software without specific prior written permission. 14* 15* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS 17* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 18* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 19* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 20* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 21* 22**********************************************************************************************************************************/ 23 24#ifndef __OAL_SOURCE__ 25#define __OAL_SOURCE__ 26 27#include "oalImp.h" 28#include "oalDevice.h" 29#include "oalContext.h" 30#include "al.h" 31 32#include <Carbon/Carbon.h> 33#include <AudioToolbox/AudioConverter.h> 34#include <list> 35#include <libkern/OSAtomic.h> 36#include <vector> 37#include <queue> 38#include <dispatch/dispatch.h> 39 40#include "CAStreamBasicDescription.h" 41#include "CAAtomicStack.h" 42#include "CAGuard.h" 43 44class OALBuffer; // forward declaration 45 46// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 47// buffer info state constants 48enum { 49 kSecondsOffset = 1, 50 kSampleOffset = 2, 51 kByteOffset = 3 52}; 53 54enum { 55 kPendingProcessing = 0, 56 kInProgress = 1, 57 kProcessed = 2 58}; 59 60enum { 61 kRampingComplete = -2, 62 kRampDown = -1, 63 kNoRamping = 0, 64 kRampUp = 1 65}; 66 67enum { 68 kMQ_NoMessage = 0, 69 kMQ_Stop = 1, 70 kMQ_Rewind = 2, 71 kMQ_SetBuffer = 3, 72 kMQ_Play = 4, 73 kMQ_Pause = 5, 74 kMQ_Resume = 6, 75 kMQ_SetFramePosition = 7, 76 kMQ_ClearBuffersFromQueue = 8, 77 kMQ_DeconstructionStop = 9, 78 kMQ_Retrigger = 10, 79 kMQ_AddBuffersToQueue = 11 80}; 81 82#define OALSourceError_CallConverterAgain 'agan' 83#define kSourceNeedsBus -1 84 85// do not change kDistanceScalar from 10.0 - it is used to compensate for a reverb related problem in the 3DMixer 86#define kDistanceScalar 10.0 87 88#define kTransitionToStop 0XDD01 89#define kTransitionToPlay 0XDD02 90#define kTransitionToPause 0XDD03 91#define kTransitionToRewind 0XDD04 92#define kTransitionToRetrigger 0XDD05 93#define kTransitionToResume 0XDD06 94 95#pragma mark _____PlaybackMessage_____ 96 97class PlaybackMessage { 98public: 99 PlaybackMessage(UInt32 inMessage, OALBuffer* inBuffer, UInt32 inNumBuffers) : 100 mMessageID(inMessage), 101 mBuffer(inBuffer), 102 mNumBuffers(inNumBuffers) 103 { }; 104 105 ~PlaybackMessage(){}; 106 107 PlaybackMessage* mNext; 108 UInt32 mMessageID; 109 OALBuffer* mBuffer; 110 UInt32 mNumBuffers; 111 112 PlaybackMessage *& next() { return mNext; } 113 void set_next(PlaybackMessage *next) { mNext = next; } 114}; 115 116// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 117#pragma mark _____BufferQueue_____ 118// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 119// This struct is used by OAL source to store info about the buffers in it's queue 120struct BufferInfo { 121 ALuint mBufferToken; // the buffer name that the user was returned when the buffer was created 122 OALBuffer *mBuffer; // buffer object 123 UInt32 mOffset; // current read position offset of this data 124 UInt32 mProcessedState; // mark as true when data of this buffer is finished playing and looping is off 125 ALuint mACToken; // use this AC from the ACMap for converting the data to the mixer format, when 126 // set to zero, then NO AC is needed, the data has already been converted 127}; 128 129class BufferQueue : std::vector<BufferInfo> { 130public: 131 132 BufferQueue() { mBufferQueueSize = 0;} 133 void AppendBuffer(OALSource* thisSource, ALuint inBufferToken, OALBuffer *inBuffer, ALuint inACToken); 134 ALuint RemoveQueueEntryByIndex(OALSource* thisSource, UInt32 inIndex, bool inReleaseIt); 135 UInt32 GetQueueSizeInFrames() ; 136 UInt32 GetBufferFrameCount(UInt32 inBufferIndex); 137 void SetFirstBufferOffset(UInt32 inFrameOffset) ; 138 ALuint GetBufferTokenByIndex(UInt32 inBufferIndex); 139 UInt32 GetCurrentFrame(UInt32 inBufferIndex); 140 141 BufferInfo* Get(short inBufferIndex) { 142 iterator it = begin(); 143 std::advance(it, inBufferIndex); 144 if (it != end()) 145 return(&(*it)); 146 return (NULL); 147 } 148 149 void SetBufferAsProcessed(UInt32 inBufferIndex) { 150 iterator it = begin(); 151 std::advance(it, inBufferIndex); 152 if (it != end()) 153 it->mProcessedState = kProcessed; 154 } 155 156 // mark all the buffers in the queue as unprocessed and offset 0 157 void ResetBuffers() { 158 iterator it = begin(); 159 while (it != end()) 160 { 161 it->mProcessedState = kPendingProcessing; 162 it->mOffset = 0; 163 ++it; 164 } 165 } 166 167 UInt32 GetQueueSize () { return mBufferQueueSize; } 168 void SetQueueSize () { mBufferQueueSize = Size(); } 169 bool Empty () const { return empty(); } 170 void Reserve(UInt32 reserveSize) {return reserve(reserveSize); } 171 172private: 173 UInt32 GetPacketSize() ; 174 UInt32 FrameOffsetToPacketOffset(UInt32 inFrameOffset); 175 UInt32 Size () const { return size(); } 176 177 volatile int32_t mBufferQueueSize; // shadow variable to store the size of the queue 178}; 179typedef BufferQueue BufferQueue; 180 181// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 182#pragma mark _____ACMap_____ 183// ACMap - map the AudioConverters for the sources queue 184// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 185// This struct is used by OAL source to store info about the ACs used by it's queue 186struct ACInfo { 187 AudioConverterRef mConverter; 188 CAStreamBasicDescription mInputFormat; 189}; 190 191class ACMap : std::multimap<ALuint, ACInfo, std::less<ALuint> > { 192public: 193 194 // add a new context to the map 195 void Add (const ALuint inACToken, ACInfo *inACInfo) { 196 iterator it = upper_bound(inACToken); 197 insert(it, value_type (inACToken, *inACInfo)); 198 } 199 200 AudioConverterRef Get(ALuint inACToken) { 201 const_iterator it = find(inACToken); 202 iterator theEnd = end(); 203 204 if (it != theEnd) 205 return ((*it).second.mConverter); 206 207 return (NULL); 208 } 209 210 void GetACForFormat (CAStreamBasicDescription* inFormat, ALuint &outToken) { 211 iterator it = begin(); 212 213 outToken = 0; // 0 means there is none yet 214 while (it != end()) { 215 if( (*it).second.mInputFormat == *inFormat) { 216 outToken = (*it).first; 217 it = end(); 218 } 219 else 220 ++it; 221 } 222 return; 223 } 224 225 void Remove (const ALuint inACToken) { 226 iterator it = find(inACToken); 227 if (it != end()) { 228 AudioConverterDispose((*it).second.mConverter); 229 erase(it); 230 } 231 } 232 233 // the map should be disposed after making this call 234 void RemoveAllConverters () { 235 iterator it = begin(); 236 iterator theEnd = end(); 237 238 while (it != theEnd) { 239 AudioConverterDispose((*it).second.mConverter); 240 ++it; 241 } 242 } 243 244 UInt32 Size () const { return size(); } 245 bool Empty () const { return empty(); } 246}; 247typedef ACMap ACMap; 248 249// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 250#pragma mark _____SourceNotifyInfo_____ 251// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 252class SourceNotifyInfo 253{ 254public: 255 SourceNotifyInfo() 256 : mID(0), 257 mProc(0), 258 mUserData(0) 259 {} 260 261friend class SourceNotifications; 262private: 263 ALuint mID; 264 alSourceNotificationProc mProc; 265 void *mUserData; 266}; 267 268class SourceNotifications : public std::vector<SourceNotifyInfo> 269{ 270public: 271 SourceNotifications(ALuint inSourceID) 272 : mSourceToken(inSourceID) 273 { 274 mNotifyMutex = new CAMutex("Notifcation Mutex"); 275 } 276 277 ~SourceNotifications() 278 { 279 delete mNotifyMutex; 280 } 281 282 283 OSStatus AddSourceNotification(ALuint inID, alSourceNotificationProc inProc, void *inUserData) 284 { 285 CAMutex::Locker lock(*mNotifyMutex); 286 return AddSourceNotificationImp(inID, inProc, inUserData); 287 } 288 289 OSStatus RemoveSourceNotification(ALuint inID, alSourceNotificationProc inProc, void *inUserData) 290 { 291 CAMutex::Locker lock(*mNotifyMutex); 292 return RemoveSourceNotificationImp(inID, inProc, inUserData); 293 } 294 295 OSStatus RemoveAllSourceNotifications(ALuint inID) 296 { 297 CAMutex::Locker lock(*mNotifyMutex); 298 return RemoveAllSourceNotificationsImp(inID); 299 } 300 301 void CallSourceNotifications(ALuint inID) 302 { 303 if (mNotifyMutex != NULL) { 304 CAMutex::Locker lock(*mNotifyMutex); 305 return CallSourceNotificationsImp(inID); 306 } 307 } 308 309private: 310 const SourceNotifications::iterator FindNotificationInfo(ALuint inID, alSourceNotificationProc inProc, void *inUserData) 311 { 312 SourceNotifications::iterator it; 313 for (it = begin(); it != end(); ++it) { 314 if ((it->mID == inID) && (it->mProc == inProc) && (it->mUserData == inUserData)) 315 return it; 316 } 317 return it; // end() 318 } 319 320 OSStatus AddSourceNotificationImp(ALuint inID, alSourceNotificationProc inProc, void *inUserData) 321 { 322 OSStatus status = noErr; 323 324 SourceNotifications::iterator it = FindNotificationInfo(inID, inProc, inUserData); 325 if (it == end()) { 326 SourceNotifyInfo info; 327 info.mID = inID; 328 info.mProc = inProc; 329 info.mUserData = inUserData; 330 push_back(info); 331 } 332 else { 333 status = -50; 334 } 335 336 return status; 337 } 338 339 OSStatus RemoveSourceNotificationImp(ALuint inID, alSourceNotificationProc inProc, void *inUserData) 340 { 341 OSStatus status = noErr; 342 343 SourceNotifications::iterator it = FindNotificationInfo(inID, inProc, inUserData); 344 if (it != end()) 345 { 346 erase(it); 347 348 for (it = begin(); it != end(); ++it) { 349 if (it->mID == inID) 350 break; 351 } 352 } 353 else { 354 status = -50; 355 } 356 357 return status; 358 } 359 360 OSStatus RemoveAllSourceNotificationsImp(ALuint inID) 361 { 362 SourceNotifications::iterator it; 363 for (int index = size() - 1; index >= 0; index--) 364 { 365 it = begin() + index; 366 if (it->mID == inID) 367 erase(it); 368 } 369 370 OSStatus status = noErr; 371 372 return status; 373 } 374 375 void CallSourceNotificationsImp(ALuint inID) 376 { 377 SourceNotifications::iterator it; 378 for (it = begin(); it != end(); ++it) 379 if (it->mID == inID) 380 { 381 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 382 it->mProc(mSourceToken, inID, it->mUserData); 383 }); 384 } 385 } 386 387 CAMutex* mNotifyMutex; 388 ALuint mSourceToken; 389}; 390 391#pragma mark _____OALRenderLocker_____ 392 393class OALRenderLocker { 394 int mAcquireFlag, mTryFlag; 395 396 OALRenderLocker& operator= (const OALRenderLocker& as) { return *this; } 397 OALRenderLocker (const OALRenderLocker& as) {} 398 399public: 400 OALRenderLocker () : mAcquireFlag(0), mTryFlag (0) {} 401 402 class RenderLocker { 403 OALRenderLocker &mEditor; 404 bool mInRenderThread; 405 406 public: 407 RenderLocker (OALRenderLocker &editor, bool inRenderThread) 408 : mEditor(editor), 409 mInRenderThread(inRenderThread) 410 { 411 if (!mInRenderThread) 412 { 413 OSAtomicIncrement32Barrier(&mEditor.mAcquireFlag); 414 while (mEditor.mTryFlag) { usleep(500); } 415 } 416 } 417 ~RenderLocker () 418 { 419 if (!mInRenderThread) 420 { 421 OSAtomicDecrement32Barrier (&mEditor.mAcquireFlag); 422 } 423 } 424 }; 425 426 class RenderTryer { 427 OALRenderLocker &mTrier; 428 public: 429 RenderTryer (OALRenderLocker & trier) 430 : mTrier (trier) 431 { 432 OSAtomicIncrement32Barrier(&mTrier.mTryFlag); 433 } 434 ~RenderTryer () 435 { 436 OSAtomicDecrement32Barrier (&mTrier.mTryFlag); 437 } 438 bool Acquired () const { return !mTrier.mAcquireFlag; } 439 }; 440}; 441 442// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 443// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 444// OALSources 445// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 446// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 447#pragma mark _____OALSource_____ 448class OALSource 449{ 450#pragma mark __________ PRIVATE __________ 451 private: 452 453 ALuint mSelfToken; // the token returned to the caller upon alGenSources() 454 bool mSafeForDeletion; 455 OALContext *mOwningContext; 456 bool mIsSuspended; 457 bool mCalculateDistance; 458 bool mResetBusFormat; 459 bool mResetBus; 460 bool mResetPitch; 461 462 BufferQueue *mBufferQueueActive; // map of buffers for queueing 463 BufferQueue *mBufferQueueInactive; // map of buffers already queued 464 BufferQueue *mBufferQueueTemp; // map of buffers for temporary queueing 465 volatile int32_t mQueueLength; // snapshot of the queue length (mBufferQueueActive + mBufferQueueInactive) 466 volatile int32_t mTempQueueLength; // queue length returned when source is transitioning to flush Qs 467 UInt32 mBuffersQueuedForClear; // number of buffers pending removal from the inactive queue 468 ALuint mCurrentBufferIndex; // index of the current buffer being played 469 bool mQueueIsProcessed; // state of the entire buffer queue 470 471 volatile int32_t mInUseFlag; // flag to indicate a source is currently being used by one or more threads 472 CAGuard mSourceLock; 473 AURenderCallbackStruct mPlayCallback; 474 int mCurrentPlayBus; // the mixer bus currently used by this source 475 476 ACMap *mACMap; 477 478 bool mOutputSilence; 479 Float32 mPosition[3]; 480 Float32 mVelocity[3]; 481 Float32 mConeDirection[3]; 482 UInt32 mLooping; 483 UInt32 mSourceRelative; 484 UInt32 mSourceType; 485 Float32 mConeInnerAngle; 486 Float32 mConeOuterAngle; 487 Float32 mConeOuterGain; 488 489 // Gain Scalers 490 Float32 mConeGainScaler; 491 Float32 mAttenuationGainScaler; 492 493 // support for pre 2.0 3DMixer 494 float mReadIndex; 495 float mCachedInputL1; 496 float mCachedInputL2; 497 float mCachedInputR1; 498 float mCachedInputR2; 499 UInt32 mTempSourceStorageBufferSize; 500 AudioBufferList *mTempSourceStorage; 501 502 UInt32 mState; // playback state: Playing, Stopped, Paused, Initial, Transitioning (to stop) 503 float mGain; 504 Float32 mPitch; 505 Float32 mDopplerScaler; 506 Float32 mRollOffFactor; 507 Float32 mReferenceDistance; 508 Float32 mMaxDistance; 509 Float32 mMinGain; 510 Float32 mMaxGain; 511 512 SInt32 mRampState; 513 UInt32 mBufferCountToUnqueueInPostRender; 514 bool mTransitioningToFlushQ; 515 516 UInt32 mPlaybackHeadPosition; // stored for a deferred repositioning of playbackHead as a frame index 517 518 Float32 mASAReverbSendLevel; 519 Float32 mASAOcclusion; 520 Float32 mASAObstruction; 521 522 // thread protection 523 OALRenderLocker mRenderLocker; 524 525 // Audio Units and properties for RogerBeep and Distortion 526 AUNode mRogerBeepNode; 527 AudioUnit mRogerBeepAU; 528 Boolean mASARogerBeepEnable; 529 Boolean mASARogerBeepOn; 530 Float32 mASARogerBeepGain; 531 SInt32 mASARogerBeepSensitivity; 532 SInt32 mASARogerBeepType; 533 char* mASARogerBeepPreset; 534 535 AUNode mDistortionNode; 536 AudioUnit mDistortionAU; 537 Boolean mASADistortionEnable; 538 Boolean mASADistortionOn; 539 Float32 mASADistortionMix; 540 SInt32 mASADistortionType; 541 char* mASADistortionPreset; 542 543 AudioUnit mRenderUnit; 544 UInt32 mRenderElement; 545 546 SourceNotifications* mSourceNotifications; 547 548 typedef TAtomicStack<PlaybackMessage> PlaybackMessageList; 549 550 PlaybackMessageList mMessageQueue; 551 552 553 void JoinBufferLists(); 554 void LoopToBeginning(); 555 void ChangeChannelSettings(); 556 void InitSource(); 557 void SetState(UInt32 inState); 558 OSStatus DoRender (AudioBufferList *ioData); 559 OSStatus DoSRCRender (AudioBufferList *ioData); // support for pre 2.0 3DMixer 560 bool ConeAttenuation(); 561 void CalculateDistanceAndAzimuth(Float32 *outDistance, Float32 *outAzimuth, Float32 *outElevation, Float32 *outDopplerShift); 562 void UpdateBusGain (); 563 void UpdateMinBusGain (); 564 void UpdateMaxBusGain (); 565 void UpdateBusFormat (); 566 void UpdateBusReverb (); 567 void UpdateBusOcclusion (); 568 void UpdateBusObstruction (); 569 570 void UpdateQueue (); 571 void RampDown (AudioBufferList *ioData); 572 void RampUp (AudioBufferList *ioData); 573 void ClearActiveQueue(); 574 void AddNotifyAndRenderProcs(); 575 void ReleaseNotifyAndRenderProcs(); 576 void DisconnectFromBus(); 577 void SetupMixerBus(); 578 void ResetMixerBus(); 579 void SetupDistortionAU(); 580 void SetupRogerBeepAU(); 581 582 bool PrepBufferQueueForPlayback(); 583 584 UInt32 SecondsToFrames(Float32 inSeconds); 585 UInt32 BytesToFrames(Float32 inBytes); 586 void AppendBufferToQueue(ALuint inBufferToken, OALBuffer *inBuffer); 587 UInt32 FramesToSecondsInt(UInt32 inFrames); 588 Float32 FramesToSecondsFloat(UInt32 inFrames); 589 UInt32 FramesToBytes(UInt32 inFrames); 590 591 void PostRenderSetBuffer(ALuint inBufferToken, OALBuffer *inBuffer); 592 void PostRenderAddBuffersToQueue(UInt32 inNumBuffersToQueue); 593 void PostRenderRemoveBuffersFromQueue(UInt32 inBuffersToUnqueue); 594 void FlushBufferQueue(); 595 void FlushTempBufferQueue(); 596 597 void AdvanceQueueToFrameIndex(UInt32 inFrameOffset); 598 OSStatus SetDistanceParams(bool inChangeReferenceDistance, bool inChangeMaxDistance); 599 Float32 GetMaxAttenuation(Float32 inRefDistance, Float32 inMaxDistance, Float32 inRolloff); 600 BufferInfo* NextPlayableBufferInActiveQ(); 601 602 inline bool InRenderThread() { return mOwningContext->CallingInRenderThread(); } 603 604 void SetQueueLength() { mQueueLength = mBufferQueueActive->GetQueueSize() + mBufferQueueInactive->GetQueueSize() - mBuffersQueuedForClear; } 605 606/* 607 OSStatus MuteCurrentPlayBus () const 608 { 609 return AudioUnitSetParameter ( mOwningContext->GetMixerUnit(), k3DMixerParam_Gain, kAudioUnitScope_Input, mCurrentPlayBus, 0.0, 0); 610 } 611*/ 612 613 static OSStatus SourceNotificationProc (void *inRefCon, 614 AudioUnitRenderActionFlags *inActionFlags, 615 const AudioTimeStamp *inTimeStamp, 616 UInt32 inBusNumber, 617 UInt32 inNumberFrames, 618 AudioBufferList *ioData); 619 620 static OSStatus SourceInputProc ( void *inRefCon, 621 AudioUnitRenderActionFlags *inActionFlags, 622 const AudioTimeStamp *inTimeStamp, 623 UInt32 inBusNumber, 624 UInt32 inNumberFrames, 625 AudioBufferList *ioData); 626 627 static OSStatus ACComplexInputDataProc ( AudioConverterRef inAudioConverter, 628 UInt32 *ioNumberDataPackets, 629 AudioBufferList *ioData, 630 AudioStreamPacketDescription **outDataPacketDescription, 631 void* inUserData); 632 633#pragma mark __________ PUBLIC __________ 634 public: 635 OALSource(ALuint inSelfToken, OALContext *inOwningContext); 636 ~OALSource(); 637 638 // set info methods - these may be called from either the render thread or the API caller 639 void SetPitch (Float32 inPitch); 640 void SetGain (Float32 inGain); 641 void SetMinGain (Float32 inMinGain); 642 void SetMaxGain (Float32 inMaxGain); 643 void SetReferenceDistance (Float32 inReferenceDistance); 644 void SetMaxDistance (Float32 inMaxDistance); 645 void SetRollOffFactor (Float32 inRollOffFactor); 646 void SetLooping (UInt32 inLooping); 647 void SetPosition (Float32 inX, Float32 inY, Float32 inZ); 648 void SetVelocity (Float32 inX, Float32 inY, Float32 inZ); 649 void SetDirection (Float32 inX, Float32 inY, Float32 inZ); 650 void SetSourceRelative (UInt32 inSourceRelative); 651 void SetChannelParameters (); 652 void SetConeInnerAngle (Float32 inConeInnerAngle); 653 void SetConeOuterAngle (Float32 inConeOuterAngle); 654 void SetConeOuterGain (Float32 inConeOuterGain); 655 void SetQueueOffset(UInt32 inOffsetType, Float32 inSecondOffset); 656 void SetUpDeconstruction(); 657 658 // get info methods 659 Float32 GetPitch (); 660 Float32 GetDopplerScaler (); 661 Float32 GetGain (); 662 Float32 GetMinGain (); 663 Float32 GetMaxGain (); 664 Float32 GetReferenceDistance (); 665 Float32 GetMaxDistance (); 666 Float32 GetRollOffFactor (); 667 UInt32 GetLooping (); 668 void GetPosition (Float32 &inX, Float32 &inY, Float32 &inZ); 669 void GetVelocity (Float32 &inX, Float32 &inY, Float32 &inZ); 670 void GetDirection (Float32 &inX, Float32 &inY, Float32 &inZ); 671 UInt32 GetSourceRelative (); 672 UInt32 GetSourceType (); 673 Float32 GetConeInnerAngle (); 674 Float32 GetConeOuterAngle (); 675 Float32 GetConeOuterGain (); 676 UInt32 GetState(); 677 ALuint GetToken(); 678 UInt32 GetQueueFrameOffset(); 679 UInt32 GetQueueOffset(UInt32 inOffsetType); 680 Float32 GetQueueOffsetSecondsFloat(); 681 682 // thread safety 683 void SetInUseFlag() { OSAtomicIncrement32Barrier(&mInUseFlag); } 684 void ClearInUseFlag() { OSAtomicDecrement32Barrier(&mInUseFlag); } 685 686 // buffer queue 687 UInt32 GetQLengthPriv(); 688 UInt32 GetQLength(); 689 UInt32 GetBuffersProcessed(); 690 void SetBuffer (ALuint inBufferToken, OALBuffer *inBuffer); 691 ALuint GetBuffer (); 692 void AddToQueue(ALuint inBufferToken, OALBuffer *inBuffer); 693 void AddToTempQueue(ALuint inBufferToken, OALBuffer *inBuffer); 694 void RemoveBuffersFromQueue(UInt32 inCount, ALuint *outBufferTokens); 695 bool IsSourceTransitioningToFlushQ(); 696 bool IsSafeForDeletion () { return (mSafeForDeletion && (mInUseFlag <= 0) && mSourceLock.IsFree()); } 697 698 // source notification methods 699 ALenum AddNotification(ALuint notificationID, alSourceNotificationProc notifyProc, ALvoid* userData); 700 void RemoveNotification(ALuint notificationID, alSourceNotificationProc notifyProc, ALvoid* userData); 701 702 // notification methods 703 void ClearMessageQueue(); 704 void SwapBufferQueues(); 705 void AddPlaybackMessage(UInt32 inMessage, OALBuffer* inBuffer, UInt32 inNumBuffers); 706 void SetPlaybackState(ALuint inState, bool sendSourceStateChangeNotification=false); 707 708 OSStatus DoPreRender (); 709 OSStatus DoPostRender (); 710 711 // playback methods 712 void Play(); 713 void Pause(); 714 void Resume(); 715 void Rewind(); 716 void Stop(); 717 718 void Suspend(); 719 void Unsuspend(); 720 721 // ASA methods 722 void SetReverbSendLevel(Float32 inReverbLevel); 723 void SetOcclusion(Float32 inOcclusion); 724 void SetObstruction(Float32 inObstruction); 725 726 void SetRogerBeepEnable(Boolean inEnable); 727 void SetRogerBeepOn(Boolean inOn); 728 void SetRogerBeepGain(Float32 inGain); 729 void SetRogerBeepSensitivity(SInt32 inSensitivity); 730 void SetRogerBeepType(SInt32 inType); 731 void SetRogerBeepPreset(FSRef* inRef); 732 733 void SetDistortionEnable(Boolean inEnable); 734 void SetDistortionOn(Boolean inOn); 735 void SetDistortionMix(Float32 inMix); 736 void SetDistortionType(SInt32 inType); 737 void SetDistortionPreset(FSRef* inRef); 738 739 Float32 GetReverbSendLevel() {return mASAReverbSendLevel;} 740 Float32 GetOcclusion() {return mASAOcclusion;} 741 Float32 GetObstruction() {return mASAObstruction;} 742 743 Boolean GetRogerBeepEnable() {return mASARogerBeepEnable;} 744 Boolean GetRogerBeepOn() {return mASARogerBeepOn;} 745 Float32 GetRogerBeepGain() {return mASARogerBeepGain;} 746 UInt32 GetRogerBeepSensitivity() {return mASARogerBeepSensitivity;} 747 UInt32 GetRogerBeepType() {return mASARogerBeepType;} 748 749 Boolean GetDistortionEnable() {return mASADistortionEnable;} 750 Boolean GetDistortionOn() {return mASADistortionOn;} 751 Float32 GetDistortionMix() {return mASADistortionMix;} 752 SInt32 GetDistortionType() {return mASADistortionType;} 753}; 754 755// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 756#pragma mark _____OALSourceMap_____ 757// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 758class OALSourceMap : std::multimap<ALuint, OALSource*, std::less<ALuint> > { 759public: 760 761 // add a new context to the map 762 void Add (const ALuint inSourceToken, OALSource **inSource) { 763 iterator it = upper_bound(inSourceToken); 764 insert(it, value_type (inSourceToken, *inSource)); 765 } 766 767 OALSource* GetSourceByIndex(UInt32 inIndex) { 768 iterator it = begin(); 769 770 for (UInt32 i = 0; i < inIndex; i++) { 771 if (it != end()) 772 ++it; 773 else 774 i = inIndex; 775 } 776 777 if (it != end()) 778 return ((*it).second); 779 return (NULL); 780 } 781 782 OALSource* Get(ALuint inSourceToken) { 783 iterator it = find(inSourceToken); 784 if (it != end()) 785 return ((*it).second); 786 return (NULL); 787 } 788 789 void MarkAllSourcesForRecalculation() { 790 iterator it = begin(); 791 while (it != end()) { 792 (*it).second->SetChannelParameters(); 793 ++it; 794 } 795 return; 796 } 797 798 void SuspendAllSources() { 799 iterator it = begin(); 800 while (it != end()) 801 { 802 (*it).second->Suspend(); 803 ++it; 804 } 805 return; 806 } 807 808 void UnsuspendAllSources() { 809 iterator it = begin(); 810 while (it != end()) 811 { 812 (*it).second->Unsuspend(); 813 ++it; 814 } 815 return; 816 } 817 818 void Remove (const ALuint inSourceToken) { 819 iterator it = find(inSourceToken); 820 if (it != end()) 821 erase(it); 822 } 823 824 UInt32 Size () const { return size(); } 825 bool Empty () const { return empty(); } 826}; 827 828#endif