/*============================================================================= oalDevice.h al_osx Created by Bob Aron on Mon Oct 13 2003. Copyright (c) 2003 Apple Computer Inc. All rights reserved. $Log: oalDevice.h,v $ Revision 1.21 2004/09/27 21:40:24 baron Make the OALSource object thread safe by using two bufferQ lists and mutexes. Don't dereference NULL ptr. [3791105, 3791120] Revision 1.20 2004/09/02 20:20:07 baron Add workaround for DistanceParameter problem in the 2.0 3DMixer. Allow Doppler to be turned ON. Allow OAL Distance Model to be AL_NONE. Revision 1.19 2004/04/23 16:56:39 baron Correctly set the DistanceAtten property when using the v1.3 3DMixer. Rolloff curve should now be correct and this change fine tunes the change to scale distance calculations to the reference distance. Explicitly set the channel layout on the mixer and output unit. Revision 1.18 2004/03/19 22:43:59 baron Add BSD License and clean up comments before submitting to Open Source (Creative). Revision 1.17 2004/03/11 19:42:22 baron Add extension to clamp rendering to stereo (ALC_RENDER_CHANNEL_COUNT). Merge the OAL3DGraph and OALDevice classes. General clean up. Revision 1.16 2004/03/09 18:34:44 baron Add extensions to set Maximum Bus count on mixer and to force stereo rendering even on multichannel hardware. Revision 1.15 2004/02/25 21:52:53 baron Do not try and set the bus count if the new 3DMixer is not present. Revision 1.14 2004/02/25 20:51:55 baron Check version of 3DMixer component and fail if pre-Panther version. Use playback rate parameter to adjust sample rates if 3DMixer is not 2.0 or >, else use stream format property to change sample rates on the mixer busses. Revision 1.13 2004/02/13 23:03:23 baron Add reverb support. Not yet exposed through the API however. Revision 1.12 2004/02/13 02:34:34 baron Check for NANs. Add 3DMixer Distance Params support. Partial Min/Max Gain changes. Everything builds and works, some commented code needs to be clean up still. Revision 1.11 2004/02/11 18:18:20 baron Add a mixer sample rate member to the Device class. Fix the channel layout support. Cleanup. Revision 1.10 2004/02/04 17:28:58 baron Add some Mixer Bus Logging code. Revision 1.9 2004/01/29 22:06:19 baron Fix all the renderflag, spatialization setting code. Make settable from the API set. Add support for multi channel hw. Revision 1.8 2004/01/20 02:09:46 baron Make max channels 64 for now. Change to 256 later when 3DMixer is fixed. Revision 1.7 2004/01/20 00:46:02 baron Remember the spatial settings for each bus. Add some AUTracer code. Revision 1.6 2003/12/17 18:33:05 baron Add Speaker Configuration support. Revision 1.5 2003/12/17 00:21:14 baron Add support for a internal mix sample rate. Dependent on enhancements to the 3DMixer. Revision 1.4 2003/12/09 01:26:21 baron more cleanup. Revision 1.3 2003/12/03 23:17:09 baron Add some doppler support and clean up comments Revision 1.2 2003/12/02 18:59:50 baron Add check-in comment logging. $NoKeywords: $ =============================================================================*/ /********************************************************************************************************************************** * * OpenAL cross platform audio library * Copyright © 2004, Apple Computer, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **********************************************************************************************************************************/ #ifndef __OAL_DEVICE__ #define __OAL_DEVICE__ #include "oalImp.h" #include #include #include #include #include #include "CAStreamBasicDescription.h" #define LOG_BUS_CONNECTIONS 0 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Some build flags for gathering performance and data flow information #if USE_AU_TRACER #include "AUTracer.h" #endif #if DEBUG #define AUHAL_LOG_OUTPUT 0 #endif #if AUHAL_LOG_OUTPUT #include "AudioLogger.h" #endif // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Device Constants // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define kDefaultReferenceDistance 1.0 #define kDefaultMaximumDistance 1000000.0 #define kDefaultRolloff 1.0 #define kPreferredMixerVersion 0x21000 #define kMinimumMixerVersion 0x10300 // Default Mixer Output Sample Rate Setting: #define kDefaultMixerRate 44100.0 // Default Low Quality Stereo Spatial Setting: #define kDefaultLowQuality kSpatializationAlgorithm_EqualPowerPanning // Default High Quality Stereo Spatial Setting: #define kDefaultHighQuality kSpatializationAlgorithm_HRTF // Default MultiChannel Spatial Setting: #define kDefaultMultiChannelQuality kSpatializationAlgorithm_SoundField // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Device Structs // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ struct BusInfo { bool mIsAvailable; // is an OALSource using this bus? UInt32 mNumberChannels; // mono/stereo setting of the bus UInt32 mReverbSetting; // unused until Reverb extension is added to the implementation }; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // OALDevices // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class OALDevice { public: OALDevice(const char* inDeviceName, UInt32 inSelfToken, UInt32 &inBusCount); ~OALDevice(); // graph methods void InitializeGraph (const char* inDeviceName); void SetupGraph(); void TeardownGraph(); void ConfigureGraphForChannelLayout(); // bus methods UInt32 GetAvailableMonoBus (); UInt32 GetAvailableStereoBus (); UInt32 GetBusCount() const { return mBusCount; } void SetBusAsAvailable (UInt32 inBusIndex) const; void InitRenderQualityOnBusses(UInt32 &inRenderQuality); // set info void SetEnvironment(OALEnvironmentInfo &inEnvironment); void SetMixerRate (Float64 inSampleRate); void SetRenderQuality (UInt32 inRenderQuality); void SetRenderChannelCount (UInt32 inRenderChannelCount); void SetReverb(UInt32 inReverbSetting); void SetDistanceAttenuation(UInt32 inBusIndex, Float64 inRefDist, Float64 inMaxDist, Float64 inRolloff); // get info UInt32 GetDeviceToken () const { return mSelfToken; } Float64 GetMixerRate () const { return mMixerOutputRate; } UInt32 GetRenderQuality() {return mRenderQuality;} UInt32 GetRenderChannelCount() {return mRenderChannelCount; } UInt32 GetReverbSetting() const { return mReverbSetting; } AudioUnit GetMixerUnit() { return mMixerUnit;} UInt32 GetDesiredRenderChannelCount (); bool IsDistanceScalingRequired() { return mDistanceScalingRequired;} Float32 GetDefaultReferenceDistance() { return mDefaultReferenceDistance;} Float32 GetDefaultMaxDistance() { return mDefaultMaxDistance;} // misc. bool IsPreferredMixerAvailable() { return mPreferred3DMixerExists; } bool IsPlayable () { return mCanScheduleEvents; } bool IsValidRenderQuality (UInt32 inRenderQuality); void ResetChannelLayout(); static void GraphFormatPropertyListener ( void *inRefCon, AudioUnit ci, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement); bool IsGraphStillRunning () { Boolean running; OSStatus result = AUGraphIsRunning (mAUGraph, &running); THROW_RESULT return bool(running); } void Print () const { #if DEBUG || CoreAudio_Debug CAShow (mAUGraph); #endif } #pragma mark __________ Private_Class_Members private: UInt32 mSelfToken; AudioDeviceID mHALDevice; // the HAL device used to render audio to the user bool mPreferred3DMixerExists; bool mDistanceScalingRequired; Float32 mDefaultReferenceDistance; Float32 mDefaultMaxDistance; AUGraph mAUGraph; UInt32 mBusCount; BusInfo *mBusInfo; AUNode mOutputNode; AudioUnit mOutputUnit; AUNode mMixerNode; AudioUnit mMixerUnit; bool mCanScheduleEvents; Float64 mMixerOutputRate; UInt32 mCurrentMixerChannelCount; UInt32 mRenderChannelCount; // currently either stereo or multichannel UInt32 mRenderQuality; // Hi or Lo for now UInt32 mSpatialSetting; UInt32 mReverbSetting; #if LOG_BUS_CONNECTIONS UInt32 mMonoSourcesConnected; UInt32 mStereoSourcesConnected; #endif #if AUHAL_LOG_OUTPUT AudioLogger mLogger; #endif #if USE_AU_TRACER AUTracer mAUTracer; #endif }; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #pragma mark _____OALDeviceMap_____ class OALDeviceMap : std::multimap > { public: void Add (const UInt32 inDeviceToken, OALDevice **inDevice) { iterator it = upper_bound(inDeviceToken); insert(it, value_type (inDeviceToken, *inDevice)); } OALDevice* Get(UInt32 inDeviceToken) { iterator it = find(inDeviceToken); if (it != end()) return ((*it).second); return (NULL); } void Remove (const UInt32 inDeviceToken) { iterator it = find(inDeviceToken); if (it != end()) erase(it); } UInt32 Size () const { return size(); } bool Empty () const { return empty(); } }; #endif