diff --git a/Engine/lib/CMakeLists.txt b/Engine/lib/CMakeLists.txt index 246969628..d48ff6642 100644 --- a/Engine/lib/CMakeLists.txt +++ b/Engine/lib/CMakeLists.txt @@ -197,22 +197,44 @@ add_subdirectory(squish ${TORQUE_LIB_TARG_DIRECTORY}/squish EXCLUDE_FROM_ALL) add_subdirectory(collada ${TORQUE_LIB_TARG_DIRECTORY}/collada EXCLUDE_FROM_ALL) add_subdirectory(glad ${TORQUE_LIB_TARG_DIRECTORY}/glad EXCLUDE_FROM_ALL) +set(ALSOFT_REQUIRE_LINUX OFF) +set(ALSOFT_REQUIRE_WINDOWS OFF) +set(ALSOFT_REQUIRE_WINDOWS_NOT_UWP OFF) +set(ALSOFT_REQUIRE_APPLE OFF) +set(ALSOFT_CPUEXT_NEON OFF) + +if(UNIX AND NOT APPLE) + set(ALSOFT_REQUIRE_LINUX ON) +endif() +if(WIN32) + set(ALSOFT_REQUIRE_WINDOWS ON) +endif() +if(APPLE) + set(ALSOFT_REQUIRE_APPLE ON) +endif() + #hidden options if(TORQUE_SFX_OPENAL) advanced_option(TORQUE_OGGVORBIS "Enable OGG Vorbis" ON) advanced_option(ALSOFT_EAX "Enable legacy EAX extensions" ${WIN32}) advanced_option(ALSOFT_UPDATE_BUILD_VERSION "Update git build version info" ON) mark_as_advanced(ALSOFT_BACKEND_COREAUDIO) - advanced_option(ALSOFT_BACKEND_DSOUND "Enable DirectSound backend" OFF) + advanced_option(ALSOFT_BACKEND_ALSA "Enable ALSA Backend" ${ALSOFT_REQUIRE_LINUX}) + advanced_option(ALSOFT_REQUIRE_ALSA "Require ALSA Backend" ${ALSOFT_REQUIRE_LINUX}) + advanced_option(ALSOFT_BACKEND_DSOUND "Enable DirectSound backend" ${ALSOFT_REQUIRE_WINDOWS}) + advanced_option(ALSOFT_REQUIRE_DSOUND "Require DirectSound Backend" ${ALSOFT_REQUIRE_WINDOWS}) advanced_option(ALSOFT_BACKEND_JACK "Enable Jack backend" OFF) advanced_option(ALSOFT_BACKEND_OBOE "Enable OBOE backend" OFF) advanced_option(ALSOFT_BACKEND_OPENSL "Enable OpenSL backend" OFF) advanced_option(ALSOFT_BACKEND_PIPEWIRE "Enable PipeWire backend" OFF) advanced_option(ALSOFT_BACKEND_PORTAUDIO "Enable PortAudio backend" OFF) advanced_option(ALSOFT_BACKEND_PULSEAUDIO "Enable PulseAudio backend" OFF) - advanced_option(ALSOFT_BACKEND_SDL2 "Use SDL2 Backend" ON) - advanced_option(ALSOFT_BACKEND_WASAPI "Enable WASAPI backend" OFF) - advanced_option(ALSOFT_BACKEND_WAVE "Enable Wave backend" OFF) + advanced_option(ALSOFT_BACKEND_SDL2 "Use SDL2 Backend" OFF) + advanced_option(ALSOFT_BACKEND_COREAUDIO "Enable CoreAudio backend" ${ALSOFT_REQUIRE_APPLE}) + advanced_option(ALSOFT_REQUIRE_COREAUDIO "Require CoreAudio backend" ${ALSOFT_REQUIRE_APPLE}) + advanced_option(ALSOFT_BACKEND_WASAPI "Enable WASAPI backend" ${ALSOFT_REQUIRE_WINDOWS}) + advanced_option(ALSOFT_REQUIRE_WASAPI "Require WASAPI backend" ${ALSOFT_REQUIRE_WINDOWS}) + advanced_option(ALSOFT_BACKEND_WAVE "Enable Wave backend" ON) advanced_option(ALSOFT_BACKEND_WINMM "Enable WinMM backend" OFF) mark_as_advanced(ALSOFT_BUILD_ROUTER) mark_as_advanced(ALSOFT_CPUEXT_NEON) @@ -232,8 +254,6 @@ if(TORQUE_SFX_OPENAL) advanced_option(ALSOFT_INSTALL_UTILS "Install utility programs (openal-info, alsoft-config, ...)" OFF) mark_as_advanced(ALSOFT_UPDATE_BUILD_VERSION) mark_as_advanced(ALSOFT_NO_CONFIG_UTIL) - mark_as_advanced(ALSOFT_REQUIRE_COREAUDIO) - mark_as_advanced(ALSOFT_REQUIRE_DSOUND) mark_as_advanced(ALSOFT_REQUIRE_JACK) mark_as_advanced(ALSOFT_REQUIRE_NEON) mark_as_advanced(ALSOFT_REQUIRE_OBOE) @@ -246,7 +266,6 @@ if(TORQUE_SFX_OPENAL) mark_as_advanced(ALSOFT_REQUIRE_SSE2) mark_as_advanced(ALSOFT_REQUIRE_SSE3) mark_as_advanced(ALSOFT_REQUIRE_SSE4_1) - mark_as_advanced(ALSOFT_REQUIRE_WASAPI) mark_as_advanced(ALSOFT_REQUIRE_WINMM) mark_as_advanced(ALSOFT_SEARCH_INSTALL_DATADIR) mark_as_advanced(ALSOFT_TESTS) diff --git a/Engine/source/T3D/assets/SoundAsset.cpp b/Engine/source/T3D/assets/SoundAsset.cpp index e8b6d3cdb..b1a49a32a 100644 --- a/Engine/source/T3D/assets/SoundAsset.cpp +++ b/Engine/source/T3D/assets/SoundAsset.cpp @@ -59,31 +59,43 @@ IMPLEMENT_CONOBJECT(SoundAsset); -ConsoleType(SoundAssetPtr, TypeSoundAssetPtr, const char*, ASSET_ID_FIELD_PREFIX) +IMPLEMENT_STRUCT(AssetPtr, AssetPtrSoundAsset, , "") +END_IMPLEMENT_STRUCT -//----------------------------------------------------------------------------- +ConsoleType(SoundAssetPtr, TypeSoundAssetPtr, AssetPtr, ASSET_ID_FIELD_PREFIX) ConsoleGetType(TypeSoundAssetPtr) { // Fetch asset Id. - return *((const char**)(dptr)); + return (*((AssetPtr*)dptr)).getAssetId(); } -//----------------------------------------------------------------------------- - ConsoleSetType(TypeSoundAssetPtr) { // Was a single argument specified? if (argc == 1) { // Yes, so fetch field value. - *((const char**)dptr) = StringTable->insert(argv[0]); + const char* pFieldValue = argv[0]; + + // Fetch asset pointer. + AssetPtr* pAssetPtr = dynamic_cast*>((AssetPtrBase*)(dptr)); + + // Is the asset pointer the correct type? + if (pAssetPtr == NULL) + { + Con::warnf("(TypeSoundAssetPtrRefactor) - Failed to set asset Id '%d'.", pFieldValue); + return; + } + + // Set asset. + pAssetPtr->setAssetId(pFieldValue); return; } // Warn. - Con::warnf("(TypeSoundAssetPtr) - Cannot set multiple args to a single asset."); + Con::warnf("(TypeSoundAssetPtrRefactor) - Cannot set multiple args to a single asset."); } //----------------------------------------------------------------------------- @@ -134,7 +146,7 @@ SoundAsset::SoundAsset() for (U32 i = 0; i < SFXPlayList::NUM_SLOTS; i++) { mSoundFile[i] = StringTable->EmptyString(); - mSoundPath[i] = StringTable->EmptyString(); + mSoundResource[i] = NULL; mPlaylist.mSlots.mTransitionOut[i] = SFXPlayList::TRANSITION_Wait; mPlaylist.mSlots.mVolumeScale.mValue[i] = 1.f; @@ -173,7 +185,8 @@ SoundAsset::SoundAsset() mProfileDesc.mPriority = 1.0f; mProfileDesc.mSourceGroup = NULL; mProfileDesc.mFadeInEase = EaseF(); - mProfileDesc.mReverb = SFXSoundReverbProperties(); + mProfileDesc.mSourceGroup = dynamic_cast(Sim::findObject("AudioChannelMaster")); + dMemset(mProfileDesc.mParameters, 0, sizeof(mProfileDesc.mParameters)); mIsPlaylist = false; @@ -183,6 +196,9 @@ SoundAsset::SoundAsset() mPlaylist.mLoopMode = SFXPlayList::LOOP_All; mPlaylist.mActiveSlots = 1; + mResolvedTrack = NULL; + mResolvedDescription = NULL; + } //----------------------------------------------------------------------------- @@ -190,8 +206,17 @@ SoundAsset::SoundAsset() SoundAsset::~SoundAsset() { - if (mPlaylist.isProperlyAdded() && !mPlaylist.isDeleted()) - mPlaylist.unregisterObject(); + if (mResolvedTrack) + { + if (mResolvedTrack->isProperlyAdded() && !mResolvedTrack->isDeleted()) + mResolvedTrack->deleteObject(); + } + + if (mResolvedDescription) + { + if (mResolvedDescription->isProperlyAdded() && !mResolvedDescription->isDeleted()) + mResolvedDescription->deleteObject(); + } } //----------------------------------------------------------------------------- @@ -202,77 +227,77 @@ void SoundAsset::initPersistFields() Parent::initPersistFields(); addGroup("SoundSlots"); addArray("slots", SFXPlayList::SFXPlaylistSettings::NUM_SLOTS); - addProtectedField("soundFile", TypeAssetLooseFilePath, Offset(mSoundFile, SoundAsset), - &_setSoundFile, &defaultProtectedGetFn, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, "Path to the sound file."); + addProtectedField("soundFile", TypeAssetLooseFilePath, Offset(mSoundFile, SoundAsset), + &_setSoundFile, &defaultProtectedGetFn, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, "Path to the sound file."); - addField("replay", TYPEID< SFXPlayList::EReplayMode >(), Offset(mPlaylist.mSlots.mReplayMode, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Behavior when an already playing sound is encountered on this slot from a previous cycle.\n" - "Each slot can have an arbitrary number of sounds playing on it from previous cycles. This field determines " - "how SFXController will handle these sources."); - addField("transitionIn", TYPEID< SFXPlayList::ETransitionMode >(), Offset(mPlaylist.mSlots.mTransitionIn, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Behavior when moving into this slot.\n" - "After the delayIn time has expired (if any), this slot determines what the controller " - "will do before actually playing the slot."); - addField("transitionOut", TYPEID< SFXPlayList::ETransitionMode >(), Offset(mPlaylist.mSlots.mTransitionOut, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Behavior when moving out of this slot.\n" - "After the #detailTimeOut has expired (if any), this slot determines what the controller " - "will do before moving on to the next slot."); - addFieldV("delayTimeIn", TypeRangedF32, Offset(mPlaylist.mSlots.mDelayTimeIn.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Seconds to wait after moving into slot before #transitionIn."); - addField("delayTimeInVariance", TypePoint2F, Offset(mPlaylist.mSlots.mDelayTimeIn.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Bounds on randomization of #delayTimeIn.\n\n" - "@ref SFXPlayList_randomization\n"); - addFieldV("delayTimeOut", TypeRangedF32, Offset(mPlaylist.mSlots.mDelayTimeOut.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Seconds to wait before moving out of slot after #transitionOut."); - addField("delayTimeOutVariance", TypePoint2F, Offset(mPlaylist.mSlots.mDelayTimeOut.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Bounds on randomization of #delayTimeOut.\n\n" - "@ref SFXPlayList_randomization\n"); - addFieldV("fadeTimeIn", TypeRangedF32, Offset(mPlaylist.mSlots.mFadeTimeIn.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Seconds to fade sound in (-1 to use the track's own fadeInTime.)\n" - "@see SFXDescription::fadeTimeIn"); - addField("fadeTimeInVariance", TypePoint2F, Offset(mPlaylist.mSlots.mFadeTimeIn.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Bounds on randomization of #fadeInTime.\n\n" - "@ref SFXPlayList_randomization\n"); - addFieldV("fadeTimeOut", TypeRangedF32, Offset(mPlaylist.mSlots.mFadeTimeOut.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Seconds to fade sound out (-1 to use the track's own fadeOutTime.)\n" - "@see SFXDescription::fadeTimeOut"); - addField("fadeTimeOutVariance", TypePoint2F, Offset(mPlaylist.mSlots.mFadeTimeOut.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Bounds on randomization of #fadeOutTime\n\n" - "@ref SFXPlayList_randomization\n"); - addFieldV("referenceDistance", TypeRangedF32, Offset(mPlaylist.mSlots.mMinDistance.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "@c referenceDistance to set for 3D sounds in this slot (<1 to use @c referenceDistance of track's own description).\n" - "@see SFXDescription::referenceDistance"); - addField("referenceDistanceVariance", TypePoint2F, Offset(mPlaylist.mSlots.mMinDistance.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Bounds on randomization of #referenceDistance.\n\n" - "@ref SFXPlayList_randomization\n"); - addFieldV("maxSlotDistance", TypeRangedF32, Offset(mPlaylist.mSlots.mMaxDistance.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "@c maxDistance to apply to 3D sounds in this slot (<1 to use @c maxDistance of track's own description).\n" - "@see SFXDescription::maxDistance"); - addField("maxSlotDistanceVariance", TypePoint2F, Offset(mPlaylist.mSlots.mMaxDistance.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Bounds on randomization of #maxDistance.\n\n" - "@ref SFXPlayList_randomization\n"); - addFieldV("volumeScale", TypeRangedF32, Offset(mPlaylist.mSlots.mVolumeScale.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Scale factor to apply to volume of sounds played on this list slot.\n" - "This value will scale the actual volume level set on the track assigned to the slot, i.e. a value of 0.5 will " - "cause the track to play at half-volume."); - addField("volumeScaleVariance", TypePoint2F, Offset(mPlaylist.mSlots.mVolumeScale.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Bounds on randomization of #volumeScale.\n\n" - "@ref SFXPlayList_randomization\n"); - addFieldV("pitchScale", TypeRangedF32, Offset(mPlaylist.mSlots.mPitchScale.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Scale factor to apply to pitch of sounds played on this list slot.\n" - "This value will scale the actual pitch set on the track assigned to the slot, i.e. a value of 0.5 will " - "cause the track to play at half its assigned speed."); - addField("pitchScaleVariance", TypePoint2F, Offset(mPlaylist.mSlots.mPitchScale.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Bounds on randomization of #pitchScale.\n\n" - "@ref SFXPlayList_randomization\n"); - addFieldV("repeatCount", TypeRangedS32, Offset(mPlaylist.mSlots.mRepeatCount, SoundAsset), &CommonValidators::PositiveInt, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Number of times to loop this slot."); - addField("state", TypeSFXStateName, Offset(mPlaylist.mSlots.mState, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "State that must be active for this slot to play.\n\n" - "@ref SFXPlayList_states"); - addField("stateMode", TYPEID< SFXPlayList::EStateMode >(), Offset(mPlaylist.mSlots.mStateMode, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, - "Behavior when assigned state is deactivated while slot is playing.\n\n" - "@ref SFXPlayList_states"); + addField("replay", TYPEID< SFXPlayList::EReplayMode >(), Offset(mPlaylist.mSlots.mReplayMode, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Behavior when an already playing sound is encountered on this slot from a previous cycle.\n" + "Each slot can have an arbitrary number of sounds playing on it from previous cycles. This field determines " + "how SFXController will handle these sources."); + addField("transitionIn", TYPEID< SFXPlayList::ETransitionMode >(), Offset(mPlaylist.mSlots.mTransitionIn, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Behavior when moving into this slot.\n" + "After the delayIn time has expired (if any), this slot determines what the controller " + "will do before actually playing the slot."); + addField("transitionOut", TYPEID< SFXPlayList::ETransitionMode >(), Offset(mPlaylist.mSlots.mTransitionOut, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Behavior when moving out of this slot.\n" + "After the #detailTimeOut has expired (if any), this slot determines what the controller " + "will do before moving on to the next slot."); + addFieldV("delayTimeIn", TypeRangedF32, Offset(mPlaylist.mSlots.mDelayTimeIn.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Seconds to wait after moving into slot before #transitionIn."); + addField("delayTimeInVariance", TypePoint2F, Offset(mPlaylist.mSlots.mDelayTimeIn.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Bounds on randomization of #delayTimeIn.\n\n" + "@ref SFXPlayList_randomization\n"); + addFieldV("delayTimeOut", TypeRangedF32, Offset(mPlaylist.mSlots.mDelayTimeOut.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Seconds to wait before moving out of slot after #transitionOut."); + addField("delayTimeOutVariance", TypePoint2F, Offset(mPlaylist.mSlots.mDelayTimeOut.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Bounds on randomization of #delayTimeOut.\n\n" + "@ref SFXPlayList_randomization\n"); + addFieldV("fadeTimeIn", TypeRangedF32, Offset(mPlaylist.mSlots.mFadeTimeIn.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Seconds to fade sound in (-1 to use the track's own fadeInTime.)\n" + "@see SFXDescription::fadeTimeIn"); + addField("fadeTimeInVariance", TypePoint2F, Offset(mPlaylist.mSlots.mFadeTimeIn.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Bounds on randomization of #fadeInTime.\n\n" + "@ref SFXPlayList_randomization\n"); + addFieldV("fadeTimeOut", TypeRangedF32, Offset(mPlaylist.mSlots.mFadeTimeOut.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Seconds to fade sound out (-1 to use the track's own fadeOutTime.)\n" + "@see SFXDescription::fadeTimeOut"); + addField("fadeTimeOutVariance", TypePoint2F, Offset(mPlaylist.mSlots.mFadeTimeOut.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Bounds on randomization of #fadeOutTime\n\n" + "@ref SFXPlayList_randomization\n"); + addFieldV("referenceDistance", TypeRangedF32, Offset(mPlaylist.mSlots.mMinDistance.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "@c referenceDistance to set for 3D sounds in this slot (<1 to use @c referenceDistance of track's own description).\n" + "@see SFXDescription::referenceDistance"); + addField("referenceDistanceVariance", TypePoint2F, Offset(mPlaylist.mSlots.mMinDistance.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Bounds on randomization of #referenceDistance.\n\n" + "@ref SFXPlayList_randomization\n"); + addFieldV("maxSlotDistance", TypeRangedF32, Offset(mPlaylist.mSlots.mMaxDistance.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "@c maxDistance to apply to 3D sounds in this slot (<1 to use @c maxDistance of track's own description).\n" + "@see SFXDescription::maxDistance"); + addField("maxSlotDistanceVariance", TypePoint2F, Offset(mPlaylist.mSlots.mMaxDistance.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Bounds on randomization of #maxDistance.\n\n" + "@ref SFXPlayList_randomization\n"); + addFieldV("volumeScale", TypeRangedF32, Offset(mPlaylist.mSlots.mVolumeScale.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Scale factor to apply to volume of sounds played on this list slot.\n" + "This value will scale the actual volume level set on the track assigned to the slot, i.e. a value of 0.5 will " + "cause the track to play at half-volume."); + addField("volumeScaleVariance", TypePoint2F, Offset(mPlaylist.mSlots.mVolumeScale.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Bounds on randomization of #volumeScale.\n\n" + "@ref SFXPlayList_randomization\n"); + addFieldV("pitchScale", TypeRangedF32, Offset(mPlaylist.mSlots.mPitchScale.mValue, SoundAsset), &CommonValidators::PositiveFloat, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Scale factor to apply to pitch of sounds played on this list slot.\n" + "This value will scale the actual pitch set on the track assigned to the slot, i.e. a value of 0.5 will " + "cause the track to play at half its assigned speed."); + addField("pitchScaleVariance", TypePoint2F, Offset(mPlaylist.mSlots.mPitchScale.mVariance, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Bounds on randomization of #pitchScale.\n\n" + "@ref SFXPlayList_randomization\n"); + addFieldV("repeatCount", TypeRangedS32, Offset(mPlaylist.mSlots.mRepeatCount, SoundAsset), &CommonValidators::PositiveInt, SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Number of times to loop this slot."); + addField("state", TypeSFXStateName, Offset(mPlaylist.mSlots.mState, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "State that must be active for this slot to play.\n\n" + "@ref SFXPlayList_states"); + addField("stateMode", TYPEID< SFXPlayList::EStateMode >(), Offset(mPlaylist.mSlots.mStateMode, SoundAsset), SFXPlayList::SFXPlaylistSettings::NUM_SLOTS, + "Behavior when assigned state is deactivated while slot is playing.\n\n" + "@ref SFXPlayList_states"); endArray("slots"); endGroup("SoundSlots"); @@ -284,48 +309,79 @@ void SoundAsset::initPersistFields() // if streaming, a default packet size should be chosen for all sounds. addField("isStreaming", TypeBool, Offset(mProfileDesc.mIsStreaming, SoundAsset), "Use streaming."); //....why? + addFieldV("priority", TypeRangedF32, Offset(mProfileDesc.mPriority, SoundAsset), &CommonValidators::PositiveFloat, "Priority level for virtualization of sounds (1 = base level).\n" + "When there are more concurrently active sounds than supported by the audio mixer, some of the sounds " + "need to be culled. Which sounds are culled first depends primarily on total audibility of individual sounds. " + "However, the priority of invidual sounds may be decreased or decreased through this field.\n\n" + "@ref SFXSound_virtualization"); + addField("parameters", TypeSFXParameterName, Offset(mProfileDesc.mParameters, SoundAsset), SFXDescription::MaxNumParameters, + "Names of the parameters to which sources using this description will automatically be linked.\n\n" + "Individual parameters are identified by their #internalName.\n\n" + "@ref SFX_interactive"); addField("useHardware", TypeBool, Offset(mProfileDesc.mUseHardware, SoundAsset), "Use hardware mixing for this sound."); addField("sourceGroup", TypeSFXSourceName, Offset(mProfileDesc.mSourceGroup, SoundAsset), "Group that sources playing with this description should be put into."); addField("preload", TypeBool, Offset(mPreload, SoundAsset), "Whether to preload sound data when the profile is added to system."); endGroup("General Profile"); addGroup("Fading"); - addFieldV("fadeInTime", TypeRangedF32, Offset(mProfileDesc.mFadeInTime, SoundAsset), &CommonValidators::PositiveFloat, "Number of seconds to gradually fade in volume from zero when playback starts."); - addFieldV("fadeOutTime", TypeRangedF32, Offset(mProfileDesc.mFadeOutTime, SoundAsset), &CommonValidators::PositiveFloat, "Number of seconds to gradually fade out volume down to zero when playback is stopped or paused."); - addField("fadeInEase", TypeEaseF, Offset(mProfileDesc.mFadeInEase, SoundAsset), "Easing curve for fade-in transition."); - addField("fadeOutEase", TypeEaseF, Offset(mProfileDesc.mFadeOutEase, SoundAsset), "Easing curve for fade-out transition."); - addField("fadeLoops", TypeBool, Offset(mProfileDesc.mFadeLoops, SoundAsset), "Fade each cycle of a loop in and/or out; otherwise only fade-in first cycle."); + addFieldV("fadeInTime", TypeRangedF32, Offset(mProfileDesc.mFadeInTime, SoundAsset), &CommonValidators::PositiveFloat, "Number of seconds to gradually fade in volume from zero when playback starts."); + addFieldV("fadeOutTime", TypeRangedF32, Offset(mProfileDesc.mFadeOutTime, SoundAsset), &CommonValidators::PositiveFloat, "Number of seconds to gradually fade out volume down to zero when playback is stopped or paused."); + addField("fadeInEase", TypeEaseF, Offset(mProfileDesc.mFadeInEase, SoundAsset), "Easing curve for fade-in transition."); + addField("fadeOutEase", TypeEaseF, Offset(mProfileDesc.mFadeOutEase, SoundAsset), "Easing curve for fade-out transition."); + addField("fadeLoops", TypeBool, Offset(mProfileDesc.mFadeLoops, SoundAsset), "Fade each cycle of a loop in and/or out; otherwise only fade-in first cycle."); endGroup("Fading"); addGroup("3D"); - addFieldV("minDistance", TypeRangedF32, Offset(mProfileDesc.mMinDistance, SoundAsset), &CommonValidators::PositiveFloat, "Minimum distance for sound."); - addFieldV("maxDistance", TypeRangedF32, Offset(mProfileDesc.mMaxDistance, SoundAsset), &CommonValidators::PositiveFloat, "Max distance for sound."); - addFieldV("coneInsideAngle", TypeRangedS32, Offset(mProfileDesc.mConeInsideAngle, SoundAsset), &CommonValidators::S32_PosDegreeRange, "Cone inside angle."); - addFieldV("coneOutsideAngle", TypeRangedS32, Offset(mProfileDesc.mConeOutsideAngle, SoundAsset), &CommonValidators::S32_PosDegreeRange, "Cone outside angle."); - addFieldV("coneOutsideVolume", TypeRangedF32, Offset(mProfileDesc.mConeOutsideVolume, SoundAsset), &CommonValidators::NormalizedFloat, "Cone outside volume."); - addFieldV("rolloffFactor", TypeRangedF32, Offset(mProfileDesc.mRolloffFactor, SoundAsset), &CommonValidators::NegDefaultF32, "Rolloff factor."); - addField("scatterDistance", TypePoint3F, Offset(mProfileDesc.mScatterDistance, SoundAsset), "Randomization to the spacial position of the sound."); + addFieldV("minDistance", TypeRangedF32, Offset(mProfileDesc.mMinDistance, SoundAsset), &CommonValidators::PositiveFloat, "Minimum distance for sound."); + addFieldV("maxDistance", TypeRangedF32, Offset(mProfileDesc.mMaxDistance, SoundAsset), &CommonValidators::PositiveFloat, "Max distance for sound."); + addFieldV("coneInsideAngle", TypeRangedS32, Offset(mProfileDesc.mConeInsideAngle, SoundAsset), &CommonValidators::S32_PosDegreeRange, "Cone inside angle."); + addFieldV("coneOutsideAngle", TypeRangedS32, Offset(mProfileDesc.mConeOutsideAngle, SoundAsset), &CommonValidators::S32_PosDegreeRange, "Cone outside angle."); + addFieldV("coneOutsideVolume", TypeRangedF32, Offset(mProfileDesc.mConeOutsideVolume, SoundAsset), &CommonValidators::NormalizedFloat, "Cone outside volume."); + addFieldV("rolloffFactor", TypeRangedF32, Offset(mProfileDesc.mRolloffFactor, SoundAsset), &CommonValidators::NegDefaultF32, "Rolloff factor."); + addField("scatterDistance", TypePoint3F, Offset(mProfileDesc.mScatterDistance, SoundAsset), "Randomization to the spacial position of the sound."); endGroup("3D"); addGroup("Playlist settings"); - addField("random", TYPEID< SFXPlayList::ERandomMode >(), Offset(mPlaylist.mRandomMode, SoundAsset), "Slot playback order randomization pattern."); - addField("loopMode", TYPEID< SFXPlayList::ELoopMode >(), Offset(mPlaylist.mLoopMode, SoundAsset), "Behavior when description has looping enabled."); - addFieldV("numSlotsToPlay", TypeRangedS32, Offset(mPlaylist.mNumSlotsToPlay, SoundAsset), &playlistSlotRange, "Number of slots to play."); - addField("trace", TypeBool, Offset(mPlaylist.mTrace, SoundAsset), "Enable/disable execution tracing for this playlist (local only)."); + addField("random", TYPEID< SFXPlayList::ERandomMode >(), Offset(mPlaylist.mRandomMode, SoundAsset), "Slot playback order randomization pattern."); + addField("loopMode", TYPEID< SFXPlayList::ELoopMode >(), Offset(mPlaylist.mLoopMode, SoundAsset), "Behavior when description has looping enabled."); + addFieldV("numSlotsToPlay", TypeRangedS32, Offset(mPlaylist.mNumSlotsToPlay, SoundAsset), &playlistSlotRange, "Number of slots to play."); + addField("trace", TypeBool, Offset(mPlaylist.mTrace, SoundAsset), "Enable/disable execution tracing for this playlist (local only)."); endGroup("Playlist settings"); } //------------------------------------------------------------------------------ +void SoundAsset::onRemove() +{ + for (U32 i = 0; i < SFXPlayList::SFXPlaylistSettings::NUM_SLOTS; i++) + { + if (mSoundFile[i] == StringTable->EmptyString()) + break; + + Torque::FS::RemoveChangeNotification(mSoundFile[i], this, &SoundAsset::_onResourceChanged); + } + + Parent::onRemove(); +} + +void SoundAsset::inspectPostApply() +{ + Parent::inspectPostApply(); + + refreshAsset(); +} + void SoundAsset::copyTo(SimObject* object) { // Call to parent. Parent::copyTo(object); + } void SoundAsset::initializeAsset(void) { Parent::initializeAsset(); + for (U32 i = 0; i < SFXPlayList::SFXPlaylistSettings::NUM_SLOTS; i++) { if (i == 0 && mSoundFile[i] == StringTable->EmptyString()) @@ -334,134 +390,59 @@ void SoundAsset::initializeAsset(void) if (mSoundFile[i] == StringTable->EmptyString()) break; - mSoundPath[i] = getOwned() ? expandAssetFilePath(mSoundFile[i]) : mSoundPath[i]; - if (!Torque::FS::IsFile(mSoundPath[i])) - Con::errorf("SoundAsset::initializeAsset (%s)[%d] could not find %s!", getAssetName(), i, mSoundPath[i]); + mSoundFile[i] = expandAssetFilePath(mSoundFile[i]); + if (getOwned()) + Torque::FS::AddChangeNotification(mSoundFile[i], this, &SoundAsset::_onResourceChanged); } + + populateSFXTrack(); } -void SoundAsset::_onResourceChanged(const Torque::Path &path) +void SoundAsset::_onResourceChanged(const Torque::Path& path) { for (U32 i = 0; i < SFXPlayList::NUM_SLOTS; i++) { - if (path != Torque::Path(mSoundPath[i])) + if (path != Torque::Path(mSoundFile[i])) return; } + refreshAsset(); } void SoundAsset::onAssetRefresh(void) { - for (U32 i = 0; i < SFXPlayList::SFXPlaylistSettings::NUM_SLOTS; i++) - { - if (i == 0 && mSoundFile[i] == StringTable->EmptyString()) - return; + if (!isProperlyAdded()) + return; - if (mSoundFile[i] == StringTable->EmptyString()) - break; - - mSoundPath[i] = getOwned() ? expandAssetFilePath(mSoundFile[i]) : mSoundPath[i]; - } + Parent::onAssetRefresh(); + populateSFXTrack(); } U32 SoundAsset::load() { - if (mLoadedState == AssetErrCode::Ok) return mLoadedState; + if (mLoadedState == AssetErrCode::Ok) + return mLoadedState; - // find out how many active slots we have. - U32 numSlots = 0; - for (U32 i = 0; i < SFXPlayList::SFXPlaylistSettings::NUM_SLOTS; i++) + if (!mResolvedTrack) { - if (i == 0 && mSoundPath[i] == StringTable->EmptyString()) - return false; - - if (mSoundPath[i] == StringTable->EmptyString()) - break; - - numSlots++; - } - - if (mProfileDesc.mSourceGroup == NULL) - mProfileDesc.mSourceGroup = dynamic_cast(Sim::findObject("AudioChannelMaster")); - - if (numSlots > 1) - { - mIsPlaylist = true; - - for (U32 i = 0; i < numSlots; i++) + if (mIsPlaylist) { - if (mSoundPath[i]) - { - if (!Torque::FS::IsFile(mSoundPath[i])) - { - Con::errorf("SoundAsset::initializeAsset: Attempted to load file %s but it was not valid!", mSoundFile[i]); - mLoadedState = BadFileReference; - return mLoadedState; - } - else - { - mSFXProfile[i] = new SFXProfile; - mSFXProfile[i]->setDescription(&mProfileDesc); - mSFXProfile[i]->setSoundFileName(mSoundPath[i]); - mSFXProfile[i]->setPreload(mPreload); - mSFXProfile[i]->registerObject(String::ToString("%s_profile_track%d", getAssetName()).c_str()); - - mPlaylist.mSlots.mTrack[i] = mSFXProfile[i]; - - } - } + mResolvedTrack = buildPlaylist(); + } + else + { + mResolvedTrack = buildProfile(); } - mPlaylist.setDescription(&mProfileDesc); - mPlaylist.registerObject(String::ToString("%s_playlist", getAssetName()).c_str()); - } - else - { - if (mSoundPath[0]) - { - if (!Torque::FS::IsFile(mSoundPath[0])) - { - Con::errorf("SoundAsset::initializeAsset: Attempted to load file %s but it was not valid!", mSoundFile[0]); - mLoadedState = BadFileReference; - return mLoadedState; - } - else - { - mSFXProfile[0] = new SFXProfile; - mSFXProfile[0]->setDescription(&mProfileDesc); - mSFXProfile[0]->setSoundFileName(mSoundPath[0]); - mSFXProfile[0]->setPreload(mPreload); - mSFXProfile[0]->registerObject(String::ToString("%s_profile", getAssetName()).c_str()); - } - - } + mResolvedTrack->registerObject(String::ToString("%s_profile_track", getAssetName()).c_str()); } - mChangeSignal.trigger(); mLoadedState = Ok; return mLoadedState; } -bool SoundAsset::_setSoundFile(void* object, const char* index, const char* data) -{ - SoundAsset* pData = static_cast(object); - - U32 id = 0; - if (index) - id = dAtoui(index); - - // Update. - pData->mSoundFile[id] = StringTable->insert(data, true); - if (pData->mSoundFile[id] == StringTable->EmptyString()) - pData->mSoundPath[id] = StringTable->EmptyString(); - - // Refresh the asset. - pData->refreshAsset(); - return true; -} - StringTableEntry SoundAsset::getAssetIdByFileName(StringTableEntry fileName) { if (fileName == StringTable->EmptyString()) @@ -478,7 +459,7 @@ StringTableEntry SoundAsset::getAssetIdByFileName(StringTableEntry fileName) SoundAsset* soundAsset = AssetDatabase.acquireAsset(query.mAssetList[i]); if (soundAsset) { - if (soundAsset->getSoundPath() == fileName) + if (soundAsset->getSoundFile() == fileName) soundAssetId = soundAsset->getAssetId(); AssetDatabase.releaseAsset(query.mAssetList[i]); @@ -505,7 +486,7 @@ U32 SoundAsset::getAssetById(StringTableEntry assetId, AssetPtr* sou } } -U32 SoundAsset::getAssetByFileName(StringTableEntry fileName, AssetPtr* soundAsset) +U32 SoundAsset::getAssetByFilename(StringTableEntry fileName, AssetPtr* soundAsset) { AssetQuery query; U32 foundAssetcount = AssetDatabase.findAssetType(&query, "SoundAsset"); @@ -520,7 +501,7 @@ U32 SoundAsset::getAssetByFileName(StringTableEntry fileName, AssetPtr(query.mAssetList[i]); - if (tSoundAsset && tSoundAsset->getSoundPath() == fileName) + if (tSoundAsset && tSoundAsset->getSoundFile() == fileName) { soundAsset->setAssetId(query.mAssetList[i]); AssetDatabase.releaseAsset(query.mAssetList[i]); @@ -534,9 +515,172 @@ U32 SoundAsset::getAssetByFileName(StringTableEntry fileName, AssetPtrregisterObject(String::ToString("%s_profile_description", getAssetName()).c_str()); + } + + mProfileDesc.validate(); + + mResolvedDescription->mPitch = mProfileDesc.mPitch; + mResolvedDescription->mVolume = mProfileDesc.mVolume; + mResolvedDescription->mIs3D = mProfileDesc.mIs3D; + mResolvedDescription->mIsLooping = mProfileDesc.mIsLooping; + mResolvedDescription->mIsStreaming = mProfileDesc.mIsStreaming; + mResolvedDescription->mUseHardware = mProfileDesc.mUseHardware; + mResolvedDescription->mMinDistance = mProfileDesc.mMinDistance; + mResolvedDescription->mMaxDistance = mProfileDesc.mMaxDistance; + mResolvedDescription->mConeInsideAngle = mProfileDesc.mConeInsideAngle; + mResolvedDescription->mConeOutsideAngle = mProfileDesc.mConeOutsideAngle; + mResolvedDescription->mConeOutsideVolume = mProfileDesc.mConeOutsideVolume; + mResolvedDescription->mRolloffFactor = mProfileDesc.mRolloffFactor; + mResolvedDescription->mFadeInTime = mProfileDesc.mFadeInTime; + mResolvedDescription->mFadeOutTime = mProfileDesc.mFadeOutTime; + mResolvedDescription->mFadeLoops = mProfileDesc.mFadeLoops; + mResolvedDescription->mScatterDistance = mProfileDesc.mScatterDistance; + mResolvedDescription->mStreamPacketSize = mProfileDesc.mStreamPacketSize; + mResolvedDescription->mStreamReadAhead = mProfileDesc.mStreamReadAhead; + mResolvedDescription->mPriority = mProfileDesc.mPriority; + mResolvedDescription->mSourceGroup = mProfileDesc.mSourceGroup; + mResolvedDescription->mFadeInEase = mProfileDesc.mFadeInEase; + mResolvedDescription->mSourceGroup = mProfileDesc.mSourceGroup; +} + +SFXProfile* SoundAsset::buildProfile() +{ + SFXProfile* profile = new SFXProfile(mResolvedDescription, mSoundFile[0], mPreload); + mSoundResource[0] = profile->getResource(); + return profile; +} + +//----------------------------------------------------------------------------- +// BUILD PLAYLIST +//----------------------------------------------------------------------------- + +SFXPlayList* SoundAsset::buildPlaylist() +{ + SFXPlayList* pl = new SFXPlayList(); + + pl->mRandomMode = mPlaylist.mRandomMode; + pl->mLoopMode = mPlaylist.mLoopMode; + pl->mNumSlotsToPlay = mPlaylist.mNumSlotsToPlay; + pl->mTrace = mPlaylist.mTrace; + pl->mSlots = mPlaylist.mSlots; + + // Build child tracks for each valid slot + for (U32 i = 0; i < SFXPlayList::SFXPlaylistSettings::NUM_SLOTS; ++i) + { + if (mSoundFile[i] == StringTable->EmptyString()) + continue; + + // Build child SFXProfile + SFXProfile* child = new SFXProfile(mResolvedDescription, mSoundFile[i], mPreload); + mSoundResource[i] = child->getResource(); + pl->mSlots.mTrack[i] = child; + } + + return pl; +} + +void SoundAsset::populateSFXTrack(void) +{ + U32 count = 0; + for (U32 i = 0; i < SFXPlayList::SFXPlaylistSettings::NUM_SLOTS; ++i) + { + if (mSoundFile[i] != StringTable->EmptyString()) + { + if (!Torque::FS::IsFile(mSoundFile[i])) + { + mLoadedState = AssetErrCode::BadFileReference; + return; + } + + ++count; + } + } + + mIsPlaylist = (count > 1); + + buildDescription(); + + if (mResolvedTrack && mResolvedDescription) + { + if (SFX) + SFX->notifyDescriptionChanged(mResolvedDescription); + + return; + } + + mResolvedTrack = NULL; + + // reset loaded state. + mLoadedState = AssetErrCode::NotLoaded; +} + +void SoundAsset::setSoundFile(StringTableEntry pSoundFile, U32 slot) +{ + AssertFatal(pSoundFile != NULL, "Cannot use a NULL sound file."); + + pSoundFile = StringTable->insert(pSoundFile); + + if (pSoundFile == mSoundFile[slot]) + return; + + mSoundFile[slot] = getOwned() ? expandAssetFilePath(pSoundFile) : StringTable->insert(pSoundFile);; + + refreshAsset(); +} + +void SoundAsset::onTamlPreWrite(void) +{ + // Call parent. + Parent::onTamlPreWrite(); + + for (U32 i = 0; i < SFXPlayList::SFXPlaylistSettings::NUM_SLOTS; i++) + { + if (mSoundFile[i] == StringTable->EmptyString()) + break; + + mSoundFile[i] = collapseAssetFilePath(mSoundFile[i]); + } +} + +void SoundAsset::onTamlPostWrite(void) +{ + for (U32 i = 0; i < SFXPlayList::SFXPlaylistSettings::NUM_SLOTS; i++) + { + if (mSoundFile[i] == StringTable->EmptyString()) + break; + + mSoundFile[i] = expandAssetFilePath(mSoundFile[i]); + } +} + +void SoundAsset::onTamlCustomWrite(TamlCustomNodes& customNodes) +{ + // Debug Profiling. + PROFILE_SCOPE(SoundAsset_OnTamlCustomWrite); + + // Call parent. + Parent::onTamlCustomRead(customNodes); +} + +void SoundAsset::onTamlCustomRead(const TamlCustomNodes& customNodes) +{ + // Debug Profiling. + PROFILE_SCOPE(SoundAsset_OnTamlCustomRead); + + // Call parent. + Parent::onTamlCustomRead(customNodes); +} + DefineEngineMethod(SoundAsset, getSoundPath, const char*, (), , "") { - return object->getSoundPath(); + return object->getSoundFile(); } DefineEngineMethod(SoundAsset, playSound, S32, (Point3F position), (Point3F::Zero), @@ -548,12 +692,18 @@ DefineEngineMethod(SoundAsset, playSound, S32, (Point3F position), (Point3F::Zer MatrixF transform; transform.setPosition(position); SFXSource* source; - if (position == Point3F::Zero || !object->is3D()) + if (position == Point3F::Zero && !object->is3D()) + { source = SFX->playOnce(object->getSFXTrack()); + } else + { + if (position == Point3F::Zero) + transform = SFX->getListener().getTransform(); source = SFX->playOnce(object->getSFXTrack(), &transform, NULL, -1); + } - if(source) + if (source) return source->getId(); else return 0; @@ -584,7 +734,7 @@ void GuiInspectorTypeSoundAssetPtr::consoleInit() ConsoleBaseType::getType(TypeSoundAssetPtr)->setInspectorFieldType("GuiInspectorTypeSoundAssetPtr"); } -GuiControl * GuiInspectorTypeSoundAssetPtr::constructEditControl() +GuiControl* GuiInspectorTypeSoundAssetPtr::constructEditControl() { // Create base filename edit controls GuiControl* retCtrl = Parent::constructEditControl(); diff --git a/Engine/source/T3D/assets/SoundAsset.h b/Engine/source/T3D/assets/SoundAsset.h index d005ec0c1..1076f00e4 100644 --- a/Engine/source/T3D/assets/SoundAsset.h +++ b/Engine/source/T3D/assets/SoundAsset.h @@ -87,21 +87,12 @@ class SoundAsset : public AssetBase typedef AssetPtr ConcreteAssetPtr; protected: - StringTableEntry mSoundFile[SFXPlayList::SFXPlaylistSettings::NUM_SLOTS]; - StringTableEntry mSoundPath[SFXPlayList::SFXPlaylistSettings::NUM_SLOTS]; - SimObjectPtr mSFXProfile[SFXPlayList::SFXPlaylistSettings::NUM_SLOTS]; - SFXDescription mProfileDesc; - SFXPlayList mPlaylist; - // subtitles - StringTableEntry mSubtitleString; - bool mPreload; - bool mIsPlaylist; //SFXPlayList::SlotData mSlots; /*These will be needed in the refactor! Resource mSoundResource; - + // SFXDesctriptions, some off these will be removed F32 mPitchAdjust; @@ -121,9 +112,6 @@ protected: F32 mPriority; */ - typedef Signal SoundAssetChanged; - SoundAssetChanged mChangeSignal; - public: enum SoundAssetErrCode { @@ -142,41 +130,79 @@ public: if (errCode > SoundAssetErrCode::Extended) return "undefined error"; return mErrCodeStrings[errCode - Parent::Extended]; }; + +private: + StringTableEntry mSoundFile[SFXPlayList::SFXPlaylistSettings::NUM_SLOTS]; + Resource mSoundResource[SFXPlayList::SFXPlaylistSettings::NUM_SLOTS]; + + SFXDescription mProfileDesc; + + SFXPlayList mPlaylist; + // subtitles + StringTableEntry mSubtitleString; + bool mPreload; + bool mIsPlaylist; + SFXTrack* mResolvedTrack; + SFXDescription* mResolvedDescription; + +public: SoundAsset(); virtual ~SoundAsset(); /// Engine. static void initPersistFields(); + void onRemove() override; + void inspectPostApply() override; void copyTo(SimObject* object) override; //SFXResource* getSound() { return mSoundResource; } - Resource getSoundResource(const U32 slotId = 0) { load(); return mSFXProfile[slotId]->getResource(); } + Resource getSoundResource(const U32 slotId = 0) { load(); return mSoundResource[slotId]; } /// Declare Console Object. DECLARE_CONOBJECT(SoundAsset); - static bool _setSoundFile(void* object, const char* index, const char* data); + // asset Base load U32 load() override; - inline StringTableEntry getSoundPath(const U32 slotId = 0) const { return mSoundPath[slotId]; }; - SFXProfile* getSfxProfile(const U32 slotId = 0) { return mSFXProfile[slotId]; } - SFXPlayList* getSfxPlaylist() { return &mPlaylist; } - SFXTrack* getSFXTrack() { load(); return mIsPlaylist ? dynamic_cast(&mPlaylist) : dynamic_cast(mSFXProfile[0].getPointer()); } - SFXDescription* getSfxDescription() { return &mProfileDesc; } - bool isPlaylist(){ return mIsPlaylist; } + + void setSoundFile(StringTableEntry pSoundFile, U32 slot = 0); + inline StringTableEntry getSoundFile(U32 slot = 0) { return mSoundFile[slot]; } + inline StringTableEntry getRelativeSoundFile(U32 slot = 0) { return collapseAssetFilePath(mSoundFile[slot]); } + + SFXTrack* getSFXTrack() { load(); return mResolvedTrack; } + SFXDescription* getSfxDescription() { return mResolvedDescription ? mResolvedDescription : &mProfileDesc; } + bool isPlaylist() { return mIsPlaylist; } bool isLoop() { return mProfileDesc.mIsLooping; } bool is3D() { return mProfileDesc.mIs3D; } static StringTableEntry getAssetIdByFileName(StringTableEntry fileName); static U32 getAssetById(StringTableEntry assetId, AssetPtr* materialAsset); - static U32 getAssetByFileName(StringTableEntry fileName, AssetPtr* matAsset); + static U32 getAssetByFilename(StringTableEntry fileName, AssetPtr* matAsset); + + void buildDescription(); + SFXProfile* buildProfile(); + SFXPlayList* buildPlaylist(); + + void populateSFXTrack(void); protected: - void initializeAsset(void) override; - void _onResourceChanged(const Torque::Path & path); - void onAssetRefresh(void) override; + // Asset Base callback + void initializeAsset(void) override; + void _onResourceChanged(const Torque::Path& path); + void onAssetRefresh(void) override; + + /// Taml callbacks. + void onTamlPreWrite(void) override; + void onTamlPostWrite(void) override; + void onTamlCustomWrite(TamlCustomNodes& customNodes) override; + void onTamlCustomRead(const TamlCustomNodes& customNodes) override; + +protected: + static bool _setSoundFile(void* obj, const char* index, const char* data) { U32 idx = 0; if (index) idx = dAtoi(index); static_cast(obj)->setSoundFile(data, idx); return false; } + }; +DECLARE_STRUCT(AssetPtr) DefineConsoleType(TypeSoundAssetPtr, SoundAsset) DefineConsoleType(TypeSoundAssetId, String) @@ -272,8 +298,8 @@ public: \ \ const StringTableEntry get##name() const\ {\ - if (m##name##Asset && (m##name##Asset->getSoundPath() != StringTable->EmptyString()))\ - return m##name##Asset->getSoundPath();\ + if (m##name##Asset && (m##name##Asset->getSoundFile() != StringTable->EmptyString()))\ + return m##name##Asset->getSoundFile();\ else if (m##name##AssetId != StringTable->EmptyString())\ return m##name##AssetId;\ else if (m##name##Name != StringTable->EmptyString())\ @@ -467,8 +493,8 @@ public: \ \ const StringTableEntry get##name(const U32& index) const\ {\ - if (m##name##Asset[index] && (m##name##Asset[index]->getSoundPath() != StringTable->EmptyString()))\ - return m##name##Asset[index]->getSoundPath();\ + if (m##name##Asset[index] && (m##name##Asset[index]->getSoundFile() != StringTable->EmptyString()))\ + return m##name##Asset[index]->getSoundFile();\ else if (m##name##AssetId[index] != StringTable->EmptyString())\ return m##name##AssetId[index];\ else if (m##name##Name[index] != StringTable->EmptyString())\ diff --git a/Engine/source/T3D/assets/assetImporter.cpp b/Engine/source/T3D/assets/assetImporter.cpp index ff9213675..6c22ce7d2 100644 --- a/Engine/source/T3D/assets/assetImporter.cpp +++ b/Engine/source/T3D/assets/assetImporter.cpp @@ -3309,30 +3309,19 @@ Torque::Path AssetImporter::importSoundAsset(AssetImportObject* assetItem) StringTableEntry assetName = StringTable->insert(assetItem->assetName.c_str()); - String soundFileName = assetItem->filePath.getFileName() + "." + assetItem->filePath.getExtension(); - String assetPath = targetPath + "/" + soundFileName; + String soundFileName = assetItem->filePath.getFullFileName(); + String assetPath = "@" + soundFileName; String tamlPath = targetPath + "/" + assetName + ".asset.taml"; String originalPath = assetItem->filePath.getFullPath().c_str(); - char qualifiedFromFile[2048]; - char qualifiedToFile[2048]; - -#ifndef TORQUE_SECURE_VFS - Platform::makeFullPathName(originalPath.c_str(), qualifiedFromFile, sizeof(qualifiedFromFile)); - Platform::makeFullPathName(assetPath.c_str(), qualifiedToFile, sizeof(qualifiedToFile)); -#else - dStrcpy(qualifiedFromFile, originalPath.c_str(), sizeof(qualifiedFromFile)); - dStrcpy(qualifiedToFile, assetPath.c_str(), sizeof(qualifiedToFile)); -#endif - newAsset->setAssetName(assetName); - newAsset->_setSoundFile(newAsset, "0", soundFileName.c_str()); + newAsset->setSoundFile(assetPath.c_str()); //If it's not a re-import, check that the file isn't being in-place imported. If it isn't, store off the original //file path for reimporting support later - if (!isReimport && String::compare(qualifiedFromFile, qualifiedToFile) && Torque::FS::IsFile(qualifiedFromFile)) + if (!isReimport) { - newAsset->setDataField(StringTable->insert("originalFilePath"), NULL, qualifiedFromFile); + newAsset->setDataField(StringTable->insert("originalFilePath"), nullptr, originalPath.c_str()); } Taml tamlWriter; @@ -3345,18 +3334,6 @@ Torque::Path AssetImporter::importSoundAsset(AssetImportObject* assetItem) return ""; } - if (!isReimport) - { - bool isInPlace = !String::compare(qualifiedFromFile, qualifiedToFile); - - if (!isInPlace && !Torque::FS::CopyFile(qualifiedFromFile, qualifiedToFile, !isReimport)) - { - dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to copy file %s", assetItem->filePath.getFullPath().c_str()); - activityLog.push_back(importLogBuffer); - return ""; - } - } - return tamlPath; } diff --git a/Engine/source/T3D/levelInfo.cpp b/Engine/source/T3D/levelInfo.cpp index 884fd7d17..41f4328e4 100644 --- a/Engine/source/T3D/levelInfo.cpp +++ b/Engine/source/T3D/levelInfo.cpp @@ -217,7 +217,7 @@ U32 LevelInfo::packUpdate(NetConnection *conn, U32 mask, BitStream *stream) mathWrite( *stream, mAmbientLightBlendCurve ); sfxWrite( stream, mSoundAmbience ); - stream->writeInt( mSoundDistanceModel, 1 ); + stream->writeInt( mSoundDistanceModel, 4 ); PACK_ASSET_REFACTOR(conn, AccuTexture); @@ -251,7 +251,7 @@ void LevelInfo::unpackUpdate(NetConnection *conn, BitStream *stream) String errorStr; if( !sfxReadAndResolve( stream, &mSoundAmbience, errorStr ) ) Con::errorf( "%s", errorStr.c_str() ); - mSoundDistanceModel = ( SFXDistanceModel ) stream->readInt( 1 ); + mSoundDistanceModel = ( SFXDistanceModel ) stream->readInt( 4 ); if( isProperlyAdded() ) { diff --git a/Engine/source/T3D/pathCamera.cpp b/Engine/source/T3D/pathCamera.cpp index bb14db972..eede59c86 100644 --- a/Engine/source/T3D/pathCamera.cpp +++ b/Engine/source/T3D/pathCamera.cpp @@ -275,7 +275,9 @@ void PathCamera::advancePosition(S32 ms) } // Script callbacks - if (int(mPosition) != int(delta.timeVec)) + if ((mState == Backward) && (int(mPosition) == 0) && (mSpline.advanceTime(delta.timeVec - mNodeBase, -ms) < TickSec)) + onNode(0); + else if (int(mPosition) > 0 && int(mPosition) != int(delta.timeVec)) onNode(int(mPosition)); // Set frame interpolation diff --git a/Engine/source/T3D/pathShape.cpp b/Engine/source/T3D/pathShape.cpp index 9370c09e5..8a29074d1 100644 --- a/Engine/source/T3D/pathShape.cpp +++ b/Engine/source/T3D/pathShape.cpp @@ -27,6 +27,11 @@ IMPLEMENT_CO_DATABLOCK_V1(PathShapeData); +PathShapeData::PathShapeData() +{ + mUseEase = false; +} + void PathShapeData::consoleInit() { } @@ -143,11 +148,6 @@ bool PathShape::onNewDataBlock(GameBaseData* dptr, bool reload) return true; } -PathShapeData::PathShapeData() -{ - -} - //---------------------------------------------------------------------------- void PathShape::initPersistFields() @@ -229,7 +229,9 @@ void PathShape::advancePosition(S32 ms) } // Script callbacks - if (int(mPosition) != int(delta.timeVec)) + if ((mState == Backward) && (int(mPosition) == 0) && (mSpline.advanceTime(delta.timeVec - mNodeBase, -ms) < TickSec)) + onNode(0); + else if (int(mPosition)>0 && int(mPosition) != int(delta.timeVec)) onNode(int(mPosition)); // Set frame interpolation diff --git a/Engine/source/T3D/player.cpp b/Engine/source/T3D/player.cpp index c7aef08b3..1b9af0ea6 100644 --- a/Engine/source/T3D/player.cpp +++ b/Engine/source/T3D/player.cpp @@ -1015,19 +1015,19 @@ void PlayerData::initPersistFields() "Used when computing the damage location.\n" "@see Player::getDamageLocation" ); addFieldV( "boxTorsoLeftPercentage", TypeRangedF32, Offset(boxTorsoLeftPercentage, PlayerData), &CommonValidators::NormalizedFloat, - "@brief Percentage of the player's bounding box width that represents the left side of the torso.\n\n" + "@brief Percentage of the player's bounding box width from center that represents the left side of the torso.\n\n" "Used when computing the damage location.\n" "@see Player::getDamageLocation" ); addFieldV( "boxTorsoRightPercentage", TypeRangedF32, Offset(boxTorsoRightPercentage, PlayerData), &CommonValidators::NormalizedFloat, - "@brief Percentage of the player's bounding box width that represents the right side of the torso.\n\n" + "@brief Percentage of the player's bounding box width from center that represents the right side of the torso.\n\n" "Used when computing the damage location.\n" "@see Player::getDamageLocation" ); addFieldV( "boxTorsoBackPercentage", TypeRangedF32, Offset(boxTorsoBackPercentage, PlayerData), &CommonValidators::NormalizedFloat, - "@brief Percentage of the player's bounding box depth that represents the back side of the torso.\n\n" + "@brief Percentage of the player's bounding box depth from center that represents the back side of the torso.\n\n" "Used when computing the damage location.\n" "@see Player::getDamageLocation" ); addFieldV( "boxTorsoFrontPercentage", TypeRangedF32, Offset(boxTorsoFrontPercentage, PlayerData), &CommonValidators::NormalizedFloat, - "@brief Percentage of the player's bounding box depth that represents the front side of the torso.\n\n" + "@brief Percentage of the player's bounding box depth from center that represents the front side of the torso.\n\n" "Used when computing the damage location.\n" "@see Player::getDamageLocation" ); @@ -2395,10 +2395,10 @@ void Player::getDamageLocation(const Point3F& in_rPos, const char *&out_rpVert, { F32 xWidth = boxSize.x; - //boxTorsoBackPercentage and boxTorsoLeftPercentage should both be negative floats - F32 backPoint = yLength * mDataBlock->boxTorsoBackPercentage; + //boxTorsoBackPercentage and boxTorsoLeftPercentage need to be flipped negative + F32 backPoint = (yLength * mDataBlock->boxTorsoBackPercentage) * -1.0f; F32 frontPoint = yLength * mDataBlock->boxTorsoFrontPercentage; - F32 leftPoint = xWidth * mDataBlock->boxTorsoLeftPercentage; + F32 leftPoint = (xWidth * mDataBlock->boxTorsoLeftPercentage) * -1.0f; F32 rightPoint = xWidth * mDataBlock->boxTorsoRightPercentage; S32 index = 0; //Middle hits are cases 0-2 diff --git a/Engine/source/T3D/sfx/sfxEmitter.cpp b/Engine/source/T3D/sfx/sfxEmitter.cpp index 16d8394d9..0cd794ba1 100644 --- a/Engine/source/T3D/sfx/sfxEmitter.cpp +++ b/Engine/source/T3D/sfx/sfxEmitter.cpp @@ -820,7 +820,7 @@ void SFXEmitter::_update() // is toggled on a local profile sound. It makes the // editor feel responsive and that things are working. if( gEditingMission && - (SoundAsset::getAssetErrCode(mSoundAsset) || !mSoundAsset->getSfxProfile()) && + (SoundAsset::getAssetErrCode(mSoundAsset) || !mSoundAsset->getSFXTrack()) && mPlayOnAdd && mDirty.test( IsLooping ) ) prevState = SFXStatusPlaying; diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index c936660ae..a87e1280a 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -231,6 +231,12 @@ bool GuiCanvas::onAdd() { // ensure that we have a cursor setCursor(dynamic_cast(Sim::findObject("DefaultCursor"))); + + SFXSystem::enumerateProviders(); + SFXProvider* p = SFXSystem::getBestProviderChoice(); + + if (p) + SFX->createDevice(p); // Enumerate things for GFX before we have an active device. GFXInit::enumerateAdapters(); diff --git a/Engine/source/sfx/dsound/dsFunctions.h b/Engine/source/sfx/dsound/dsFunctions.h deleted file mode 100644 index ad7a3e53b..000000000 --- a/Engine/source/sfx/dsound/dsFunctions.h +++ /dev/null @@ -1,27 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -// The various functions we need to grab from DSound.dll -DS_FUNCTION( DirectSoundEnumerateA, HRESULT, (LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext) ) -DS_FUNCTION( DirectSoundEnumerateW, HRESULT, (LPDSENUMCALLBACKW pDSEnumCallback, LPVOID pContext) ) -DS_FUNCTION( DirectSoundCreate8, HRESULT, (LPCGUID pcGuidDevice, LPDIRECTSOUND8 *ppDS8, LPUNKNOWN pUnkOuter) ) - diff --git a/Engine/source/sfx/dsound/sfxDSBuffer.cpp b/Engine/source/sfx/dsound/sfxDSBuffer.cpp deleted file mode 100644 index d7d7bb9d9..000000000 --- a/Engine/source/sfx/dsound/sfxDSBuffer.cpp +++ /dev/null @@ -1,277 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "sfx/dsound/sfxDSBuffer.h" -#include "sfx/sfxStream.h" -#include "sfx/sfxDescription.h" -#include "sfx/sfxInternal.h" -#include "platform/async/asyncUpdate.h" -#include "core/util/safeRelease.h" -#include "core/util/safeCast.h" - - -SFXDSBuffer* SFXDSBuffer::create( IDirectSound8 *dsound, - const ThreadSafeRef< SFXStream >& stream, - SFXDescription* description, - bool useHardware ) -{ - AssertFatal( dsound, "SFXDSBuffer::create() - Got null dsound!" ); - AssertFatal( stream, "SFXDSBuffer::create() - Got a null stream!" ); - AssertFatal( description, "SFXDSBuffer::create() - Got a null description" ); - - SFXDSBuffer* buffer = new SFXDSBuffer( dsound, - stream, - description, - useHardware ); - - - if( !buffer->_createBuffer( &buffer->mBuffer ) ) - SAFE_DELETE( buffer ); - - return buffer; -} - -SFXDSBuffer::SFXDSBuffer( IDirectSound8* dsound, - const ThreadSafeRef< SFXStream >& stream, - SFXDescription* description, - bool useHardware ) - : Parent( stream, description ), - mDSound( dsound ), - mIs3d( description->mIs3D ), - mUseHardware( useHardware ), - mBuffer( NULL ), - mDuplicate( false ) -{ - AssertFatal( mDSound, "SFXDSBuffer::SFXDSBuffer() - Got null dsound!" ); - - mDSound->AddRef(); -} - -SFXDSBuffer::~SFXDSBuffer() -{ - SAFE_RELEASE( mBuffer ); - SAFE_RELEASE( mDSound ); -} - -bool SFXDSBuffer::_createBuffer( IDirectSoundBuffer8 **buffer8 ) -{ - AssertFatal( mAsyncState != NULL, - "SFXDSBuffer::_createBuffer() - Can't create buffer when not connected to stream!" ); - - const SFXFormat& format = getFormat(); - - // Set up WAV format structure. - WAVEFORMATEX wfx; - dMemset( &wfx, 0, sizeof( WAVEFORMATEX ) ); - wfx.wFormatTag = WAVE_FORMAT_PCM; - wfx.nChannels = format.getChannels(); - wfx.nSamplesPerSec = format.getSamplesPerSecond(); - wfx.wBitsPerSample = format.getBitsPerChannel(); - wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8; - wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; - - // Set up DSBUFFERDESC structure. - DSBUFFERDESC dsbdesc; - dMemset( &dsbdesc, 0, sizeof( DSBUFFERDESC ) ); - dsbdesc.dwSize = sizeof( DSBUFFERDESC ); - dsbdesc.dwFlags = - ( mIs3d ? DSBCAPS_CTRL3D | DSBCAPS_MUTE3DATMAXDISTANCE : DSBCAPS_CTRLPAN ) | - ( isStreaming() ? DSBCAPS_CTRLPOSITIONNOTIFY : 0 ) | - DSBCAPS_CTRLFREQUENCY | - DSBCAPS_CTRLVOLUME | - DSBCAPS_GETCURRENTPOSITION2 | - DSBCAPS_GLOBALFOCUS | - DSBCAPS_STATIC | - ( mUseHardware ? DSBCAPS_LOCHARDWARE : DSBCAPS_LOCSOFTWARE ); - dsbdesc.dwBufferBytes = mBufferSize; - if ( mIs3d ) - dsbdesc.guid3DAlgorithm = DS3DALG_HRTF_FULL; - dsbdesc.lpwfxFormat = &wfx; - - // Create the buffer. - IDirectSoundBuffer *buffer = NULL; - HRESULT hr = mDSound->CreateSoundBuffer( &dsbdesc, &buffer, NULL ); - if ( FAILED( hr ) || !buffer ) - return false; - - // Grab the version 8 interface. - IDirectSoundBuffer8* buffer8Ptr; - hr = buffer->QueryInterface( IID_IDirectSoundBuffer8, ( LPVOID* ) &buffer8Ptr ); - - // Release the original interface. - buffer->Release(); - - // If we failed to get the 8 interface... exit. - if ( FAILED( hr ) || !buffer8Ptr ) - return false; - - // Set up notification positions, if this is a streaming buffer. - - if( isStreaming() ) - { - using namespace SFXInternal; - - const U32 maxQueuedPackets = SFXAsyncQueue::DEFAULT_STREAM_QUEUE_LENGTH; - const U32 packetSize = mAsyncState->mStream->getPacketSize(); - - LPDIRECTSOUNDNOTIFY8 lpDsNotify; - if( FAILED( hr = buffer8Ptr->QueryInterface( IID_IDirectSoundNotify8, ( LPVOID* ) &lpDsNotify ) ) ) - { - SAFE_RELEASE( buffer8Ptr ); - return false; - } - - const U32 numNotifies = maxQueuedPackets + 1; // Add one for end-of-stream notification pos. - DSBPOSITIONNOTIFY* dsbNotifyPos = - ( DSBPOSITIONNOTIFY* ) _alloca( numNotifies * sizeof( DSBPOSITIONNOTIFY ) ); - - // Events seem to be triggered way too early by DS causing the playback queues to - // reject updates, so we nudge the update markers "somewhat" to the right here. - // This value here is based on experimentation. No harm should result if we don't - // hit it other than updates happening in sub-optimal timing. - enum { OFFSET_DELTA = 5000 }; - - U32 offset = ( packetSize + OFFSET_DELTA ) % mBufferSize; - HANDLE updateEvent = ( HANDLE ) UPDATE_THREAD()->getUpdateEvent(); - for( U32 i = 0; i < maxQueuedPackets; ++ i, offset = ( offset + packetSize ) % mBufferSize ) - { - dsbNotifyPos[ i ].dwOffset = offset; - dsbNotifyPos[ i ].hEventNotify = updateEvent; - } - - // A end-of-stream notification position. - - //FIXME: this position will start to be wrong when doing stream seeks - - dsbNotifyPos[ numNotifies - 1 ].dwOffset = ( format.getDataLength( getDuration() ) + OFFSET_DELTA ) % mBufferSize; - dsbNotifyPos[ numNotifies - 1 ].hEventNotify = updateEvent; - - // Install the notifications. - - lpDsNotify->SetNotificationPositions( numNotifies, dsbNotifyPos ); - SAFE_RELEASE( lpDsNotify ); - - // Don't need to notify on stop as when playback is stopped, - // the packet buffers will just fill up and stop updating - // when saturated. - } - - *buffer8 = buffer8Ptr; - return true; -} - -bool SFXDSBuffer::_copyData( U32 offset, - const U8 *data, - U32 length ) -{ - AssertFatal( mBuffer, "SFXDSBuffer::_copyData() - no buffer" ); - - // Fill the buffer with the resource data. - VOID* lpvWrite; - DWORD dwLength; - VOID* lpvWrite2; - DWORD dwLength2; - HRESULT hr = mBuffer->Lock( - offset, // Offset at which to start lock. - length, // Size of lock. - &lpvWrite, // Gets address of first part of lock. - &dwLength, // Gets size of first part of lock. - &lpvWrite2, // Address of wraparound not needed. - &dwLength2, // Size of wraparound not needed. - 0 ); - if ( FAILED( hr ) ) - return false; - - // Copy the first part. - dMemcpy( lpvWrite, data, dwLength ); - - // Do we have a wrap? - if ( lpvWrite2 ) - dMemcpy( lpvWrite2, data + dwLength, dwLength2 ); - - // And finally, unlock. - hr = mBuffer->Unlock( - lpvWrite, // Address of lock start. - dwLength, // Size of lock. - lpvWrite2, // No wraparound portion. - dwLength2 ); // No wraparound size. - - // Return success code. - return SUCCEEDED(hr); -} - -void SFXDSBuffer::_flush() -{ - AssertFatal( isStreaming(), "SFXDSBuffer::_flush() - not a streaming buffer" ); - AssertFatal( SFXInternal::isSFXThread(), "SFXDSBuffer::_flush() - not on SFX thread" ); - - Parent::_flush(); - mBuffer->SetCurrentPosition( 0 ); -} - -bool SFXDSBuffer::_duplicateBuffer( IDirectSoundBuffer8 **buffer8 ) -{ - AssertFatal( mBuffer, "SFXDSBuffer::_duplicateBuffer() - Duplicate buffer is null!" ); - - // If this is the first duplicate then - // give the caller our original buffer. - if ( !mDuplicate ) - { - mDuplicate = true; - - *buffer8 = mBuffer; - (*buffer8)->AddRef(); - - return true; - } - - IDirectSoundBuffer *buffer1 = NULL; - HRESULT hr = mDSound->DuplicateSoundBuffer( mBuffer, &buffer1 ); - if ( FAILED( hr ) || !buffer1 ) - return false; - - // Grab the version 8 interface. - hr = buffer1->QueryInterface( IID_IDirectSoundBuffer8, (LPVOID*)buffer8 ); - - // Release the original interface. - buffer1->Release(); - - return SUCCEEDED( hr ) && (*buffer8); -} - -bool SFXDSBuffer::createVoice( IDirectSoundBuffer8 **buffer8 ) -{ - return ( mBuffer && _duplicateBuffer( buffer8 ) && *buffer8 ); -} - -void SFXDSBuffer::releaseVoice( IDirectSoundBuffer8 **buffer ) -{ - AssertFatal( *buffer, "SFXDSBuffer::releaseVoice() - Got null buffer!" ); - - if ( *buffer == mBuffer ) - { - mDuplicate = false; - (*buffer)->Stop(); - } - - SAFE_RELEASE( (*buffer) ); -} diff --git a/Engine/source/sfx/dsound/sfxDSBuffer.h b/Engine/source/sfx/dsound/sfxDSBuffer.h deleted file mode 100644 index 94549df86..000000000 --- a/Engine/source/sfx/dsound/sfxDSBuffer.h +++ /dev/null @@ -1,101 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _SFXDSBUFFER_H_ -#define _SFXDSBUFFER_H_ - -#include - -#ifndef _SFXINTERNAL_H_ -# include "sfx/sfxInternal.h" -#endif - - -/// DirectSound SFXBuffer implementation. -/// -/// Note that the actual sound buffer held by the buffer may -/// get duplicated around for individual voices. This is kind -/// of ugly as the resulting buffers aren't tied to a SFXDSBuffer -/// anymore. -class SFXDSBuffer : public SFXInternal::SFXWrapAroundBuffer -{ - typedef SFXInternal::SFXWrapAroundBuffer Parent; - - friend class SFXDSDevice; - friend class SFXDSVoice; - - protected: - - /// - bool mIs3d; - - /// - bool mUseHardware; - - IDirectSound8 *mDSound; - - /// The buffer used when duplication is allowed. - IDirectSoundBuffer8 *mBuffer; - - /// We set this to true when the original buffer has - /// been handed out and duplicates need to be made. - bool mDuplicate; - - /// - SFXDSBuffer( IDirectSound8 *dsound, - const ThreadSafeRef< SFXStream >& stream, - SFXDescription* description, - bool useHardware ); - - virtual ~SFXDSBuffer(); - - /// Set up a DirectSound buffer. - /// @note This method will not fill the buffer with data. - /// @note If this is a streaming buffer, the resulting buffer - /// will have its notification positions set up and already - /// be registered with SFXDSStreamThread. - bool _createBuffer( IDirectSoundBuffer8 **buffer8 ); - - /// - bool _duplicateBuffer( IDirectSoundBuffer8 **buffer8 ); - - // SFXWrapAroundBuffer. - virtual bool _copyData( U32 offset, const U8* data, U32 length ); - virtual void _flush(); - -public: - - /// - static SFXDSBuffer* create( IDirectSound8* dsound, - const ThreadSafeRef< SFXStream >& stream, - SFXDescription* description, - bool useHardware ); - - // - bool createVoice( IDirectSoundBuffer8 **buffer ); - - // - void releaseVoice( IDirectSoundBuffer8 **buffer ); - -}; - -#endif // _SFXDSBUFFER_H_ \ No newline at end of file diff --git a/Engine/source/sfx/dsound/sfxDSDevice.cpp b/Engine/source/sfx/dsound/sfxDSDevice.cpp deleted file mode 100644 index b83ed120c..000000000 --- a/Engine/source/sfx/dsound/sfxDSDevice.cpp +++ /dev/null @@ -1,229 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "sfx/dsound/sfxDSDevice.h" -#include "sfx/dsound/sfxDSBuffer.h" -#include "sfx/dsound/sfxDSVoice.h" -#include "platformWin32/platformWin32.h" -#include "core/util/safeRelease.h" -#include "platform/async/asyncUpdate.h" -#include "console/console.h" - - -SFXDSDevice::SFXDSDevice( SFXProvider* provider, - DSoundFNTable *dsFnTbl, - GUID* guid, - String name, - bool useHardware, - S32 maxBuffers ) - : SFXDevice( name, provider, useHardware, maxBuffers ), - mDSound( NULL ), - mPrimaryBuffer( NULL ), - mListener( NULL ), - mDSoundTbl( dsFnTbl ), - mGUID( guid ) -{ -} - -bool SFXDSDevice::_init() -{ - HRESULT hr = mDSoundTbl->DirectSoundCreate8( mGUID, &mDSound, NULL ); - if ( FAILED( hr ) || !mDSound ) - { - Con::errorf( "SFXDSDevice::SFXDSDevice() - DirectSoundCreate8 failed" ); - return false; - } - - hr = mDSound->SetCooperativeLevel( getWin32WindowHandle(), DSSCL_PRIORITY ); - if ( FAILED( hr ) ) - { - Con::errorf( "SFXDSDevice::SFXDSDevice() - SetCooperativeLevel failed" ); - return false; - } - - // Get the primary buffer. - DSBUFFERDESC dsbd; - dMemset( &dsbd, 0, sizeof( DSBUFFERDESC ) ); - dsbd.dwSize = sizeof( DSBUFFERDESC ); - dsbd.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; - hr = mDSound->CreateSoundBuffer( &dsbd, &mPrimaryBuffer, NULL ); - if ( FAILED( hr ) ) - { - Con::errorf( "SFXDSDevice::SFXDSDevice - Creating primary sound buffer failed" ); - return false; - } - - // Set the format and bitrate on the primary buffer. - S32 frequency = Con::getIntVariable( "$pref::SFX::frequency", 44100 ); - S32 bitrate = Con::getIntVariable( "$pref::SFX::bitrate", 32 ); - - WAVEFORMATEX wfx; - dMemset( &wfx, 0, sizeof( WAVEFORMATEX ) ); - wfx.wFormatTag = WAVE_FORMAT_PCM; - wfx.nChannels = 2; - wfx.nSamplesPerSec = frequency; - wfx.wBitsPerSample = bitrate; - wfx.nBlockAlign = ( wfx.nChannels * wfx.wBitsPerSample ) / 8; - wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; - hr = mPrimaryBuffer->SetFormat( &wfx ); - if( FAILED( hr ) ) - { - Con::errorf( "SFXDSDevice::SFXDSDevice() - Setting format of primary buffer failed" ); - return false; - } - - // Grab the 3d listener. - hr = mPrimaryBuffer->QueryInterface( IID_IDirectSound3DListener8, (LPVOID*)&mListener ); - if ( FAILED( hr ) ) - { - Con::errorf( "SFXDSDevice::SFXDevice() - Querying the listener interface failed!" ); - mListener = NULL; - } - - mCaps.dwSize = sizeof( DSCAPS ); - mDSound->GetCaps( &mCaps ); - - // If the device reports no hardware buffers then - // we have no choice but to disable hardware. - if ( mCaps.dwMaxHw3DAllBuffers == 0 ) - mUseHardware = false; - - // If mMaxBuffers is negative then use the caps - // to decide on a good maximum value... or set 8. - if ( mMaxBuffers < 0 ) - mMaxBuffers = getMax( mCaps.dwMaxHw3DAllBuffers, 8 ); - - // Start the stream thread. - - if( !Con::getBoolVariable( "$_forceAllMainThread" ) ) - { - SFXInternal::gUpdateThread = - new AsyncUpdateThread( "DirectSound Update Thread", SFXInternal::gBufferUpdateList ); - SFXInternal::gUpdateThread->start(); - } - - return true; -} - -SFXDSDevice::~SFXDSDevice() -{ - // And release our resources. - SAFE_RELEASE( mListener ); - SAFE_RELEASE( mPrimaryBuffer ); - SAFE_RELEASE( mDSound ); -} - -SFXBuffer* SFXDSDevice::createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description ) -{ - AssertFatal( stream, "SFXDSDevice::createBuffer() - Got null stream!" ); - AssertFatal( description, "SFXDSDevice::createBuffer() - Got null description!" ); - - SFXDSBuffer* buffer = SFXDSBuffer::create( mDSound, - stream, - description, - mUseHardware ); - - if( buffer ) - _addBuffer( buffer ); - - return buffer; -} - -SFXVoice* SFXDSDevice::createVoice( bool is3D, SFXBuffer *buffer ) -{ - // Don't bother going any further if we've - // exceeded the maximum voices. - if ( mVoices.size() >= mMaxBuffers ) - return NULL; - - AssertFatal( buffer, "SFXDSDevice::createVoice() - Got null buffer!" ); - - SFXDSBuffer* dsBuffer = dynamic_cast( buffer ); - AssertFatal( dsBuffer, "SFXDSDevice::createVoice() - Got bad buffer!" ); - - SFXDSVoice* voice = SFXDSVoice::create( this, dsBuffer ); - if ( !voice ) - return NULL; - - _addVoice( voice ); - return voice; -} - -void SFXDSDevice::_commitDeferred() -{ - if( mListener ) - mListener->CommitDeferredSettings(); -} - -void SFXDSDevice::update() -{ - Parent::update(); - - // Apply the deferred settings that changed between updates. - mListener->CommitDeferredSettings(); -} - -void SFXDSDevice::setListener( U32 index, const SFXListenerProperties& listener ) -{ - // Get the transform from the listener. - const MatrixF& transform = listener.getTransform(); - Point3F pos, dir, up; - transform.getColumn( 3, &pos ); - transform.getColumn( 1, &dir ); - transform.getColumn( 2, &up ); - - // And the velocity... - const VectorF& velocity = listener.getVelocity(); - - // Finally, set it all to DSound! - mListener->SetPosition( pos.x, pos.z, pos.y, DS3D_DEFERRED ); - mListener->SetOrientation( dir.x, dir.z, dir.y, up.x, up.z, up.y, DS3D_DEFERRED ); - mListener->SetVelocity( velocity.x, velocity.z, velocity.y, DS3D_DEFERRED ); -} - -void SFXDSDevice::setDistanceModel( SFXDistanceModel model ) -{ - switch( model ) - { - case SFXDistanceModelLinear: - Con::errorf( "SFXDSDevice::setDistanceModel - 'linear' distance attenuation not supported by DirectSound" ); - break; - - case SFXDistanceModelLogarithmic: - break; // Nothing to do. - - default: - AssertWarn( false, "SFXDSDevice::setDistanceModel() - model not implemented" ); - } -} - -void SFXDSDevice::setDopplerFactor( F32 factor ) -{ - if( mListener ) - mListener->SetDopplerFactor( factor, DS3D_DEFERRED ); // Committed in update. -} - -void SFXDSDevice::setRolloffFactor( F32 factor ) -{ - if( mListener ) - mListener->SetRolloffFactor( factor, DS3D_DEFERRED ); // Committed in update. -} diff --git a/Engine/source/sfx/dsound/sfxDSDevice.h b/Engine/source/sfx/dsound/sfxDSDevice.h deleted file mode 100644 index 540294c85..000000000 --- a/Engine/source/sfx/dsound/sfxDSDevice.h +++ /dev/null @@ -1,142 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _SFXDSDEVICE_H_ -#define _SFXDSDEVICE_H_ - -#ifndef _STRINGFUNCTIONS_H_ -# include "core/strings/stringFunctions.h" -#endif -#ifndef _SFXDEVICE_H_ - #include "sfx/sfxDevice.h" -#endif -#ifndef _SFXDSVOICE_H_ - #include "sfx/dsound/sfxDSVoice.h" -#endif -#ifndef OS_DLIBRARY_H - #include "platform/platformDlibrary.h" -#endif - -#include - -// Typedefs -#define DS_FUNCTION(fn_name, fn_return, fn_args) \ - typedef fn_return (WINAPI *DSFNPTR##fn_name##)##fn_args##; -#include "sfx/dsound/dsFunctions.h" -#undef DS_FUNCTION - -// Function table -struct DSoundFNTable -{ - DSoundFNTable() : isLoaded( false ) {}; - bool isLoaded; - DLibraryRef dllRef; - -#define DS_FUNCTION(fn_name, fn_return, fn_args) \ - DSFNPTR##fn_name fn_name; -#include "sfx/dsound/dsFunctions.h" -#undef DS_FUNCTION -}; - - -/// Helper for asserting on dsound HRESULTS. -inline void DSAssert( HRESULT hr, const char *info ) -{ - #ifdef TORQUE_DEBUG - - if( FAILED( hr ) ) - { - char buf[256]; - dSprintf( buf, 256, "Error code: %x\n%s", hr, info ); - AssertFatal( false, buf ); - } - - #endif -} - - -/// The DirectSound device implementation exposes a couple -/// of settings to script that you should be aware of: -/// -/// $DirectSound::dopplerFactor - This controls the scale of -/// the doppler effect. Valid factors are 0.0 to 10.0 and it -/// defaults to 0.75. -/// -/// $DirectSound::distanceFactor - This sets the unit conversion -/// for -/// -/// $DirectSound::rolloffFactor - ; -/// -/// -class SFXDSDevice : public SFXDevice -{ - typedef SFXDevice Parent; - - friend class SFXDSVoice; - friend class SFXDSProvider; // _init - - public: - - //explicit SFXDSDevice(); - - SFXDSDevice( SFXProvider* provider, - DSoundFNTable *dsFnTbl, - GUID* guid, - String name, - bool useHardware, - S32 maxBuffers ); - - virtual ~SFXDSDevice(); - - protected: - - IDirectSound8 *mDSound; - - IDirectSound3DListener8 *mListener; - - IDirectSoundBuffer *mPrimaryBuffer; - - DSoundFNTable *mDSoundTbl; - - DSCAPS mCaps; - - GUID* mGUID; - - bool _init(); - - /// Called from SFXDSVoice to commit any deferred - /// settings before playback begins. - void _commitDeferred(); - - public: - - // SFXDevice - virtual SFXBuffer* createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description ); - virtual SFXVoice* createVoice( bool is3D, SFXBuffer *buffer ); - virtual void update(); - virtual void setListener( U32 index, const SFXListenerProperties& listener ); - virtual void setDistanceModel( SFXDistanceModel mode ); - virtual void setDopplerFactor( F32 factor ); - virtual void setRolloffFactor( F32 factor ); -}; - -#endif // _SFXDSDEVICE_H_ diff --git a/Engine/source/sfx/dsound/sfxDSProvider.cpp b/Engine/source/sfx/dsound/sfxDSProvider.cpp deleted file mode 100644 index a18101484..000000000 --- a/Engine/source/sfx/dsound/sfxDSProvider.cpp +++ /dev/null @@ -1,198 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "sfx/sfxProvider.h" -#include "sfx/dsound/sfxDSDevice.h" -#include "core/util/safeRelease.h" -#include "console/console.h" -#include "core/strings/unicode.h" -#include "core/util/safeDelete.h" -#include "core/module.h" - - -class SFXDSProvider : public SFXProvider -{ -public: - - SFXDSProvider() - : SFXProvider( "DirectSound" ) {} - virtual ~SFXDSProvider(); - - void init(); - -protected: - DSoundFNTable mDSound; - - struct DSDeviceInfo : SFXDeviceInfo - { - GUID* guid; - DSCAPS caps; - }; - - static BOOL CALLBACK dsEnumProc( - LPGUID lpGUID, - LPCTSTR lpszDesc, - LPCTSTR lpszDrvName, - LPVOID lpContext ); - - void addDeviceDesc( GUID* guid, const String& name, const String& desc ); - -public: - - SFXDevice* createDevice( const String& deviceName, bool useHardware, S32 maxBuffers ); - -}; - -MODULE_BEGIN( DirectSound ) - - MODULE_INIT_BEFORE( SFX ) - MODULE_SHUTDOWN_AFTER( SFX ) - - SFXDSProvider* mProvider; - - MODULE_INIT - { - mProvider = new SFXDSProvider; - } - - MODULE_SHUTDOWN - { - delete mProvider; - } - -MODULE_END; - -//------------------------------------------------------------------------------ -// Helper - -bool dsBindFunction( DLibrary *dll, void *&fnAddress, const char *name ) -{ - fnAddress = dll->bind( name ); - - if (!fnAddress) - Con::warnf( "DSound Loader: DLL bind failed for %s", name ); - - return fnAddress != 0; -} - -//------------------------------------------------------------------------------ - -SFXDSProvider::~SFXDSProvider() -{ -} - -void SFXDSProvider::init() -{ - // Grab the functions we'll want from the dsound DLL. - mDSound.dllRef = OsLoadLibrary( "dsound.dll" ); - mDSound.isLoaded = true; -#define DS_FUNCTION(fn_name, fn_return, fn_args) \ - mDSound.isLoaded &= dsBindFunction(mDSound.dllRef, *(void**)&mDSound.fn_name, #fn_name); -#include "sfx/dsound/dsFunctions.h" -#undef DS_FUNCTION - - AssertISV( mDSound.isLoaded, "DirectSound failed to load." ); - - // All we need to do to init is enumerate the - // devices... if this fails then don't register - // the provider as it's broken in some way. - if ( FAILED( mDSound.DirectSoundEnumerate( dsEnumProc, (VOID*)this ) ) ) - { - Con::errorf( "SFXDSProvider - Device enumeration failed!" ); - return; - } - - // Did we get any devices? - if ( mDeviceInfo.empty() ) - { - Con::errorf( "SFXDSProvider - No valid devices found!" ); - return; - } - - // Wow, we made it - register the provider. - regProvider( this ); -} - - -BOOL CALLBACK SFXDSProvider::dsEnumProc( - LPGUID lpGUID, - LPCTSTR lpszDesc, - LPCTSTR lpszDrvName, - LPVOID lpContext ) -{ - SFXDSProvider* provider = (SFXDSProvider*)lpContext; - provider->addDeviceDesc( lpGUID, lpszDrvName, lpszDesc ); - return TRUE; -} - -void SFXDSProvider::addDeviceDesc( GUID* guid, const String& name, const String& desc ) -{ - // Create a dummy device to get the caps. - IDirectSound8* dsound; - HRESULT hr = mDSound.DirectSoundCreate8( guid, &dsound, NULL ); - if ( FAILED( hr ) || !dsound ) - return; - - // Init the caps structure and have the device fill it out. - DSCAPS caps; - dMemset( &caps, 0, sizeof( caps ) ); - caps.dwSize = sizeof( caps ); - hr = dsound->GetCaps( &caps ); - - // Clean up and handle errors. - SAFE_RELEASE( dsound ); - - if ( FAILED( hr ) ) - return; - - // Now, record the desc info into our own internal list. - DSDeviceInfo* info = new DSDeviceInfo; - info->name = desc; - info->driver = name; - info->hasHardware = caps.dwMaxHw3DAllBuffers > 0; - info->maxBuffers = caps.dwMaxHw3DAllBuffers; - info->guid = guid; - info->caps = caps; - - mDeviceInfo.push_back( info ); -} - -SFXDevice* SFXDSProvider::createDevice( const String& deviceName, bool useHardware, S32 maxBuffers ) -{ - DSDeviceInfo* info = dynamic_cast< DSDeviceInfo* > - ( _findDeviceInfo( deviceName ) ); - - if( !info ) - return NULL; - - SFXDSDevice* device = new SFXDSDevice( this, - &mDSound, - info->guid, - info->name, - useHardware, - maxBuffers ); - - if( !device->_init() ) - SAFE_DELETE( device ); - - return device; -} diff --git a/Engine/source/sfx/dsound/sfxDSVoice.cpp b/Engine/source/sfx/dsound/sfxDSVoice.cpp deleted file mode 100644 index ffabec043..000000000 --- a/Engine/source/sfx/dsound/sfxDSVoice.cpp +++ /dev/null @@ -1,229 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "sfx/dsound/sfxDSVoice.h" -#include "sfx/dsound/sfxDSDevice.h" -#include "core/util/safeRelease.h" - - -SFXDSVoice* SFXDSVoice::create( SFXDSDevice *device, SFXDSBuffer *buffer ) -{ - AssertFatal( buffer, "SFXDSVoice::create() - Got null buffer!" ); - - IDirectSoundBuffer8 *dsBuffer8 = NULL; - if ( !buffer->createVoice( &dsBuffer8 ) || !dsBuffer8 ) - return NULL; - - // Now try to grab a 3D interface... if we don't - // get one its probably because its not a 3d sound. - IDirectSound3DBuffer8* dsBuffer3d8 = NULL; - dsBuffer8->QueryInterface( IID_IDirectSound3DBuffer8, (LPVOID*)&dsBuffer3d8 ); - - // Create the voice and return! - SFXDSVoice* voice = new SFXDSVoice( device, - buffer, - dsBuffer8, - dsBuffer3d8 ); - - // Now set the voice to a default state. - // The buffer from which we have duplicated may have been assigned different - // properties and we don't want to inherit these. - - voice->setVolume( 1.0 ); - voice->setPitch( 1.0 ); - - return voice; -} - -SFXDSVoice::SFXDSVoice( SFXDSDevice *device, - SFXDSBuffer *buffer, - IDirectSoundBuffer8 *dsBuffer, - IDirectSound3DBuffer8 *dsBuffer3d ) - : Parent( buffer ), - mDevice( device ), - mDSBuffer( dsBuffer ), - mDSBuffer3D( dsBuffer3d ), - mIsLooping( false ) -{ - AssertFatal( mDevice, "SFXDSVoice::SFXDSVoice() - SFXDSDevice is null!" ); - AssertFatal( mBuffer, "SFXDSVoice::SFXDSVoice() - SFXDSBuffer is null!" ); - AssertFatal( mDSBuffer, "SFXDSVoice::SFXDSVoice() - Dsound buffer is null!" ); -} - -SFXDSVoice::~SFXDSVoice() -{ - SAFE_RELEASE( mDSBuffer3D ); - - SFXDSBuffer* dsBuffer = _getBuffer(); - if( dsBuffer ) - dsBuffer->releaseVoice( &mDSBuffer ); - - mBuffer = NULL; -} - -SFXStatus SFXDSVoice::_status() const -{ - DWORD status = 0; - mDSBuffer->GetStatus( &status ); - - if ( status & DSBSTATUS_PLAYING ) - return SFXStatusPlaying; - else - return SFXStatusStopped; -} - -void SFXDSVoice::_play() -{ - DSAssert( mDSBuffer->Play( 0, 0, mIsLooping ? DSBPLAY_LOOPING : 0 ), - "SFXDSVoice::_play() - Playback failed!" ); -} - -void SFXDSVoice::_stop() -{ - DSAssert( mDSBuffer->Stop(), "SFXDSVoice::pause - stop failed!" ); - mDSBuffer->SetCurrentPosition( 0 ); -} - -void SFXDSVoice::_pause() -{ - DSAssert( mDSBuffer->Stop(), "SFXDSVoice::pause - stop failed!" ); -} - -void SFXDSVoice::_seek( U32 sample ) -{ - U32 pos = mBuffer->getFormat().getBytesPerSample() * sample; - mDSBuffer->SetCurrentPosition( pos ); -} - -U32 SFXDSVoice::_tell() const -{ - DWORD position = 0; - mDSBuffer->GetCurrentPosition( &position, NULL ); - U32 samplePos = _getBuffer()->getSamplePos( position ); - return samplePos; -} - -void SFXDSVoice::setMinMaxDistance( F32 min, F32 max ) -{ - if ( !mDSBuffer3D ) - return; - - mDSBuffer3D->SetMinDistance( min, DS3D_DEFERRED ); - mDSBuffer3D->SetMaxDistance( max, DS3D_DEFERRED ); -} - -void SFXDSVoice::play( bool looping ) -{ - // If this is a 3d sound then we need - // to commit any deferred settings before - // we start playback else we can get some - // glitches. - - if ( mDSBuffer3D ) - mDevice->_commitDeferred(); - - // If this is a streaming buffer, - // force looping. - - const bool isStreaming = mBuffer->isStreaming(); - if( isStreaming ) - looping = true; - mIsLooping = looping; - - Parent::play( looping ); -} - -void SFXDSVoice::setVelocity( const VectorF& velocity ) -{ - if ( !mDSBuffer3D ) - return; - - DSAssert( mDSBuffer3D->SetVelocity( velocity.x, velocity.z, velocity.y, DS3D_DEFERRED ), - "SFXDSVoice::setVelocity - couldn't update buffer!" ); -} - -void SFXDSVoice::setTransform( const MatrixF& transform ) -{ - if ( !mDSBuffer3D ) - return; - - Point3F pos, dir; - transform.getColumn( 3, &pos ); - transform.getColumn( 1, &dir ); - DSAssert( mDSBuffer3D->SetPosition( pos.x, pos.z, pos.y, DS3D_DEFERRED ), - "SFXDSVoice::setTransform - couldn't set position of the buffer." ); - - DSAssert( mDSBuffer3D->SetConeOrientation( dir.x, dir.z, dir.y, DS3D_DEFERRED ), - "SFXDSVoice::setTransform - couldn't set cone orientation of the buffer." ); -} - -/// Helper for converting floating point linear volume -/// to a logrithmic integer volume for dsound. -LONG SFXDSVoice::_linearToLogVolume( F32 linVolume ) -{ - LONG logVolume; - - if ( linVolume <= 0.0f ) - logVolume = DSBVOLUME_MIN; - else - { - logVolume = -2000.0 * mLog( 1.0f / linVolume ); - logVolume = mClamp( logVolume, DSBVOLUME_MIN, DSBVOLUME_MAX ); - } - - return logVolume; -} - -void SFXDSVoice::setVolume( F32 volume ) -{ - LONG logVolume = _linearToLogVolume( volume ); - - HRESULT hr = mDSBuffer->SetVolume( logVolume ); - DSAssert( hr, "SFXDSVoice::setVolume - couldn't set volume!" ); -} - -void SFXDSVoice::setPitch( F32 pitch ) -{ - F32 sampleRate = _getBuffer()->getFormat().getSamplesPerSecond(); - F32 frequency = mFloor( mClampF( sampleRate * pitch, DSBFREQUENCY_MIN, DSBFREQUENCY_MAX ) ); - - DSAssert( mDSBuffer->SetFrequency( ( U32 )frequency ), - "SFXDSVoice::setPitch - couldn't set playback frequency."); -} - -void SFXDSVoice::setCone( F32 innerAngle, F32 outerAngle, F32 outerVolume ) -{ - if ( !mDSBuffer3D ) - return; - - DSAssert( mDSBuffer3D->SetConeAngles( innerAngle, - outerAngle, - DS3D_DEFERRED ), - "SFXDSVoice::setCone - couldn't set cone angles!" ); - - - LONG logVolume = _linearToLogVolume( outerVolume ); - - DSAssert( mDSBuffer3D->SetConeOutsideVolume( logVolume, - DS3D_DEFERRED ), - "SFXDSVoice::setCone - couldn't set cone outside volume!" ); -} diff --git a/Engine/source/sfx/dsound/sfxDSVoice.h b/Engine/source/sfx/dsound/sfxDSVoice.h deleted file mode 100644 index e428832c1..000000000 --- a/Engine/source/sfx/dsound/sfxDSVoice.h +++ /dev/null @@ -1,92 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _SFXDSVOICE_H_ -#define _SFXDSVOICE_H_ - -#ifndef _SFXVOICE_H_ - #include "sfx/sfxVoice.h" -#endif -#ifndef _SFXDSBUFFER_H_ - #include "sfx/dsound/sfxDSBuffer.h" -#endif - -#include - -class SFXDSDevice; - - -class SFXDSVoice : public SFXVoice -{ - typedef SFXVoice Parent; - - protected: - - SFXDSVoice( SFXDSDevice *device, - SFXDSBuffer *buffer, - IDirectSoundBuffer8 *dsBuffer, - IDirectSound3DBuffer8 *dsBuffer3d ); - - /// The device used to commit deferred settings. - SFXDSDevice *mDevice; - - IDirectSoundBuffer8 *mDSBuffer; - - IDirectSound3DBuffer8 *mDSBuffer3D; - - bool mIsLooping; - - SFXDSBuffer* _getBuffer() const { return ( SFXDSBuffer* ) mBuffer.getPointer(); } - - /// Helper for converting floating point linear volume - /// to a logrithmic integer volume for dsound. - static LONG _linearToLogVolume( F32 linVolume ); - - // SFXVoice - virtual SFXStatus _status() const; - virtual void _play(); - virtual void _pause(); - virtual void _stop(); - virtual void _seek( U32 sample ); - virtual U32 _tell() const; - - public: - - /// - static SFXDSVoice* create( SFXDSDevice *device, - SFXDSBuffer *buffer ); - - /// - virtual ~SFXDSVoice(); - - // SFXVoice - void setMinMaxDistance( F32 min, F32 max ); - void play( bool looping ); - void setVelocity( const VectorF& velocity ); - void setTransform( const MatrixF& transform ); - void setVolume( F32 volume ); - void setPitch( F32 pitch ); - void setCone( F32 innerAngle, F32 outerAngle, F32 outerVolume ); - -}; - -#endif // _SFXDSBUFFER_H_ \ No newline at end of file diff --git a/Engine/source/sfx/media/sfxSndStream.cpp b/Engine/source/sfx/media/sfxSndStream.cpp index 86c7e20ab..ef39e02cf 100644 --- a/Engine/source/sfx/media/sfxSndStream.cpp +++ b/Engine/source/sfx/media/sfxSndStream.cpp @@ -43,36 +43,117 @@ bool SFXSndStream::_readHeader() vio_data.offset = 0; vio_data.data = mStream; + vio_data.sampleBlockAlign = 1; + vio_data.byteBlockAlign = 0; + if ((sndFile = sf_open_virtual(&vio, SFM_READ, &sfinfo, &vio_data)) == NULL) { Con::printf("SFXSndStream - _readHeader failed: %s", sf_strerror(sndFile)); return false; } - S32 bitsPerSample = 0; - switch ((sfinfo.format & SF_FORMAT_SUBMASK)) + S32 bitsPerSample = 16; + + switch (sfinfo.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_S8: case SF_FORMAT_PCM_U8: bitsPerSample = 8; + mSampleType = Sample_Int8; // Still decode using sf_readf_short() break; + case SF_FORMAT_PCM_16: bitsPerSample = 16; + mSampleType = Sample_Int16; break; - case SF_FORMAT_VORBIS: + case SF_FORMAT_PCM_24: case SF_FORMAT_PCM_32: case SF_FORMAT_FLOAT: - bitsPerSample = 16; - sf_command(sndFile, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE); + case SF_FORMAT_DOUBLE: + case SF_FORMAT_VORBIS: + case SF_FORMAT_OPUS: + case SF_FORMAT_ALAC_20: + case SF_FORMAT_ALAC_24: + case SF_FORMAT_ALAC_32: + case 0x0080/*SF_FORMAT_MPEG_LAYER_I*/: + case 0x0081/*SF_FORMAT_MPEG_LAYER_II*/: + case 0x0082/*SF_FORMAT_MPEG_LAYER_III*/: + bitsPerSample = 32; + mSampleType = Sample_Float; break; - default: - // missed, set it to 16 anyway. + + case SF_FORMAT_IMA_ADPCM: bitsPerSample = 16; + mSampleType = Sample_IMA4; + break; + + case SF_FORMAT_MS_ADPCM: + bitsPerSample = 16; + mSampleType = Sample_MSADPCM; + break; + + default: + bitsPerSample = 16; + mSampleType = Sample_Int16; break; } - mFormat.set(sfinfo.channels, bitsPerSample * sfinfo.channels, sfinfo.samplerate); + //------------------------------------------------------------ + // Block alignment logic for ADPCM formats + //------------------------------------------------------------ + int byteBlockAlign = 0; + int sampleBlockAlign = 1; + + if (mSampleType == Sample_IMA4 || mSampleType == Sample_MSADPCM) + { + SF_CHUNK_INFO inf = { "fmt ", 4, 0, NULL }; + SF_CHUNK_ITERATOR* iter = sf_get_chunk_iterator(sndFile, &inf); + + if (!iter || sf_get_chunk_size(iter, &inf) != SF_ERR_NO_ERROR || inf.datalen < 14) + mSampleType = Sample_Int16; + else + { + uint8_t* fmtbuf = (uint8_t*)malloc(inf.datalen); + inf.data = fmtbuf; + + if (sf_get_chunk_data(iter, &inf) != SF_ERR_NO_ERROR) + mSampleType = Sample_Int16; + else + { + byteBlockAlign = fmtbuf[12] | (fmtbuf[13] << 8); + int ch = sfinfo.channels; + + if (mSampleType == Sample_IMA4) + sampleBlockAlign = (byteBlockAlign / ch - 4) / 4 * 8 + 1; + else + sampleBlockAlign = (byteBlockAlign / ch - 7) * 2 + 2; + } + dFree(fmtbuf); + } + } + + //------------------------------------------------------------ + // Commit alignment to class + VIO data + //------------------------------------------------------------ + if (mSampleType == Sample_Int16) + { + sampleBlockAlign = 1; + byteBlockAlign = sfinfo.channels * 2; + } + else if (mSampleType == Sample_Float) + { + sampleBlockAlign = 1; + byteBlockAlign = sfinfo.channels * 4; + } + + vio_data.sampleBlockAlign = sampleBlockAlign; + vio_data.byteBlockAlign = byteBlockAlign; + + mSampleBlockAlign = sampleBlockAlign; + mByteBlockAlign = byteBlockAlign; + + mFormat.set(sfinfo.channels, bitsPerSample * sfinfo.channels, sfinfo.samplerate, mSampleType); mSamples = sfinfo.frames; @@ -136,22 +217,20 @@ U32 SFXSndStream::read(U8* buffer, U32 length) U32 framesRead = 0; - switch (sfinfo.format & SF_FORMAT_SUBMASK) + switch (mSampleType) { - case SF_FORMAT_PCM_S8: - case SF_FORMAT_PCM_U8: - framesRead = sf_readf_int(sndFile, (int*)buffer, framesToRead); + case SFXSampleType::Sample_Int8: framesRead = sf_readf_int(sndFile, (int*)buffer, framesToRead); break; - case SF_FORMAT_PCM_16: - case SF_FORMAT_VORBIS: - case SF_FORMAT_PCM_24: - case SF_FORMAT_PCM_32: - case SF_FORMAT_FLOAT: - framesRead = sf_readf_short(sndFile, (short*)buffer, framesToRead); + case SFXSampleType::Sample_Int16: framesRead = sf_readf_short(sndFile, (short*)buffer, framesToRead); + break; + case SFXSampleType::Sample_Float: framesRead = sf_readf_float(sndFile, (float*)buffer, framesToRead); + break; + case SFXSampleType::Sample_IMA4: + case SFXSampleType::Sample_MSADPCM: + framesRead = sf_read_raw(sndFile, buffer, framesToRead); break; default: - Con::errorf("SFXSndStream - read: Unsupported format."); - return 0; + break; } if (framesRead != framesToRead) diff --git a/Engine/source/sfx/media/sfxSndStream.h b/Engine/source/sfx/media/sfxSndStream.h index a6bfbd28c..c190ab772 100644 --- a/Engine/source/sfx/media/sfxSndStream.h +++ b/Engine/source/sfx/media/sfxSndStream.h @@ -39,11 +39,18 @@ public: protected: + SFXSampleType mSampleType; + S32 mSampleBlockAlign; + S32 mByteBlockAlign; + // setup our vio_data struct. typedef struct { sf_count_t offset, length; Stream* data; + + S32 sampleBlockAlign; + S32 byteBlockAlign; } VIO_DATA; /// Total number of bytes read from the stream so far. @@ -58,11 +65,11 @@ protected: // vio callbacks static sf_count_t sndSeek(sf_count_t offset, int whence, void* user_data); - static sf_count_t sndRead(void *ptr, sf_count_t count, void* user_data); + static sf_count_t sndRead(void* ptr, sf_count_t count, void* user_data); static sf_count_t sndWrite(const void* ptr, sf_count_t count, void* user_data); static sf_count_t sndTell(void* user_data); static sf_count_t sndFileLen(void* user_data); - + // SFXStream bool _readHeader() override; void _close() override; diff --git a/Engine/source/sfx/null/sfxNullDevice.cpp b/Engine/source/sfx/null/sfxNullDevice.cpp index 6b53e29b7..9fc75573f 100644 --- a/Engine/source/sfx/null/sfxNullDevice.cpp +++ b/Engine/source/sfx/null/sfxNullDevice.cpp @@ -24,15 +24,30 @@ #include "sfx/null/sfxNullBuffer.h" #include "sfx/sfxInternal.h" - -SFXNullDevice::SFXNullDevice( SFXProvider* provider, - String name, - bool useHardware, - S32 maxBuffers ) - - : SFXDevice( name, provider, useHardware, maxBuffers ) +class SFXNULLRegisterProvider { - mMaxBuffers = getMax( maxBuffers, 8 ); +public: + SFXNULLRegisterProvider() + { + SFXSystem::getRegisterProviderSignal().notify(&SFXNullDevice::enumerateProviders); + } +}; + +static SFXNULLRegisterProvider pSFXNULLRegisterProvider; + + +SFXProvider::CreateProviderInstanceDelegate SFXNullDevice::mCreateDeviceInstance(SFXNullDevice::createInstance); + +SFXDevice* SFXNullDevice::createInstance(U32 providerIndex) +{ + SFXNullDevice* dev = new SFXNullDevice(providerIndex); + return dev; +} + + +SFXNullDevice::SFXNullDevice( U32 providerIndex ) +{ + mMaxBuffers = 8; } SFXNullDevice::~SFXNullDevice() @@ -65,6 +80,17 @@ SFXVoice* SFXNullDevice::createVoice( bool is3D, SFXBuffer *buffer ) return voice; } +void SFXNullDevice::enumerateProviders(Vector& providerList) +{ + SFXProvider* toAdd = new SFXProvider; + toAdd->mName = String::ToString("SFX Null Device"); + toAdd->mIndex = providerList.size(); + toAdd->mDeviceType = Output; + toAdd->mType = NullProvider; + toAdd->mCreateDeviceInstanceDelegate = mCreateDeviceInstance; + providerList.push_back(toAdd); +} + void SFXNullDevice::update() { // Do nothing. Prevent SFXDevice from running diff --git a/Engine/source/sfx/null/sfxNullDevice.h b/Engine/source/sfx/null/sfxNullDevice.h index 299b53cd8..d3b73a191 100644 --- a/Engine/source/sfx/null/sfxNullDevice.h +++ b/Engine/source/sfx/null/sfxNullDevice.h @@ -23,8 +23,6 @@ #ifndef _SFXNULLDEVICE_H_ #define _SFXNULLDEVICE_H_ -class SFXProvider; - #ifndef _SFXDEVICE_H_ #include "sfx/sfxDevice.h" #endif @@ -37,27 +35,28 @@ class SFXProvider; #ifndef _SFXNULLVOICE_H_ #include "sfx/null/sfxNullVoice.h" #endif - +#ifndef _SFXSYSTEM_H_ +#include "sfx/sfxSystem.h" +#endif class SFXNullDevice : public SFXDevice { typedef SFXDevice Parent; +protected: + static SFXProvider::CreateProviderInstanceDelegate mCreateDeviceInstance; - public: +public: + static void enumerateProviders(Vector& providerList); + SFXNullDevice( U32 providerIndex ); + static SFXDevice* createInstance(U32 adapterIndex); + virtual ~SFXNullDevice(); - SFXNullDevice( SFXProvider* provider, - String name, - bool useHardware, - S32 maxBuffers ); +public: - virtual ~SFXNullDevice(); - - public: - - // SFXDevice. - SFXBuffer* createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description ) override; - SFXVoice* createVoice( bool is3D, SFXBuffer *buffer ) override; - void update() override; + // SFXDevice. + SFXBuffer* createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description ) override; + SFXVoice* createVoice( bool is3D, SFXBuffer *buffer ) override; + void update() override; }; -#endif // _SFXNULLDEVICE_H_ \ No newline at end of file +#endif // _SFXNULLDEVICE_H_ diff --git a/Engine/source/sfx/null/sfxNullProvider.cpp b/Engine/source/sfx/null/sfxNullProvider.cpp deleted file mode 100644 index a41dda4c8..000000000 --- a/Engine/source/sfx/null/sfxNullProvider.cpp +++ /dev/null @@ -1,98 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "sfx/sfxProvider.h" -#include "sfx/null/sfxNullDevice.h" -#include "core/strings/stringFunctions.h" -#include "core/module.h" - - -class SFXNullProvider : public SFXProvider -{ -public: - - SFXNullProvider() - : SFXProvider( "Null" ) {} - virtual ~SFXNullProvider(); - -protected: - void addDeviceDesc( const String& name, const String& desc ); - void init() override; - -public: - - SFXDevice* createDevice( const String& deviceName, bool useHardware, S32 maxBuffers ) override; - -}; - -MODULE_BEGIN( SFXNull ) - - MODULE_INIT_BEFORE( SFX ) - MODULE_SHUTDOWN_AFTER( SFX ) - - SFXNullProvider* mProvider; - - MODULE_INIT - { - mProvider = new SFXNullProvider; - } - - MODULE_SHUTDOWN - { - delete mProvider; - } - -MODULE_END; - -void SFXNullProvider::init() -{ - regProvider( this ); - addDeviceDesc( "Null", "SFX Null Device" ); -} - -SFXNullProvider::~SFXNullProvider() -{ -} - - -void SFXNullProvider::addDeviceDesc( const String& name, const String& desc ) -{ - SFXDeviceInfo* info = new SFXDeviceInfo; - info->internalName = desc; - info->name = "Null Device"; - info->driver = name; - info->hasHardware = false; - info->maxBuffers = 8; - - mDeviceInfo.push_back( info ); -} - -SFXDevice* SFXNullProvider::createDevice( const String& deviceName, bool useHardware, S32 maxBuffers ) -{ - SFXDeviceInfo* info = _findDeviceInfo( deviceName ); - - // Do we find one to create? - if ( info ) - return new SFXNullDevice( this, info->internalName, useHardware, maxBuffers ); - - return NULL; -} diff --git a/Engine/source/sfx/openal/LoadOAL.cpp b/Engine/source/sfx/openal/LoadOAL.cpp new file mode 100644 index 000000000..1f45aeb3b --- /dev/null +++ b/Engine/source/sfx/openal/LoadOAL.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2006, Creative Labs 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: + * + * * Redistributions of source code must retain the above copyright notice, this list of conditions and + * the following disclaimer. + * * 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. + * * Neither the name of Creative Labs Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT OWNER OR 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. + */ + // Based on Openal-soft router code. + +#include "sfx/openal/LoadOAL.h" +#include "console/console.h" + +#if defined(TORQUE_OS_WIN) +#include +#else +#include +#include +#endif + +LIB_HANDLE openaAlDll = NULL; + +#define LOAD_REQUIRED(table, x) \ + table->x = reinterpret_castx)>(reinterpret_cast( \ + GET_PROC_ADDRESS(openaAlDll, #x))); \ + if(!table->x) \ + { \ + Con::warnf("Failed to find entry point :%s\n", #x); \ + loadok = false; \ + } + + +ALboolean LoadOAL10Library(char *szOALFullPathName, LPOPENALFNTABLE oal) +{ + if (!oal) + return AL_FALSE; + + if (szOALFullPathName) + openaAlDll = LOAD_LIBRARY(szOALFullPathName); + else + { +#if defined(TORQUE_OS_WIN) + openaAlDll = LOAD_LIBRARY("openal32.dll"); +#elif defined(TORQUE_OS_LINUX) + openaAlDll = LOAD_LIBRARY("libopenal.so"); +#elif defined(TORQUE_OS_MAC) + openaAlDll = LOAD_LIBRARY("@rpath/libopenal.1.24.3.dylib"); +#endif + } + + if (!openaAlDll) + return AL_FALSE; + + bool loadok = true; + + LOAD_REQUIRED(oal, alcCreateContext); + LOAD_REQUIRED(oal, alcMakeContextCurrent); + LOAD_REQUIRED(oal, alcProcessContext); + LOAD_REQUIRED(oal, alcSuspendContext); + LOAD_REQUIRED(oal, alcDestroyContext); + LOAD_REQUIRED(oal, alcGetCurrentContext); + LOAD_REQUIRED(oal, alcGetContextsDevice); + LOAD_REQUIRED(oal, alcOpenDevice); + LOAD_REQUIRED(oal, alcCloseDevice); + LOAD_REQUIRED(oal, alcGetError); + LOAD_REQUIRED(oal, alcIsExtensionPresent); + LOAD_REQUIRED(oal, alcGetProcAddress); + LOAD_REQUIRED(oal, alcGetEnumValue); + LOAD_REQUIRED(oal, alcGetString); + LOAD_REQUIRED(oal, alcGetIntegerv); + LOAD_REQUIRED(oal, alcCaptureOpenDevice); + LOAD_REQUIRED(oal, alcCaptureCloseDevice); + LOAD_REQUIRED(oal, alcCaptureStart); + LOAD_REQUIRED(oal, alcCaptureStop); + LOAD_REQUIRED(oal, alcCaptureSamples); + + LOAD_REQUIRED(oal, alEnable); + LOAD_REQUIRED(oal, alDisable); + LOAD_REQUIRED(oal, alIsEnabled); + LOAD_REQUIRED(oal, alGetString); + LOAD_REQUIRED(oal, alGetBooleanv); + LOAD_REQUIRED(oal, alGetIntegerv); + LOAD_REQUIRED(oal, alGetFloatv); + LOAD_REQUIRED(oal, alGetDoublev); + LOAD_REQUIRED(oal, alGetBoolean); + LOAD_REQUIRED(oal, alGetInteger); + LOAD_REQUIRED(oal, alGetFloat); + LOAD_REQUIRED(oal, alGetDouble); + LOAD_REQUIRED(oal, alGetError); + LOAD_REQUIRED(oal, alIsExtensionPresent); + LOAD_REQUIRED(oal, alGetProcAddress); + LOAD_REQUIRED(oal, alGetEnumValue); + LOAD_REQUIRED(oal, alListenerf); + LOAD_REQUIRED(oal, alListener3f); + LOAD_REQUIRED(oal, alListenerfv); + LOAD_REQUIRED(oal, alListeneri); + LOAD_REQUIRED(oal, alListener3i); + LOAD_REQUIRED(oal, alListeneriv); + LOAD_REQUIRED(oal, alGetListenerf); + LOAD_REQUIRED(oal, alGetListener3f); + LOAD_REQUIRED(oal, alGetListenerfv); + LOAD_REQUIRED(oal, alGetListeneri); + LOAD_REQUIRED(oal, alGetListener3i); + LOAD_REQUIRED(oal, alGetListeneriv); + LOAD_REQUIRED(oal, alGenSources); + LOAD_REQUIRED(oal, alDeleteSources); + LOAD_REQUIRED(oal, alIsSource); + LOAD_REQUIRED(oal, alSourcef); + LOAD_REQUIRED(oal, alSource3f); + LOAD_REQUIRED(oal, alSourcefv); + LOAD_REQUIRED(oal, alSourcei); + LOAD_REQUIRED(oal, alSource3i); + LOAD_REQUIRED(oal, alSourceiv); + LOAD_REQUIRED(oal, alGetSourcef); + LOAD_REQUIRED(oal, alGetSource3f); + LOAD_REQUIRED(oal, alGetSourcefv); + LOAD_REQUIRED(oal, alGetSourcei); + LOAD_REQUIRED(oal, alGetSource3i); + LOAD_REQUIRED(oal, alGetSourceiv); + LOAD_REQUIRED(oal, alSourcePlayv); + LOAD_REQUIRED(oal, alSourceStopv); + LOAD_REQUIRED(oal, alSourceRewindv); + LOAD_REQUIRED(oal, alSourcePausev); + LOAD_REQUIRED(oal, alSourcePlay); + LOAD_REQUIRED(oal, alSourceStop); + LOAD_REQUIRED(oal, alSourceRewind); + LOAD_REQUIRED(oal, alSourcePause); + LOAD_REQUIRED(oal, alSourceQueueBuffers); + LOAD_REQUIRED(oal, alSourceUnqueueBuffers); + LOAD_REQUIRED(oal, alGenBuffers); + LOAD_REQUIRED(oal, alDeleteBuffers); + LOAD_REQUIRED(oal, alIsBuffer); + LOAD_REQUIRED(oal, alBufferData); + LOAD_REQUIRED(oal, alDopplerFactor); + LOAD_REQUIRED(oal, alDopplerVelocity); + LOAD_REQUIRED(oal, alSpeedOfSound); + LOAD_REQUIRED(oal, alDistanceModel); + + // these are optional. + LOAD_REQUIRED(oal, alBufferf); + LOAD_REQUIRED(oal, alBuffer3f); + LOAD_REQUIRED(oal, alBufferfv); + LOAD_REQUIRED(oal, alBufferi); + LOAD_REQUIRED(oal, alBuffer3i); + LOAD_REQUIRED(oal, alBufferiv); + LOAD_REQUIRED(oal, alGetBufferf); + LOAD_REQUIRED(oal, alGetBuffer3f); + LOAD_REQUIRED(oal, alGetBufferfv); + LOAD_REQUIRED(oal, alGetBufferi); + LOAD_REQUIRED(oal, alGetBuffer3i); + LOAD_REQUIRED(oal, alGetBufferiv); + + return AL_TRUE; +} + +ALvoid UnloadOAL10Library() +{ + // Unload the dll + if (openaAlDll) + CLOSE_LIBRARY(openaAlDll); +} diff --git a/Engine/source/sfx/openal/LoadOAL.h b/Engine/source/sfx/openal/LoadOAL.h index dc9cc5de8..40495ae56 100644 --- a/Engine/source/sfx/openal/LoadOAL.h +++ b/Engine/source/sfx/openal/LoadOAL.h @@ -24,26 +24,52 @@ #define _LOADOAL_H_ #ifndef _PLATFORM_H_ -# include "platform/platform.h" +#include "platform/platform.h" #endif -#if defined(TORQUE_OS_MAC) -#undef AL_ALEXT_PROTOTYPES -# include -# include -#elif defined(TORQUE_OS_LINUX) -# include -# include -# include -# include -# include -#else -# include -# include -# include -# include +#ifndef _TVECTOR_H_ +#include "core/util/tVector.h" #endif +#ifndef _PATH_H_ +#include "core/util/path.h" +#endif + +// Since openal is deprecated and we pack the lib into the mac bundle, all +// platforms now support all of these. +#include +#include +#include +#include +#include + +#ifndef _OPENALFNTABLE +#define _OPENALFNTABLE + +#if defined(TORQUE_OS_WIN) +#include +#define LIB_HANDLE HINSTANCE +#define LOAD_LIBRARY(path) LoadLibraryA(path) +#define GET_PROC_ADDRESS(lib, name) GetProcAddress(lib, name) +#define CLOSE_LIBRARY(lib) FreeLibrary(lib) +#define LIB_EXTENSION L".dll" +#else +#include +#define LIB_HANDLE void* +#define LOAD_LIBRARY(path) dlopen(path, RTLD_LAZY) +#define GET_PROC_ADDRESS(lib, name) dlsym(lib, name) +#define CLOSE_LIBRARY(lib) dlclose(lib) +#ifdef __APPLE__ +#define LIB_EXTENSION ".dylib" +#else +#define LIB_EXTENSION ".so" +#endif +#endif + +constexpr auto MakeALCVer(int major, int minor) noexcept -> int { + return (major << 8) | minor; +} + #ifndef ALAPIENTRY #define ALAPIENTRY #endif @@ -52,11 +78,6 @@ #define ALCAPIENTRY #endif -// Open AL Function table definition - -#ifndef _OPENALFNTABLE -#define _OPENALFNTABLE - // AL 1.0 did not define the ALchar and ALCchar types, so define them here // if they don't exist @@ -68,110 +89,148 @@ #define ALCchar char #endif -typedef struct +struct OPENALFNTABLE { - LPALENABLE alEnable; - LPALDISABLE alDisable; - LPALISENABLED alIsEnabled; - LPALGETBOOLEAN alGetBoolean; - LPALGETINTEGER alGetInteger; - LPALGETFLOAT alGetFloat; - LPALGETDOUBLE alGetDouble; - LPALGETBOOLEANV alGetBooleanv; - LPALGETINTEGERV alGetIntegerv; - LPALGETFLOATV alGetFloatv; - LPALGETDOUBLEV alGetDoublev; - LPALGETSTRING alGetString; - LPALGETERROR alGetError; - LPALISEXTENSIONPRESENT alIsExtensionPresent; - LPALGETPROCADDRESS alGetProcAddress; - LPALGETENUMVALUE alGetEnumValue; - LPALLISTENERI alListeneri; - LPALLISTENERF alListenerf; - LPALLISTENER3F alListener3f; - LPALLISTENERFV alListenerfv; - LPALGETLISTENERI alGetListeneri; - LPALGETLISTENERF alGetListenerf; - LPALGETLISTENER3F alGetListener3f; - LPALGETLISTENERFV alGetListenerfv; - LPALGENSOURCES alGenSources; - LPALDELETESOURCES alDeleteSources; - LPALISSOURCE alIsSource; - LPALSOURCEI alSourcei; - LPALSOURCEF alSourcef; - LPALSOURCE3I alSource3i; - LPALSOURCE3F alSource3f; - LPALSOURCEFV alSourcefv; - LPALGETSOURCEI alGetSourcei; - LPALGETSOURCEF alGetSourcef; - LPALGETSOURCEFV alGetSourcefv; - LPALSOURCEPLAYV alSourcePlayv; - LPALSOURCESTOPV alSourceStopv; - LPALSOURCEPLAY alSourcePlay; - LPALSOURCEPAUSE alSourcePause; - LPALSOURCESTOP alSourceStop; - LPALSOURCEREWIND alSourceRewind; - LPALGENBUFFERS alGenBuffers; - LPALDELETEBUFFERS alDeleteBuffers; - LPALISBUFFER alIsBuffer; - LPALBUFFERDATA alBufferData; - LPALGETBUFFERI alGetBufferi; - LPALGETBUFFERF alGetBufferf; - LPALSOURCEQUEUEBUFFERS alSourceQueueBuffers; - LPALSOURCEUNQUEUEBUFFERS alSourceUnqueueBuffers; - LPALDISTANCEMODEL alDistanceModel; - LPALDOPPLERFACTOR alDopplerFactor; - LPALDOPPLERVELOCITY alDopplerVelocity; - LPALCGETSTRING alcGetString; - LPALCGETINTEGERV alcGetIntegerv; - LPALCOPENDEVICE alcOpenDevice; - LPALCCLOSEDEVICE alcCloseDevice; - LPALCCREATECONTEXT alcCreateContext; - LPALCMAKECONTEXTCURRENT alcMakeContextCurrent; - LPALCPROCESSCONTEXT alcProcessContext; - LPALCGETCURRENTCONTEXT alcGetCurrentContext; - LPALCGETCONTEXTSDEVICE alcGetContextsDevice; - LPALCSUSPENDCONTEXT alcSuspendContext; - LPALCDESTROYCONTEXT alcDestroyContext; - LPALCGETERROR alcGetError; - LPALCISEXTENSIONPRESENT alcIsExtensionPresent; - LPALCGETPROCADDRESS alcGetProcAddress; - LPALCGETENUMVALUE alcGetEnumValue; - -#if defined(AL_ALEXT_PROTOTYPES) - LPALGENEFFECTS alGenEffects; - LPALDELETEEFFECTS alDeleteEffects; - LPALISEFFECT alIsEffect; - LPALEFFECTI alEffecti; - LPALEFFECTIV alEffectiv; - LPALEFFECTF alEffectf; - LPALEFFECTFV alEffectfv; - LPALGETEFFECTI alGetEffecti; - LPALGETEFFECTIV alGetEffectiv; - LPALGETEFFECTF alGetEffectf; - LPALGETEFFECTFV alGetEffectfv; - LPALRELEASEALEFFECTS alReleaseEffects; - LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots; - LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots; - LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot; - LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti; - LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv; - LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf; - LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv; - LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti; - LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv; - LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf; - LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv; - LPALGENFILTERS alGenFilters; - LPALDELETEFILTERS alDeleteFilters; - LPALFILTERI alFilteri; - LPALCGETSTRINGISOFT alcGetStringiSOFT; + LPALCCREATECONTEXT alcCreateContext{ nullptr }; + LPALCMAKECONTEXTCURRENT alcMakeContextCurrent{ nullptr }; + LPALCPROCESSCONTEXT alcProcessContext{ nullptr }; + LPALCSUSPENDCONTEXT alcSuspendContext{ nullptr }; + LPALCDESTROYCONTEXT alcDestroyContext{ nullptr }; + LPALCGETCURRENTCONTEXT alcGetCurrentContext{ nullptr }; + LPALCGETCONTEXTSDEVICE alcGetContextsDevice{ nullptr }; + LPALCOPENDEVICE alcOpenDevice{ nullptr }; + LPALCCLOSEDEVICE alcCloseDevice{ nullptr }; + LPALCGETERROR alcGetError{ nullptr }; + LPALCISEXTENSIONPRESENT alcIsExtensionPresent{ nullptr }; + LPALCGETPROCADDRESS alcGetProcAddress{ nullptr }; + LPALCGETENUMVALUE alcGetEnumValue{ nullptr }; + LPALCGETSTRING alcGetString{ nullptr }; + LPALCGETINTEGERV alcGetIntegerv{ nullptr }; + LPALCCAPTUREOPENDEVICE alcCaptureOpenDevice{ nullptr }; + LPALCCAPTURECLOSEDEVICE alcCaptureCloseDevice{ nullptr }; + LPALCCAPTURESTART alcCaptureStart{ nullptr }; + LPALCCAPTURESTOP alcCaptureStop{ nullptr }; + LPALCCAPTURESAMPLES alcCaptureSamples{ nullptr }; + + PFNALCSETTHREADCONTEXTPROC alcSetThreadContext{ nullptr }; + PFNALCGETTHREADCONTEXTPROC alcGetThreadContext{ nullptr }; + + LPALENABLE alEnable{ nullptr }; + LPALDISABLE alDisable{ nullptr }; + LPALISENABLED alIsEnabled{ nullptr }; + LPALGETSTRING alGetString{ nullptr }; + LPALGETBOOLEANV alGetBooleanv{ nullptr }; + LPALGETINTEGERV alGetIntegerv{ nullptr }; + LPALGETFLOATV alGetFloatv{ nullptr }; + LPALGETDOUBLEV alGetDoublev{ nullptr }; + LPALGETBOOLEAN alGetBoolean{ nullptr }; + LPALGETINTEGER alGetInteger{ nullptr }; + LPALGETFLOAT alGetFloat{ nullptr }; + LPALGETDOUBLE alGetDouble{ nullptr }; + LPALGETERROR alGetError{ nullptr }; + LPALISEXTENSIONPRESENT alIsExtensionPresent{ nullptr }; + LPALGETPROCADDRESS alGetProcAddress{ nullptr }; + LPALGETENUMVALUE alGetEnumValue{ nullptr }; + LPALLISTENERF alListenerf{ nullptr }; + LPALLISTENER3F alListener3f{ nullptr }; + LPALLISTENERFV alListenerfv{ nullptr }; + LPALLISTENERI alListeneri{ nullptr }; + LPALLISTENER3I alListener3i{ nullptr }; + LPALLISTENERIV alListeneriv{ nullptr }; + LPALGETLISTENERF alGetListenerf{ nullptr }; + LPALGETLISTENER3F alGetListener3f{ nullptr }; + LPALGETLISTENERFV alGetListenerfv{ nullptr }; + LPALGETLISTENERI alGetListeneri{ nullptr }; + LPALGETLISTENER3I alGetListener3i{ nullptr }; + LPALGETLISTENERIV alGetListeneriv{ nullptr }; + LPALGENSOURCES alGenSources{ nullptr }; + LPALDELETESOURCES alDeleteSources{ nullptr }; + LPALISSOURCE alIsSource{ nullptr }; + LPALSOURCEF alSourcef{ nullptr }; + LPALSOURCE3F alSource3f{ nullptr }; + LPALSOURCEFV alSourcefv{ nullptr }; + LPALSOURCEI alSourcei{ nullptr }; + LPALSOURCE3I alSource3i{ nullptr }; + LPALSOURCEIV alSourceiv{ nullptr }; + LPALGETSOURCEF alGetSourcef{ nullptr }; + LPALGETSOURCE3F alGetSource3f{ nullptr }; + LPALGETSOURCEFV alGetSourcefv{ nullptr }; + LPALGETSOURCEI alGetSourcei{ nullptr }; + LPALGETSOURCE3I alGetSource3i{ nullptr }; + LPALGETSOURCEIV alGetSourceiv{ nullptr }; + LPALSOURCEPLAYV alSourcePlayv{ nullptr }; + LPALSOURCESTOPV alSourceStopv{ nullptr }; + LPALSOURCEREWINDV alSourceRewindv{ nullptr }; + LPALSOURCEPAUSEV alSourcePausev{ nullptr }; + LPALSOURCEPLAY alSourcePlay{ nullptr }; + LPALSOURCESTOP alSourceStop{ nullptr }; + LPALSOURCEREWIND alSourceRewind{ nullptr }; + LPALSOURCEPAUSE alSourcePause{ nullptr }; + LPALSOURCEQUEUEBUFFERS alSourceQueueBuffers{ nullptr }; + LPALSOURCEUNQUEUEBUFFERS alSourceUnqueueBuffers{ nullptr }; + LPALGENBUFFERS alGenBuffers{ nullptr }; + LPALDELETEBUFFERS alDeleteBuffers{ nullptr }; + LPALISBUFFER alIsBuffer{ nullptr }; + LPALBUFFERF alBufferf{ nullptr }; + LPALBUFFER3F alBuffer3f{ nullptr }; + LPALBUFFERFV alBufferfv{ nullptr }; + LPALBUFFERI alBufferi{ nullptr }; + LPALBUFFER3I alBuffer3i{ nullptr }; + LPALBUFFERIV alBufferiv{ nullptr }; + LPALGETBUFFERF alGetBufferf{ nullptr }; + LPALGETBUFFER3F alGetBuffer3f{ nullptr }; + LPALGETBUFFERFV alGetBufferfv{ nullptr }; + LPALGETBUFFERI alGetBufferi{ nullptr }; + LPALGETBUFFER3I alGetBuffer3i{ nullptr }; + LPALGETBUFFERIV alGetBufferiv{ nullptr }; + LPALBUFFERDATA alBufferData{ nullptr }; + LPALDOPPLERFACTOR alDopplerFactor{ nullptr }; + LPALDOPPLERVELOCITY alDopplerVelocity{ nullptr }; + LPALSPEEDOFSOUND alSpeedOfSound{ nullptr }; + LPALDISTANCEMODEL alDistanceModel{ nullptr }; + + /* Functions to load after first context creation. */ + LPALGENFILTERS alGenFilters{ nullptr }; + LPALDELETEFILTERS alDeleteFilters{ nullptr }; + LPALISFILTER alIsFilter{ nullptr }; + LPALFILTERF alFilterf{ nullptr }; + LPALFILTERFV alFilterfv{ nullptr }; + LPALFILTERI alFilteri{ nullptr }; + LPALFILTERIV alFilteriv{ nullptr }; + LPALGETFILTERF alGetFilterf{ nullptr }; + LPALGETFILTERFV alGetFilterfv{ nullptr }; + LPALGETFILTERI alGetFilteri{ nullptr }; + LPALGETFILTERIV alGetFilteriv{ nullptr }; + LPALGENEFFECTS alGenEffects{ nullptr }; + LPALDELETEEFFECTS alDeleteEffects{ nullptr }; + LPALISEFFECT alIsEffect{ nullptr }; + LPALEFFECTF alEffectf{ nullptr }; + LPALEFFECTFV alEffectfv{ nullptr }; + LPALEFFECTI alEffecti{ nullptr }; + LPALEFFECTIV alEffectiv{ nullptr }; + LPALGETEFFECTF alGetEffectf{ nullptr }; + LPALGETEFFECTFV alGetEffectfv{ nullptr }; + LPALGETEFFECTI alGetEffecti{ nullptr }; + LPALGETEFFECTIV alGetEffectiv{ nullptr }; + LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots{ nullptr }; + LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots{ nullptr }; + LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot{ nullptr }; + LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf{ nullptr }; + LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv{ nullptr }; + LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti{ nullptr }; + LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv{ nullptr }; + LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf{ nullptr }; + LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv{ nullptr }; + LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti{ nullptr }; + LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv{ nullptr }; + +}; + +using LPOPENALFNTABLE = OPENALFNTABLE*; + #endif -} OPENALFNTABLE, *LPOPENALFNTABLE; -#endif - -ALboolean LoadOAL10Library(char *szOALFullPathName, LPOPENALFNTABLE lpOALFnTable); +ALboolean LoadOAL10Library(char* szOALFullPathName, LPOPENALFNTABLE lpOALFnTable); ALvoid UnloadOAL10Library(); #endif // _LOADOAL_H_ diff --git a/Engine/source/sfx/openal/aldlist.cpp b/Engine/source/sfx/openal/aldlist.cpp deleted file mode 100644 index f55a56569..000000000 --- a/Engine/source/sfx/openal/aldlist.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) 2006, Creative Labs 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: - * - * * Redistributions of source code must retain the above copyright notice, this list of conditions and - * the following disclaimer. - * * 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. - * * Neither the name of Creative Labs Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT OWNER OR 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. - */ - -#include "core/strings/stringFunctions.h" - -#include "aldlist.h" -#if defined(TORQUE_OS_MAC) -#include -#elif defined(TORQUE_OS_LINUX) -#include -#else -#include -#endif - - -/* - * Init call - */ -ALDeviceList::ALDeviceList( const OPENALFNTABLE& oalft ) -{ - VECTOR_SET_ASSOCIATION( vDeviceInfo ); - - ALDEVICEINFO ALDeviceInfo; - char *devices; - int index; - const char *defaultDeviceName; - const char *actualDeviceName; - - dMemcpy( &ALFunction, &oalft, sizeof(OPENALFNTABLE) ); - - // DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support - vDeviceInfo.clear(); - vDeviceInfo.reserve(10); - - defaultDeviceIndex = 0; - - // grab function pointers for 1.0-API functions, and if successful proceed to enumerate all devices - if (ALFunction.alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT")) { - devices = (char *)ALFunction.alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); - defaultDeviceName = (char *)ALFunction.alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER); - } - else - { - devices = (char *)ALFunction.alcGetString(NULL, ALC_DEVICE_SPECIFIER); - defaultDeviceName = (char *)ALFunction.alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); - } - - index = 0; - // go through device list (each device terminated with a single NULL, list terminated with double NULL) - while (*devices != '\0') { - if (String::compare(defaultDeviceName, devices) == 0) { - defaultDeviceIndex = index; - } - - ALCdevice* device = ALFunction.alcOpenDevice(devices); - if (device) - { - ALCcontext* ctx = ALFunction.alcCreateContext(device, nullptr); - - if (ctx) - { - ALFunction.alcMakeContextCurrent(ctx); - actualDeviceName = ALFunction.alcGetString(device, ALC_DEVICE_SPECIFIER); - bool bNewName = true; - - if (actualDeviceName) - { - for (int i = 0; i < GetNumDevices(); i++) { - if (String::compare(GetDeviceName(i), devices) == 0) { - bNewName = false; - } - } - } - - if ((bNewName) && (actualDeviceName != NULL) && (dStrlen(actualDeviceName) > 0)) - { - dMemset(&ALDeviceInfo, 0, sizeof(ALDEVICEINFO)); - ALDeviceInfo.bSelected = true; - dStrncpy(ALDeviceInfo.strDeviceName, actualDeviceName, sizeof(ALDeviceInfo.strDeviceName)); - char deviceExternal[256]; - dStrcpy(deviceExternal, devices, 256); - - vDeviceInfo.push_back(ALDeviceInfo); - } - - ALFunction.alcMakeContextCurrent(nullptr); - ALFunction.alcDestroyContext(ctx); - } - ALFunction.alcCloseDevice(device); - } - - devices += dStrlen(devices) + 1; - index += 1; - } - - ResetFilters(); -} - -/* - * Exit call - */ -ALDeviceList::~ALDeviceList() -{ -} - -/* - * Returns the number of devices in the complete device list - */ -int ALDeviceList::GetNumDevices() -{ - return (int)vDeviceInfo.size(); -} - -/* - * Returns the device name at an index in the complete device list - */ -const char* ALDeviceList::GetDeviceName(int index) -{ - if (index < GetNumDevices()) - return vDeviceInfo[index].strDeviceName; - else - return NULL; -} - - -/* - * Returns the major and minor version numbers for a device at a specified index in the complete list - */ -void ALDeviceList::GetDeviceVersion(int index, int *major, int *minor) -{ - if (index < GetNumDevices()) { - if (major) - *major = vDeviceInfo[index].iMajorVersion; - if (minor) - *minor = vDeviceInfo[index].iMinorVersion; - } - return; -} - -/* - * Returns the maximum number of Sources that can be generate on the given device - */ -U32 ALDeviceList::GetMaxNumSources(S32 index) -{ - if (index < GetNumDevices()) - return vDeviceInfo[index].uiSourceCount; - else - return 0; -} - -/* - * Checks if the extension is supported on the given device - */ -bool ALDeviceList::IsExtensionSupported(int index, SFXALCaps cap) -{ - bool bReturn = false; - - if (index < GetNumDevices()) - bReturn = vDeviceInfo[index].iCapsFlags & cap; - - return bReturn; -} - -/* - * returns the index of the default device in the complete device list - */ -int ALDeviceList::GetDefaultDevice() -{ - return defaultDeviceIndex; -} - -/* - * Deselects devices which don't have the specified minimum version - */ -void ALDeviceList::FilterDevicesMinVer(S32 major, S32 minor) -{ - int dMajor, dMinor; - for (U32 i = 0; i < vDeviceInfo.size(); i++) { - GetDeviceVersion(i, &dMajor, &dMinor); - if ((dMajor < major) || ((dMajor == major) && (dMinor < minor))) { - vDeviceInfo[i].bSelected = false; - } - } -} - -/* - * Deselects devices which don't have the specified maximum version - */ -void ALDeviceList::FilterDevicesMaxVer(S32 major, S32 minor) -{ - S32 dMajor, dMinor; - for (U32 i = 0; i < vDeviceInfo.size(); i++) { - GetDeviceVersion(i, &dMajor, &dMinor); - if ((dMajor > major) || ((dMajor == major) && (dMinor > minor))) { - vDeviceInfo[i].bSelected = false; - } - } -} - -/* - * Deselects device which don't support the given extension name - */ -void ALDeviceList::FilterDevicesExtension(SFXALCaps cap) -{ - for (U32 i = 0; i < vDeviceInfo.size(); i++) - vDeviceInfo[i].bSelected = vDeviceInfo[i].iCapsFlags & cap; -} - -/* - * Resets all filtering, such that all devices are in the list - */ -void ALDeviceList::ResetFilters() -{ - for (S32 i = 0; i < GetNumDevices(); i++) { - vDeviceInfo[i].bSelected = true; - } - filterIndex = 0; -} - -/* - * Gets index of first filtered device - */ -int ALDeviceList::GetFirstFilteredDevice() -{ - int i; - - for (i = 0; i < GetNumDevices(); i++) { - if (vDeviceInfo[i].bSelected == true) { - break; - } - } - filterIndex = i + 1; - return i; -} - -/* - * Gets index of next filtered device - */ -int ALDeviceList::GetNextFilteredDevice() -{ - int i; - - for (i = filterIndex; i < GetNumDevices(); i++) { - if (vDeviceInfo[i].bSelected == true) { - break; - } - } - filterIndex = i + 1; - return i; -} - -/* - * Internal function to detemine max number of Sources that can be generated - */ -unsigned int ALDeviceList::GetMaxNumSources() -{ - ALuint uiSources[256]; - U32 iSourceCount = 0; - - // Clear AL Error Code - ALFunction.alGetError(); - - // Generate up to 256 Sources, checking for any errors - for (iSourceCount = 0; iSourceCount < 256; iSourceCount++) - { - ALFunction.alGenSources(1, &uiSources[iSourceCount]); - if (ALFunction.alGetError() != AL_NO_ERROR) - break; - } - - // Release the Sources - ALFunction.alDeleteSources(iSourceCount, uiSources); - if (ALFunction.alGetError() != AL_NO_ERROR) - { - for (U32 i = 0; i < 256; i++) - { - ALFunction.alDeleteSources(1, &uiSources[i]); - } - } - - return iSourceCount; -} diff --git a/Engine/source/sfx/openal/aldlist.h b/Engine/source/sfx/openal/aldlist.h deleted file mode 100644 index 20f110361..000000000 --- a/Engine/source/sfx/openal/aldlist.h +++ /dev/null @@ -1,71 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef ALDEVICELIST_H -#define ALDEVICELIST_H - -#pragma warning(disable: 4786) //disable warning "identifier was truncated to '255' characters in the browser information" -#include "core/util/tVector.h" -#include "core/stringTable.h" -#include "sfx/openal/sfxALCaps.h" -#include "LoadOAL.h" - -typedef struct -{ - char strDeviceName[256]; - char strInternalDeviceName[256]; - S32 iMajorVersion; - S32 iMinorVersion; - U32 uiSourceCount; - S32 iCapsFlags; - bool bSelected; -} ALDEVICEINFO, *LPALDEVICEINFO; - -class ALDeviceList -{ -private: - OPENALFNTABLE ALFunction; - Vector vDeviceInfo; - S32 defaultDeviceIndex; - S32 filterIndex; - -public: - ALDeviceList ( const OPENALFNTABLE &oalft ); - ~ALDeviceList (); - S32 GetNumDevices(); - const char *GetDeviceName(S32 index); - void GetDeviceVersion(S32 index, S32 *major, S32 *minor); - U32 GetMaxNumSources(S32 index); - bool IsExtensionSupported(S32 index, SFXALCaps caps); - S32 GetDefaultDevice(); - void FilterDevicesMinVer(S32 major, S32 minor); - void FilterDevicesMaxVer(S32 major, S32 minor); - void FilterDevicesExtension(SFXALCaps caps); - void ResetFilters(); - S32 GetFirstFilteredDevice(); - S32 GetNextFilteredDevice(); - -private: - U32 GetMaxNumSources(); -}; - -#endif // ALDEVICELIST_H diff --git a/Engine/source/sfx/openal/linux/LoadOAL.linux.cpp b/Engine/source/sfx/openal/linux/LoadOAL.linux.cpp deleted file mode 100644 index 0ac1a59b3..000000000 --- a/Engine/source/sfx/openal/linux/LoadOAL.linux.cpp +++ /dev/null @@ -1,616 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -// TODO: Implement OpenAL loading code which is currently stubbed out. - -#if defined(__linux__) && !defined(TORQUE_OS_LINUX) -#define TORQUE_OS_LINUX -#endif - -#include -#include -#include -#include "sfx/openal/LoadOAL.h" -#include "console/console.h" - -void* openal_library = NULL; - -ALboolean LoadOAL10Library(char *szOALFullPathName, LPOPENALFNTABLE lpOALFnTable) -{ - if (!lpOALFnTable) - return AL_FALSE; - - if (szOALFullPathName) - openal_library = dlopen(szOALFullPathName, RTLD_NOW); - else - { -#ifdef TORQUE_DEBUG - openal_library = dlopen("libopenald.so.1", RTLD_NOW); - - // If the .1 library is not found, try the normal filename - if (openal_library == NULL) - { - openal_library = dlopen("libopenald.so", RTLD_NOW); - } -#else - openal_library = dlopen("libopenal.so.1", RTLD_NOW); - - // If the .1 library is not found, try the normal filename - if (openal_library == NULL) - { - openal_library = dlopen("libopenal.so", RTLD_NOW); - } -#endif - } - - if (openal_library == NULL) { - Con::errorf("Failed to load OpenAL shared library. Sound will not be available"); - return AL_FALSE; - } - - memset(lpOALFnTable, 0, sizeof(OPENALFNTABLE)); - - lpOALFnTable->alEnable = (LPALENABLE)dlsym(openal_library,"alEnable"); - if (lpOALFnTable->alEnable == NULL) - { - warn("Failed to retrieve 'alEnable' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDisable = (LPALDISABLE)dlsym(openal_library,"alDisable"); - if (lpOALFnTable->alDisable == NULL) - { - warn("Failed to retrieve 'alDisable' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsEnabled = (LPALISENABLED)dlsym(openal_library,"alIsEnabled"); - if (lpOALFnTable->alIsEnabled == NULL) - { - warn("Failed to retrieve 'alIsEnabled' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetBoolean = (LPALGETBOOLEAN)dlsym(openal_library,"alGetBoolean"); - if (lpOALFnTable->alGetBoolean == NULL) - { - warn("Failed to retrieve 'alGetBoolean' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetInteger = (LPALGETINTEGER)dlsym(openal_library,"alGetInteger"); - if (lpOALFnTable->alGetInteger == NULL) - { - warn("Failed to retrieve 'alGetInteger' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetFloat = (LPALGETFLOAT)dlsym(openal_library,"alGetFloat"); - if (lpOALFnTable->alGetFloat == NULL) - { - warn("Failed to retrieve 'alGetFloat' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetDouble = (LPALGETDOUBLE)dlsym(openal_library,"alGetDouble"); - if (lpOALFnTable->alGetDouble == NULL) - { - warn("Failed to retrieve 'alGetDouble' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetBooleanv = (LPALGETBOOLEANV)dlsym(openal_library,"alGetBooleanv"); - if (lpOALFnTable->alGetBooleanv == NULL) - { - warn("Failed to retrieve 'alGetBooleanv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetIntegerv = (LPALGETINTEGERV)dlsym(openal_library,"alGetIntegerv"); - if (lpOALFnTable->alGetIntegerv == NULL) - { - warn("Failed to retrieve 'alGetIntegerv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetFloatv = (LPALGETFLOATV)dlsym(openal_library,"alGetFloatv"); - if (lpOALFnTable->alGetFloatv == NULL) - { - warn("Failed to retrieve 'alGetFloatv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetDoublev = (LPALGETDOUBLEV)dlsym(openal_library,"alGetDoublev"); - if (lpOALFnTable->alGetDoublev == NULL) - { - warn("Failed to retrieve 'alGetDoublev' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetString = (LPALGETSTRING)dlsym(openal_library,"alGetString"); - if (lpOALFnTable->alGetString == NULL) - { - warn("Failed to retrieve 'alGetString' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetError = (LPALGETERROR)dlsym(openal_library,"alGetError"); - if (lpOALFnTable->alGetError == NULL) - { - warn("Failed to retrieve 'alGetError' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsExtensionPresent = (LPALISEXTENSIONPRESENT)dlsym(openal_library,"alIsExtensionPresent"); - if (lpOALFnTable->alIsExtensionPresent == NULL) - { - warn("Failed to retrieve 'alIsExtensionPresent' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetProcAddress = (LPALGETPROCADDRESS)dlsym(openal_library,"alGetProcAddress"); - if (lpOALFnTable->alGetProcAddress == NULL) - { - warn("Failed to retrieve 'alGetProcAddress' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetEnumValue = (LPALGETENUMVALUE)dlsym(openal_library,"alGetEnumValue"); - if (lpOALFnTable->alGetEnumValue == NULL) - { - warn("Failed to retrieve 'alGetEnumValue' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alListeneri = (LPALLISTENERI)dlsym(openal_library,"alListeneri"); - if (lpOALFnTable->alListeneri == NULL) - { - warn("Failed to retrieve 'alListeneri' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alListenerf = (LPALLISTENERF)dlsym(openal_library,"alListenerf"); - if (lpOALFnTable->alListenerf == NULL) - { - warn("Failed to retrieve 'alListenerf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alListener3f = (LPALLISTENER3F)dlsym(openal_library,"alListener3f"); - if (lpOALFnTable->alListener3f == NULL) - { - warn("Failed to retrieve 'alListener3f' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alListenerfv = (LPALLISTENERFV)dlsym(openal_library,"alListenerfv"); - if (lpOALFnTable->alListenerfv == NULL) - { - warn("Failed to retrieve 'alListenerfv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetListeneri = (LPALGETLISTENERI)dlsym(openal_library,"alGetListeneri"); - if (lpOALFnTable->alGetListeneri == NULL) - { - warn("Failed to retrieve 'alGetListeneri' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetListenerf =(LPALGETLISTENERF)dlsym(openal_library,"alGetListenerf"); - if (lpOALFnTable->alGetListenerf == NULL) - { - warn("Failed to retrieve 'alGetListenerf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetListener3f = (LPALGETLISTENER3F)dlsym(openal_library,"alGetListener3f"); - if (lpOALFnTable->alGetListener3f == NULL) - { - warn("Failed to retrieve 'alGetListener3f' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetListenerfv = (LPALGETLISTENERFV)dlsym(openal_library,"alGetListenerfv"); - if (lpOALFnTable->alGetListenerfv == NULL) - { - warn("Failed to retrieve 'alGetListenerfv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGenSources = (LPALGENSOURCES)dlsym(openal_library,"alGenSources"); - if (lpOALFnTable->alGenSources == NULL) - { - warn("Failed to retrieve 'alGenSources' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDeleteSources = (LPALDELETESOURCES)dlsym(openal_library,"alDeleteSources"); - if (lpOALFnTable->alDeleteSources == NULL) - { - warn("Failed to retrieve 'alDeleteSources' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsSource = (LPALISSOURCE)dlsym(openal_library,"alIsSource"); - if (lpOALFnTable->alIsSource == NULL) - { - warn("Failed to retrieve 'alIsSource' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcei = (LPALSOURCEI)dlsym(openal_library,"alSourcei"); - if (lpOALFnTable->alSourcei == NULL) - { - warn("Failed to retrieve 'alSourcei' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcef = (LPALSOURCEF)dlsym(openal_library,"alSourcef"); - if (lpOALFnTable->alSourcef == NULL) - { - warn("Failed to retrieve 'alSourcef' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSource3f = (LPALSOURCE3F)dlsym(openal_library,"alSource3f"); - if (lpOALFnTable->alSource3f == NULL) - { - warn("Failed to retrieve 'alSource3f' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcefv = (LPALSOURCEFV)dlsym(openal_library,"alSourcefv"); - if (lpOALFnTable->alSourcefv == NULL) - { - warn("Failed to retrieve 'alSourcefv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetSourcei = (LPALGETSOURCEI)dlsym(openal_library,"alGetSourcei"); - if (lpOALFnTable->alGetSourcei == NULL) - { - warn("Failed to retrieve 'alGetSourcei' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetSourcef = (LPALGETSOURCEF)dlsym(openal_library,"alGetSourcef"); - if (lpOALFnTable->alGetSourcef == NULL) - { - warn("Failed to retrieve 'alGetSourcef' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetSourcefv = (LPALGETSOURCEFV)dlsym(openal_library,"alGetSourcefv"); - if (lpOALFnTable->alGetSourcefv == NULL) - { - warn("Failed to retrieve 'alGetSourcefv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcePlayv = (LPALSOURCEPLAYV)dlsym(openal_library,"alSourcePlayv"); - if (lpOALFnTable->alSourcePlayv == NULL) - { - warn("Failed to retrieve 'alSourcePlayv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourceStopv = (LPALSOURCESTOPV)dlsym(openal_library,"alSourceStopv"); - if (lpOALFnTable->alSourceStopv == NULL) - { - warn("Failed to retrieve 'alSourceStopv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcePlay = (LPALSOURCEPLAY)dlsym(openal_library,"alSourcePlay"); - if (lpOALFnTable->alSourcePlay == NULL) - { - warn("Failed to retrieve 'alSourcePlay' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcePause = (LPALSOURCEPAUSE)dlsym(openal_library,"alSourcePause"); - if (lpOALFnTable->alSourcePause == NULL) - { - warn("Failed to retrieve 'alSourcePause' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourceStop = (LPALSOURCESTOP)dlsym(openal_library,"alSourceStop"); - if (lpOALFnTable->alSourceStop == NULL) - { - warn("Failed to retrieve 'alSourceStop' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourceRewind = (LPALSOURCEREWIND)dlsym(openal_library,"alSourceRewind"); - if (lpOALFnTable->alSourceRewind == NULL) - { - warn("Failed to retrieve 'alSourceRewind' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGenBuffers = (LPALGENBUFFERS)dlsym(openal_library,"alGenBuffers"); - if (lpOALFnTable->alGenBuffers == NULL) - { - warn("Failed to retrieve 'alGenBuffers' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDeleteBuffers = (LPALDELETEBUFFERS)dlsym(openal_library,"alDeleteBuffers"); - if (lpOALFnTable->alDeleteBuffers == NULL) - { - warn("Failed to retrieve 'alDeleteBuffers' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsBuffer = (LPALISBUFFER)dlsym(openal_library,"alIsBuffer"); - if (lpOALFnTable->alIsBuffer == NULL) - { - warn("Failed to retrieve 'alIsBuffer' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alBufferData = (LPALBUFFERDATA)dlsym(openal_library,"alBufferData"); - if (lpOALFnTable->alBufferData == NULL) - { - warn("Failed to retrieve 'alBufferData' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetBufferi = (LPALGETBUFFERI)dlsym(openal_library,"alGetBufferi"); - if (lpOALFnTable->alGetBufferi == NULL) - { - warn("Failed to retrieve 'alGetBufferi' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetBufferf = (LPALGETBUFFERF)dlsym(openal_library,"alGetBufferf"); - if (lpOALFnTable->alGetBufferf == NULL) - { - warn("Failed to retrieve 'alGetBufferf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourceQueueBuffers = (LPALSOURCEQUEUEBUFFERS)dlsym(openal_library,"alSourceQueueBuffers"); - if (lpOALFnTable->alSourceQueueBuffers == NULL) - { - warn("Failed to retrieve 'alSourceQueueBuffers' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourceUnqueueBuffers = (LPALSOURCEUNQUEUEBUFFERS)dlsym(openal_library,"alSourceUnqueueBuffers"); - if (lpOALFnTable->alSourceUnqueueBuffers == NULL) - { - warn("Failed to retrieve 'alSourceUnqueueBuffers' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDistanceModel = (LPALDISTANCEMODEL)dlsym(openal_library,"alDistanceModel"); - if (lpOALFnTable->alDistanceModel == NULL) - { - warn("Failed to retrieve 'alDistanceModel' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDopplerFactor = (LPALDOPPLERFACTOR)dlsym(openal_library,"alDopplerFactor"); - if (lpOALFnTable->alDopplerFactor == NULL) - { - warn("Failed to retrieve 'alDopplerFactor' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDopplerVelocity = (LPALDOPPLERVELOCITY)dlsym(openal_library,"alDopplerVelocity"); - if (lpOALFnTable->alDopplerVelocity == NULL) - { - warn("Failed to retrieve 'alDopplerVelocity' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetString = (LPALCGETSTRING)dlsym(openal_library,"alcGetString"); - if (lpOALFnTable->alcGetString == NULL) - { - warn("Failed to retrieve 'alcGetString' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetIntegerv = (LPALCGETINTEGERV)dlsym(openal_library,"alcGetIntegerv"); - if (lpOALFnTable->alcGetIntegerv == NULL) - { - warn("Failed to retrieve 'alcGetIntegerv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcOpenDevice = (LPALCOPENDEVICE)dlsym(openal_library,"alcOpenDevice"); - if (lpOALFnTable->alcOpenDevice == NULL) - { - warn("Failed to retrieve 'alcOpenDevice' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcCloseDevice = (LPALCCLOSEDEVICE)dlsym(openal_library,"alcCloseDevice"); - if (lpOALFnTable->alcCloseDevice == NULL) - { - warn("Failed to retrieve 'alcCloseDevice' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcCreateContext = (LPALCCREATECONTEXT)dlsym(openal_library,"alcCreateContext"); - if (lpOALFnTable->alcCreateContext == NULL) - { - warn("Failed to retrieve 'alcCreateContext' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcMakeContextCurrent = (LPALCMAKECONTEXTCURRENT)dlsym(openal_library,"alcMakeContextCurrent"); - if (lpOALFnTable->alcMakeContextCurrent == NULL) - { - warn("Failed to retrieve 'alcMakeContextCurrent' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcProcessContext = (LPALCPROCESSCONTEXT)dlsym(openal_library,"alcProcessContext"); - if (lpOALFnTable->alcProcessContext == NULL) - { - warn("Failed to retrieve 'alcProcessContext' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetCurrentContext = (LPALCGETCURRENTCONTEXT)dlsym(openal_library,"alcGetCurrentContext"); - if (lpOALFnTable->alcGetCurrentContext == NULL) - { - warn("Failed to retrieve 'alcGetCurrentContext' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetContextsDevice = (LPALCGETCONTEXTSDEVICE)dlsym(openal_library,"alcGetContextsDevice"); - if (lpOALFnTable->alcGetContextsDevice == NULL) - { - warn("Failed to retrieve 'alcGetContextsDevice' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcSuspendContext = (LPALCSUSPENDCONTEXT)dlsym(openal_library,"alcSuspendContext"); - if (lpOALFnTable->alcSuspendContext == NULL) - { - warn("Failed to retrieve 'alcSuspendContext' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcDestroyContext = (LPALCDESTROYCONTEXT)dlsym(openal_library,"alcDestroyContext"); - if (lpOALFnTable->alcDestroyContext == NULL) - { - warn("Failed to retrieve 'alcDestroyContext' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetError = (LPALCGETERROR)dlsym(openal_library,"alcGetError"); - if (lpOALFnTable->alcGetError == NULL) - { - warn("Failed to retrieve 'alcGetError' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcIsExtensionPresent = (LPALCISEXTENSIONPRESENT)dlsym(openal_library,"alcIsExtensionPresent"); - if (lpOALFnTable->alcIsExtensionPresent == NULL) - { - warn("Failed to retrieve 'alcIsExtensionPresent' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetProcAddress = (LPALCGETPROCADDRESS)dlsym(openal_library,"alcGetProcAddress"); - if (lpOALFnTable->alcGetProcAddress == NULL) - { - warn("Failed to retrieve 'alcGetProcAddress' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetEnumValue = (LPALCGETENUMVALUE)dlsym(openal_library,"alcGetEnumValue"); - if (lpOALFnTable->alcGetEnumValue == NULL) - { - warn("Failed to retrieve 'alcGetEnumValue' function address\n"); - return AL_FALSE; - } -#if defined(AL_ALEXT_PROTOTYPES) - //efx - lpOALFnTable->alGenEffects = (LPALGENEFFECTS)dlsym(openal_library, "alGenEffects"); - if (lpOALFnTable->alGenEffects == NULL) - { - warn("Failed to retrieve 'alGenEffects' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alEffecti = (LPALEFFECTI)dlsym(openal_library, "alEffecti"); - if (lpOALFnTable->alEffecti == NULL) - { - warn("Failed to retrieve 'alEffecti' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alEffectiv = (LPALEFFECTIV)dlsym(openal_library, "alEffectiv"); - if (lpOALFnTable->alEffectiv == NULL) - { - warn("Failed to retrieve 'alEffectiv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alEffectf = (LPALEFFECTF)dlsym(openal_library, "alEffectf"); - if (lpOALFnTable->alEffectf == NULL) - { - warn("Failed to retrieve 'alEffectf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alEffectfv = (LPALEFFECTFV)dlsym(openal_library, "alEffectfv"); - if (lpOALFnTable->alEffectfv == NULL) - { - warn("Failed to retrieve 'alEffectfv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetEffecti = (LPALGETEFFECTI)dlsym(openal_library, "alGetEffecti"); - if (lpOALFnTable->alGetEffecti == NULL) - { - warn("Failed to retrieve 'alGetEffecti' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetEffectiv = (LPALGETEFFECTIV)dlsym(openal_library, "alGetEffectiv"); - if (lpOALFnTable->alGetEffectiv == NULL) - { - warn("Failed to retrieve 'alGetEffectiv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetEffectf = (LPALGETEFFECTF)dlsym(openal_library, "alGetEffectf"); - if (lpOALFnTable->alGetEffectf == NULL) - { - warn("Failed to retrieve 'alGetEffectf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetEffectfv = (LPALGETEFFECTFV)dlsym(openal_library, "alGetEffectfv"); - if (lpOALFnTable->alGetEffectfv == NULL) - { - warn("Failed to retrieve 'alGetEffectfv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDeleteEffects = (LPALDELETEEFFECTS)dlsym(openal_library, "alDeleteEffects"); - if (lpOALFnTable->alDeleteEffects == NULL) - { - warn("Failed to retrieve 'alDeleteEffects' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsEffect = (LPALISEFFECT)dlsym(openal_library, "alIsEffect"); - if (lpOALFnTable->alIsEffect == NULL) - { - warn("Failed to retrieve 'alIsEffect' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alAuxiliaryEffectSlotf = (LPALAUXILIARYEFFECTSLOTF)dlsym(openal_library, "alAuxiliaryEffectSlotf"); - if (lpOALFnTable->alAuxiliaryEffectSlotf == NULL) - { - warn("Failed to retrieve 'alAuxiliaryEffectSlotf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alAuxiliaryEffectSlotfv = (LPALAUXILIARYEFFECTSLOTFV)dlsym(openal_library, "alAuxiliaryEffectSlotfv"); - if (lpOALFnTable->alAuxiliaryEffectSlotfv == NULL) - { - warn("Failed to retrieve 'alAuxiliaryEffectSlotfv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alAuxiliaryEffectSloti = (LPALAUXILIARYEFFECTSLOTI)dlsym(openal_library, "alAuxiliaryEffectSloti"); - if (lpOALFnTable->alAuxiliaryEffectSloti == NULL) - { - warn("Failed to retrieve 'alAuxiliaryEffectSloti' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alAuxiliaryEffectSlotiv = (LPALAUXILIARYEFFECTSLOTIV)dlsym(openal_library, "alAuxiliaryEffectSlotiv"); - if (lpOALFnTable->alAuxiliaryEffectSlotiv == NULL) - { - warn("Failed to retrieve 'alAuxiliaryEffectSlotiv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsAuxiliaryEffectSlot = (LPALISAUXILIARYEFFECTSLOT)dlsym(openal_library, "alIsAuxiliaryEffectSlot"); - if (lpOALFnTable->alIsAuxiliaryEffectSlot == NULL) - { - warn("Failed to retrieve 'alIsAuxiliaryEffectSlot' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGenAuxiliaryEffectSlots = (LPALGENAUXILIARYEFFECTSLOTS)dlsym(openal_library, "alGenAuxiliaryEffectSlots"); - if (lpOALFnTable->alGenAuxiliaryEffectSlots == NULL) - { - warn("Failed to retrieve 'alGenAuxiliaryEffectSlots' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDeleteAuxiliaryEffectSlots = (LPALDELETEAUXILIARYEFFECTSLOTS)dlsym(openal_library, "alDeleteAuxiliaryEffectSlots"); - if (lpOALFnTable->alDeleteAuxiliaryEffectSlots == NULL) - { - warn("Failed to retrieve 'alDeleteAuxiliaryEffectSlots' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetAuxiliaryEffectSlotf = (LPALGETAUXILIARYEFFECTSLOTF)dlsym(openal_library, "alGetAuxiliaryEffectSlotf"); - if (lpOALFnTable->alGetAuxiliaryEffectSlotf == NULL) - { - warn("Failed to retrieve 'alGetAuxiliaryEffectSlotf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetAuxiliaryEffectSlotfv = (LPALGETAUXILIARYEFFECTSLOTFV)dlsym(openal_library, "alGetAuxiliaryEffectSlotfv"); - if (lpOALFnTable->alGetAuxiliaryEffectSlotfv == NULL) - { - warn("Failed to retrieve 'alGetAuxiliaryEffectSlotfv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetAuxiliaryEffectSloti = (LPALGETAUXILIARYEFFECTSLOTI)dlsym(openal_library, "alGetAuxiliaryEffectSloti"); - if (lpOALFnTable->alGetAuxiliaryEffectSloti == NULL) - { - warn("Failed to retrieve 'alGetAuxiliaryEffectSloti' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetAuxiliaryEffectSlotiv = (LPALGETAUXILIARYEFFECTSLOTIV)dlsym(openal_library, "alGetAuxiliaryEffectSlotiv"); - if (lpOALFnTable->alGetAuxiliaryEffectSlotiv == NULL) - { - warn("Failed to retrieve 'alGetAuxiliaryEffectSlotiv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSource3i = (LPALSOURCE3I)dlsym(openal_library, "alSource3i"); - if (lpOALFnTable->alSource3i == NULL) - { - warn("Failed to retrieve 'alSource3i' function address\n"); - return AL_FALSE; - } -#endif - return AL_TRUE; -} - -ALvoid UnloadOAL10Library() -{ - if (openal_library != NULL) - dlclose(openal_library); -} diff --git a/Engine/source/sfx/openal/mac/LoadOAL.mac.cpp b/Engine/source/sfx/openal/mac/LoadOAL.mac.cpp deleted file mode 100644 index baf40d33b..000000000 --- a/Engine/source/sfx/openal/mac/LoadOAL.mac.cpp +++ /dev/null @@ -1,618 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -// TODO: Implement OpenAL loading code which is currently stubbed out. - -#if defined(__MACOSX__) && !defined(TORQUE_OS_MAC) -#define TORQUE_OS_MAC -#endif - -#include "console/console.h" - -#include -#include -#include -#include "sfx/openal/LoadOAL.h" - -void* openal_library = NULL; - -ALboolean LoadOAL10Library(char *szOALFullPathName, LPOPENALFNTABLE lpOALFnTable) -{ - // TODO: Implement this. - if (!lpOALFnTable) - return AL_FALSE; - - if (szOALFullPathName) - openal_library = dlopen(szOALFullPathName, RTLD_NOW); - else - { -#ifdef TORQUE_DEBUG - openal_library = dlopen("@rpath/libopenald.1.23.1.dylib", RTLD_NOW); - - if (openal_library == NULL) - { - openal_library = dlopen("@rpath/libopenald.1.dylib", RTLD_NOW); - } -#else - openal_library = dlopen("@rpath/libopenal.1.23.1.dylib", RTLD_NOW); - - if (openal_library == NULL) - { - openal_library = dlopen("@rpath/libopenal .1.dylib", RTLD_NOW); - } -#endif - } - - if (openal_library == NULL) - { - Con::errorf("Failed to load OpenAL shared library. Sound will not be available"); - return AL_FALSE; - } - - - memset(lpOALFnTable, 0, sizeof(OPENALFNTABLE)); - - lpOALFnTable->alEnable = (LPALENABLE)dlsym(openal_library,"alEnable"); - if (lpOALFnTable->alEnable == NULL) - { - warn("Failed to retrieve 'alEnable' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDisable = (LPALDISABLE)dlsym(openal_library,"alDisable"); - if (lpOALFnTable->alDisable == NULL) - { - warn("Failed to retrieve 'alDisable' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsEnabled = (LPALISENABLED)dlsym(openal_library,"alIsEnabled"); - if (lpOALFnTable->alIsEnabled == NULL) - { - warn("Failed to retrieve 'alIsEnabled' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetBoolean = (LPALGETBOOLEAN)dlsym(openal_library,"alGetBoolean"); - if (lpOALFnTable->alGetBoolean == NULL) - { - warn("Failed to retrieve 'alGetBoolean' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetInteger = (LPALGETINTEGER)dlsym(openal_library,"alGetInteger"); - if (lpOALFnTable->alGetInteger == NULL) - { - warn("Failed to retrieve 'alGetInteger' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetFloat = (LPALGETFLOAT)dlsym(openal_library,"alGetFloat"); - if (lpOALFnTable->alGetFloat == NULL) - { - warn("Failed to retrieve 'alGetFloat' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetDouble = (LPALGETDOUBLE)dlsym(openal_library,"alGetDouble"); - if (lpOALFnTable->alGetDouble == NULL) - { - warn("Failed to retrieve 'alGetDouble' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetBooleanv = (LPALGETBOOLEANV)dlsym(openal_library,"alGetBooleanv"); - if (lpOALFnTable->alGetBooleanv == NULL) - { - warn("Failed to retrieve 'alGetBooleanv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetIntegerv = (LPALGETINTEGERV)dlsym(openal_library,"alGetIntegerv"); - if (lpOALFnTable->alGetIntegerv == NULL) - { - warn("Failed to retrieve 'alGetIntegerv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetFloatv = (LPALGETFLOATV)dlsym(openal_library,"alGetFloatv"); - if (lpOALFnTable->alGetFloatv == NULL) - { - warn("Failed to retrieve 'alGetFloatv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetDoublev = (LPALGETDOUBLEV)dlsym(openal_library,"alGetDoublev"); - if (lpOALFnTable->alGetDoublev == NULL) - { - warn("Failed to retrieve 'alGetDoublev' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetString = (LPALGETSTRING)dlsym(openal_library,"alGetString"); - if (lpOALFnTable->alGetString == NULL) - { - warn("Failed to retrieve 'alGetString' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetError = (LPALGETERROR)dlsym(openal_library,"alGetError"); - if (lpOALFnTable->alGetError == NULL) - { - warn("Failed to retrieve 'alGetError' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsExtensionPresent = (LPALISEXTENSIONPRESENT)dlsym(openal_library,"alIsExtensionPresent"); - if (lpOALFnTable->alIsExtensionPresent == NULL) - { - warn("Failed to retrieve 'alIsExtensionPresent' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetProcAddress = (LPALGETPROCADDRESS)dlsym(openal_library,"alGetProcAddress"); - if (lpOALFnTable->alGetProcAddress == NULL) - { - warn("Failed to retrieve 'alGetProcAddress' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetEnumValue = (LPALGETENUMVALUE)dlsym(openal_library,"alGetEnumValue"); - if (lpOALFnTable->alGetEnumValue == NULL) - { - warn("Failed to retrieve 'alGetEnumValue' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alListeneri = (LPALLISTENERI)dlsym(openal_library,"alListeneri"); - if (lpOALFnTable->alListeneri == NULL) - { - warn("Failed to retrieve 'alListeneri' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alListenerf = (LPALLISTENERF)dlsym(openal_library,"alListenerf"); - if (lpOALFnTable->alListenerf == NULL) - { - warn("Failed to retrieve 'alListenerf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alListener3f = (LPALLISTENER3F)dlsym(openal_library,"alListener3f"); - if (lpOALFnTable->alListener3f == NULL) - { - warn("Failed to retrieve 'alListener3f' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alListenerfv = (LPALLISTENERFV)dlsym(openal_library,"alListenerfv"); - if (lpOALFnTable->alListenerfv == NULL) - { - warn("Failed to retrieve 'alListenerfv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetListeneri = (LPALGETLISTENERI)dlsym(openal_library,"alGetListeneri"); - if (lpOALFnTable->alGetListeneri == NULL) - { - warn("Failed to retrieve 'alGetListeneri' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetListenerf =(LPALGETLISTENERF)dlsym(openal_library,"alGetListenerf"); - if (lpOALFnTable->alGetListenerf == NULL) - { - warn("Failed to retrieve 'alGetListenerf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetListener3f = (LPALGETLISTENER3F)dlsym(openal_library,"alGetListener3f"); - if (lpOALFnTable->alGetListener3f == NULL) - { - warn("Failed to retrieve 'alGetListener3f' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetListenerfv = (LPALGETLISTENERFV)dlsym(openal_library,"alGetListenerfv"); - if (lpOALFnTable->alGetListenerfv == NULL) - { - warn("Failed to retrieve 'alGetListenerfv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGenSources = (LPALGENSOURCES)dlsym(openal_library,"alGenSources"); - if (lpOALFnTable->alGenSources == NULL) - { - warn("Failed to retrieve 'alGenSources' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDeleteSources = (LPALDELETESOURCES)dlsym(openal_library,"alDeleteSources"); - if (lpOALFnTable->alDeleteSources == NULL) - { - warn("Failed to retrieve 'alDeleteSources' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsSource = (LPALISSOURCE)dlsym(openal_library,"alIsSource"); - if (lpOALFnTable->alIsSource == NULL) - { - warn("Failed to retrieve 'alIsSource' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcei = (LPALSOURCEI)dlsym(openal_library,"alSourcei"); - if (lpOALFnTable->alSourcei == NULL) - { - warn("Failed to retrieve 'alSourcei' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcef = (LPALSOURCEF)dlsym(openal_library,"alSourcef"); - if (lpOALFnTable->alSourcef == NULL) - { - warn("Failed to retrieve 'alSourcef' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSource3f = (LPALSOURCE3F)dlsym(openal_library,"alSource3f"); - if (lpOALFnTable->alSource3f == NULL) - { - warn("Failed to retrieve 'alSource3f' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcefv = (LPALSOURCEFV)dlsym(openal_library,"alSourcefv"); - if (lpOALFnTable->alSourcefv == NULL) - { - warn("Failed to retrieve 'alSourcefv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetSourcei = (LPALGETSOURCEI)dlsym(openal_library,"alGetSourcei"); - if (lpOALFnTable->alGetSourcei == NULL) - { - warn("Failed to retrieve 'alGetSourcei' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetSourcef = (LPALGETSOURCEF)dlsym(openal_library,"alGetSourcef"); - if (lpOALFnTable->alGetSourcef == NULL) - { - warn("Failed to retrieve 'alGetSourcef' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetSourcefv = (LPALGETSOURCEFV)dlsym(openal_library,"alGetSourcefv"); - if (lpOALFnTable->alGetSourcefv == NULL) - { - warn("Failed to retrieve 'alGetSourcefv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcePlayv = (LPALSOURCEPLAYV)dlsym(openal_library,"alSourcePlayv"); - if (lpOALFnTable->alSourcePlayv == NULL) - { - warn("Failed to retrieve 'alSourcePlayv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourceStopv = (LPALSOURCESTOPV)dlsym(openal_library,"alSourceStopv"); - if (lpOALFnTable->alSourceStopv == NULL) - { - warn("Failed to retrieve 'alSourceStopv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcePlay = (LPALSOURCEPLAY)dlsym(openal_library,"alSourcePlay"); - if (lpOALFnTable->alSourcePlay == NULL) - { - warn("Failed to retrieve 'alSourcePlay' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcePause = (LPALSOURCEPAUSE)dlsym(openal_library,"alSourcePause"); - if (lpOALFnTable->alSourcePause == NULL) - { - warn("Failed to retrieve 'alSourcePause' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourceStop = (LPALSOURCESTOP)dlsym(openal_library,"alSourceStop"); - if (lpOALFnTable->alSourceStop == NULL) - { - warn("Failed to retrieve 'alSourceStop' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourceRewind = (LPALSOURCEREWIND)dlsym(openal_library,"alSourceRewind"); - if (lpOALFnTable->alSourceRewind == NULL) - { - warn("Failed to retrieve 'alSourceRewind' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGenBuffers = (LPALGENBUFFERS)dlsym(openal_library,"alGenBuffers"); - if (lpOALFnTable->alGenBuffers == NULL) - { - warn("Failed to retrieve 'alGenBuffers' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDeleteBuffers = (LPALDELETEBUFFERS)dlsym(openal_library,"alDeleteBuffers"); - if (lpOALFnTable->alDeleteBuffers == NULL) - { - warn("Failed to retrieve 'alDeleteBuffers' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsBuffer = (LPALISBUFFER)dlsym(openal_library,"alIsBuffer"); - if (lpOALFnTable->alIsBuffer == NULL) - { - warn("Failed to retrieve 'alIsBuffer' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alBufferData = (LPALBUFFERDATA)dlsym(openal_library,"alBufferData"); - if (lpOALFnTable->alBufferData == NULL) - { - warn("Failed to retrieve 'alBufferData' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetBufferi = (LPALGETBUFFERI)dlsym(openal_library,"alGetBufferi"); - if (lpOALFnTable->alGetBufferi == NULL) - { - warn("Failed to retrieve 'alGetBufferi' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetBufferf = (LPALGETBUFFERF)dlsym(openal_library,"alGetBufferf"); - if (lpOALFnTable->alGetBufferf == NULL) - { - warn("Failed to retrieve 'alGetBufferf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourceQueueBuffers = (LPALSOURCEQUEUEBUFFERS)dlsym(openal_library,"alSourceQueueBuffers"); - if (lpOALFnTable->alSourceQueueBuffers == NULL) - { - warn("Failed to retrieve 'alSourceQueueBuffers' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourceUnqueueBuffers = (LPALSOURCEUNQUEUEBUFFERS)dlsym(openal_library,"alSourceUnqueueBuffers"); - if (lpOALFnTable->alSourceUnqueueBuffers == NULL) - { - warn("Failed to retrieve 'alSourceUnqueueBuffers' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDistanceModel = (LPALDISTANCEMODEL)dlsym(openal_library,"alDistanceModel"); - if (lpOALFnTable->alDistanceModel == NULL) - { - warn("Failed to retrieve 'alDistanceModel' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDopplerFactor = (LPALDOPPLERFACTOR)dlsym(openal_library,"alDopplerFactor"); - if (lpOALFnTable->alDopplerFactor == NULL) - { - warn("Failed to retrieve 'alDopplerFactor' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDopplerVelocity = (LPALDOPPLERVELOCITY)dlsym(openal_library,"alDopplerVelocity"); - if (lpOALFnTable->alDopplerVelocity == NULL) - { - warn("Failed to retrieve 'alDopplerVelocity' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetString = (LPALCGETSTRING)dlsym(openal_library,"alcGetString"); - if (lpOALFnTable->alcGetString == NULL) - { - warn("Failed to retrieve 'alcGetString' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetIntegerv = (LPALCGETINTEGERV)dlsym(openal_library,"alcGetIntegerv"); - if (lpOALFnTable->alcGetIntegerv == NULL) - { - warn("Failed to retrieve 'alcGetIntegerv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcOpenDevice = (LPALCOPENDEVICE)dlsym(openal_library,"alcOpenDevice"); - if (lpOALFnTable->alcOpenDevice == NULL) - { - warn("Failed to retrieve 'alcOpenDevice' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcCloseDevice = (LPALCCLOSEDEVICE)dlsym(openal_library,"alcCloseDevice"); - if (lpOALFnTable->alcCloseDevice == NULL) - { - warn("Failed to retrieve 'alcCloseDevice' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcCreateContext = (LPALCCREATECONTEXT)dlsym(openal_library,"alcCreateContext"); - if (lpOALFnTable->alcCreateContext == NULL) - { - warn("Failed to retrieve 'alcCreateContext' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcMakeContextCurrent = (LPALCMAKECONTEXTCURRENT)dlsym(openal_library,"alcMakeContextCurrent"); - if (lpOALFnTable->alcMakeContextCurrent == NULL) - { - warn("Failed to retrieve 'alcMakeContextCurrent' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcProcessContext = (LPALCPROCESSCONTEXT)dlsym(openal_library,"alcProcessContext"); - if (lpOALFnTable->alcProcessContext == NULL) - { - warn("Failed to retrieve 'alcProcessContext' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetCurrentContext = (LPALCGETCURRENTCONTEXT)dlsym(openal_library,"alcGetCurrentContext"); - if (lpOALFnTable->alcGetCurrentContext == NULL) - { - warn("Failed to retrieve 'alcGetCurrentContext' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetContextsDevice = (LPALCGETCONTEXTSDEVICE)dlsym(openal_library,"alcGetContextsDevice"); - if (lpOALFnTable->alcGetContextsDevice == NULL) - { - warn("Failed to retrieve 'alcGetContextsDevice' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcSuspendContext = (LPALCSUSPENDCONTEXT)dlsym(openal_library,"alcSuspendContext"); - if (lpOALFnTable->alcSuspendContext == NULL) - { - warn("Failed to retrieve 'alcSuspendContext' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcDestroyContext = (LPALCDESTROYCONTEXT)dlsym(openal_library,"alcDestroyContext"); - if (lpOALFnTable->alcDestroyContext == NULL) - { - warn("Failed to retrieve 'alcDestroyContext' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetError = (LPALCGETERROR)dlsym(openal_library,"alcGetError"); - if (lpOALFnTable->alcGetError == NULL) - { - warn("Failed to retrieve 'alcGetError' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcIsExtensionPresent = (LPALCISEXTENSIONPRESENT)dlsym(openal_library,"alcIsExtensionPresent"); - if (lpOALFnTable->alcIsExtensionPresent == NULL) - { - warn("Failed to retrieve 'alcIsExtensionPresent' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetProcAddress = (LPALCGETPROCADDRESS)dlsym(openal_library,"alcGetProcAddress"); - if (lpOALFnTable->alcGetProcAddress == NULL) - { - warn("Failed to retrieve 'alcGetProcAddress' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetEnumValue = (LPALCGETENUMVALUE)dlsym(openal_library,"alcGetEnumValue"); - if (lpOALFnTable->alcGetEnumValue == NULL) - { - warn("Failed to retrieve 'alcGetEnumValue' function address\n"); - return AL_FALSE; - } -#if defined(AL_ALEXT_PROTOTYPES) - //efx - lpOALFnTable->alGenEffects = (LPALGENEFFECTS)dlsym(openal_library, "alGenEffects"); - if (lpOALFnTable->alGenEffects == NULL) - { - warn("Failed to retrieve 'alGenEffects' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alEffecti = (LPALEFFECTI)dlsym(openal_library, "alEffecti"); - if (lpOALFnTable->alEffecti == NULL) - { - warn("Failed to retrieve 'alEffecti' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alEffectiv = (LPALEFFECTIV)dlsym(openal_library, "alEffectiv"); - if (lpOALFnTable->alEffectiv == NULL) - { - warn("Failed to retrieve 'alEffectiv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alEffectf = (LPALEFFECTF)dlsym(openal_library, "alEffectf"); - if (lpOALFnTable->alEffectf == NULL) - { - warn("Failed to retrieve 'alEffectf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alEffectfv = (LPALEFFECTFV)dlsym(openal_library, "alEffectfv"); - if (lpOALFnTable->alEffectfv == NULL) - { - warn("Failed to retrieve 'alEffectfv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetEffecti = (LPALGETEFFECTI)dlsym(openal_library, "alGetEffecti"); - if (lpOALFnTable->alGetEffecti == NULL) - { - warn("Failed to retrieve 'alGetEffecti' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetEffectiv = (LPALGETEFFECTIV)dlsym(openal_library, "alGetEffectiv"); - if (lpOALFnTable->alGetEffectiv == NULL) - { - warn("Failed to retrieve 'alGetEffectiv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetEffectf = (LPALGETEFFECTF)dlsym(openal_library, "alGetEffectf"); - if (lpOALFnTable->alGetEffectf == NULL) - { - warn("Failed to retrieve 'alGetEffectf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetEffectfv = (LPALGETEFFECTFV)dlsym(openal_library, "alGetEffectfv"); - if (lpOALFnTable->alGetEffectfv == NULL) - { - warn("Failed to retrieve 'alGetEffectfv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDeleteEffects = (LPALDELETEEFFECTS)dlsym(openal_library, "alDeleteEffects"); - if (lpOALFnTable->alDeleteEffects == NULL) - { - warn("Failed to retrieve 'alDeleteEffects' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsEffect = (LPALISEFFECT)dlsym(openal_library, "alIsEffect"); - if (lpOALFnTable->alIsEffect == NULL) - { - warn("Failed to retrieve 'alIsEffect' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alAuxiliaryEffectSlotf = (LPALAUXILIARYEFFECTSLOTF)dlsym(openal_library, "alAuxiliaryEffectSlotf"); - if (lpOALFnTable->alAuxiliaryEffectSlotf == NULL) - { - warn("Failed to retrieve 'alAuxiliaryEffectSlotf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alAuxiliaryEffectSlotfv = (LPALAUXILIARYEFFECTSLOTFV)dlsym(openal_library, "alAuxiliaryEffectSlotfv"); - if (lpOALFnTable->alAuxiliaryEffectSlotfv == NULL) - { - warn("Failed to retrieve 'alAuxiliaryEffectSlotfv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alAuxiliaryEffectSloti = (LPALAUXILIARYEFFECTSLOTI)dlsym(openal_library, "alAuxiliaryEffectSloti"); - if (lpOALFnTable->alAuxiliaryEffectSloti == NULL) - { - warn("Failed to retrieve 'alAuxiliaryEffectSloti' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alAuxiliaryEffectSlotiv = (LPALAUXILIARYEFFECTSLOTIV)dlsym(openal_library, "alAuxiliaryEffectSlotiv"); - if (lpOALFnTable->alAuxiliaryEffectSlotiv == NULL) - { - warn("Failed to retrieve 'alAuxiliaryEffectSlotiv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsAuxiliaryEffectSlot = (LPALISAUXILIARYEFFECTSLOT)dlsym(openal_library, "alIsAuxiliaryEffectSlot"); - if (lpOALFnTable->alIsAuxiliaryEffectSlot == NULL) - { - warn("Failed to retrieve 'alIsAuxiliaryEffectSlot' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGenAuxiliaryEffectSlots = (LPALGENAUXILIARYEFFECTSLOTS)dlsym(openal_library, "alGenAuxiliaryEffectSlots"); - if (lpOALFnTable->alGenAuxiliaryEffectSlots == NULL) - { - warn("Failed to retrieve 'alGenAuxiliaryEffectSlots' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDeleteAuxiliaryEffectSlots = (LPALDELETEAUXILIARYEFFECTSLOTS)dlsym(openal_library, "alDeleteAuxiliaryEffectSlots"); - if (lpOALFnTable->alDeleteAuxiliaryEffectSlots == NULL) - { - warn("Failed to retrieve 'alDeleteAuxiliaryEffectSlots' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetAuxiliaryEffectSlotf = (LPALGETAUXILIARYEFFECTSLOTF)dlsym(openal_library, "alGetAuxiliaryEffectSlotf"); - if (lpOALFnTable->alGetAuxiliaryEffectSlotf == NULL) - { - warn("Failed to retrieve 'alGetAuxiliaryEffectSlotf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetAuxiliaryEffectSlotfv = (LPALGETAUXILIARYEFFECTSLOTFV)dlsym(openal_library, "alGetAuxiliaryEffectSlotfv"); - if (lpOALFnTable->alGetAuxiliaryEffectSlotfv == NULL) - { - warn("Failed to retrieve 'alGetAuxiliaryEffectSlotfv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetAuxiliaryEffectSloti = (LPALGETAUXILIARYEFFECTSLOTI)dlsym(openal_library, "alGetAuxiliaryEffectSloti"); - if (lpOALFnTable->alGetAuxiliaryEffectSloti == NULL) - { - warn("Failed to retrieve 'alGetAuxiliaryEffectSloti' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetAuxiliaryEffectSlotiv = (LPALGETAUXILIARYEFFECTSLOTIV)dlsym(openal_library, "alGetAuxiliaryEffectSlotiv"); - if (lpOALFnTable->alGetAuxiliaryEffectSlotiv == NULL) - { - warn("Failed to retrieve 'alGetAuxiliaryEffectSlotiv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSource3i = (LPALSOURCE3I)dlsym(openal_library, "alSource3i"); - if (lpOALFnTable->alSource3i == NULL) - { - warn("Failed to retrieve 'alSource3i' function address\n"); - return AL_FALSE; - } -#endif - return AL_TRUE; -} - -ALvoid UnloadOAL10Library() -{ - if (openal_library != NULL) - dlclose(openal_library); -} diff --git a/Engine/source/sfx/openal/sfxALBuffer.cpp b/Engine/source/sfx/openal/sfxALBuffer.cpp index c276e2a3d..95481b314 100644 --- a/Engine/source/sfx/openal/sfxALBuffer.cpp +++ b/Engine/source/sfx/openal/sfxALBuffer.cpp @@ -30,8 +30,7 @@ //#define DEBUG_SPEW -SFXALBuffer* SFXALBuffer::create( const OPENALFNTABLE &oalft, - const ThreadSafeRef< SFXStream >& stream, +SFXALBuffer* SFXALBuffer::create( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description, bool useHardware ) { @@ -41,27 +40,24 @@ SFXALBuffer* SFXALBuffer::create( const OPENALFNTABLE &oalft, return NULL; } - SFXALBuffer *buffer = new SFXALBuffer( oalft, - stream, + SFXALBuffer *buffer = new SFXALBuffer( stream, description, useHardware ); return buffer; } -SFXALBuffer::SFXALBuffer( const OPENALFNTABLE &oalft, - const ThreadSafeRef< SFXStream >& stream, +SFXALBuffer::SFXALBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description, bool useHardware ) : Parent( stream, description ), mIs3d( description->mIs3D ), - mUseHardware( useHardware ), - mOpenAL( oalft ) + mUseHardware( useHardware ) { // Set up device buffers. if( !isStreaming() ) - mOpenAL.alGenBuffers( 1, &mALBuffer ); + alGenBuffers( 1, &mALBuffer ); } SFXALBuffer::~SFXALBuffer() @@ -70,13 +66,13 @@ SFXALBuffer::~SFXALBuffer() _getUniqueVoice()->stop(); // Release buffers. - if ( mOpenAL.alIsBuffer( mALBuffer )) - mOpenAL.alDeleteBuffers( 1, &mALBuffer ); + if ( alIsBuffer( mALBuffer )) + alDeleteBuffers( 1, &mALBuffer ); while( mFreeBuffers.size() ) { ALuint buffer = mFreeBuffers.last(); - mOpenAL.alDeleteBuffers( 1, &buffer ); + alDeleteBuffers( 1, &buffer ); mFreeBuffers.pop_back(); } } @@ -98,7 +94,7 @@ void SFXALBuffer::write( SFXInternal::SFXStreamPacket* const* packets, U32 num ) ALenum alFormat = _sfxFormatToALFormat( getFormat() ); AssertFatal( alFormat != 0, "SFXALBuffer::write() - format unsupported" ); - mOpenAL.alBufferData( mALBuffer, alFormat, + alBufferData( mALBuffer, alFormat, packet->data, packet->mSizeActual, getFormat().getSamplesPerSecond() ); destructSingle( packet ); @@ -112,19 +108,19 @@ void SFXALBuffer::write( SFXInternal::SFXStreamPacket* const* packets, U32 num ) ALuint source = _getUniqueVoice()->mSourceName; ALint numProcessed; - mOpenAL.alGetSourcei( source, AL_BUFFERS_PROCESSED, &numProcessed ); + alGetSourcei( source, AL_BUFFERS_PROCESSED, &numProcessed ); for( U32 i = 0; i < numProcessed; ++ i ) { // Unqueue the buffer. ALuint buffer; - mOpenAL.alSourceUnqueueBuffers( source, 1, &buffer ); + alSourceUnqueueBuffers( source, 1, &buffer ); // Update the sample offset on the voice. ALint size; - mOpenAL.alGetBufferi( buffer, AL_SIZE, &size ); + alGetBufferi( buffer, AL_SIZE, &size ); _getUniqueVoice()->mSampleOffset += size / getFormat().getBytesPerSample(); // Push the buffer onto the freelist. @@ -147,22 +143,22 @@ void SFXALBuffer::write( SFXInternal::SFXStreamPacket* const* packets, U32 num ) mFreeBuffers.pop_back(); } else - mOpenAL.alGenBuffers( 1, &buffer ); + alGenBuffers( 1, &buffer ); // Upload the data. ALenum alFormat = _sfxFormatToALFormat( getFormat() ); AssertFatal( alFormat != 0, "SFXALBuffer::write() - format unsupported" ); - AssertFatal( mOpenAL.alIsBuffer( buffer ), "SFXALBuffer::write() - buffer invalid" ); + AssertFatal( alIsBuffer( buffer ), "SFXALBuffer::write() - buffer invalid" ); - mOpenAL.alBufferData( buffer, alFormat, + alBufferData( buffer, alFormat, packet->data, packet->mSizeActual, getFormat().getSamplesPerSecond() ); destructSingle( packet ); // Queue the buffer. - mOpenAL.alSourceQueueBuffers( source, 1, &buffer ); + alSourceQueueBuffers( source, 1, &buffer ); } } @@ -183,12 +179,12 @@ void SFXALBuffer::_flush() ALuint source = _getUniqueVoice()->mSourceName; ALint numQueued; - mOpenAL.alGetSourcei( source, AL_BUFFERS_QUEUED, &numQueued ); + alGetSourcei( source, AL_BUFFERS_QUEUED, &numQueued ); for( U32 i = 0; i < numQueued; ++ i ) { ALuint buffer; - mOpenAL.alSourceUnqueueBuffers( source, 1, &buffer ); + alSourceUnqueueBuffers( source, 1, &buffer ); mFreeBuffers.push_back( buffer ); } @@ -203,20 +199,20 @@ void SFXALBuffer::_flush() // issues any concurrent state changes on the voice resulting in us losing state here. ALuint newSource; - mOpenAL.alGenSources( 1, &newSource ); + alGenSources( 1, &newSource ); #define COPY_F( name ) \ { \ F32 val; \ - mOpenAL.alGetSourcef( source, name, &val ); \ - mOpenAL.alSourcef( source, name, val ); \ + alGetSourcef( source, name, &val ); \ + alSourcef( source, name, val ); \ } #define COPY_FV( name ) \ { \ VectorF val; \ - mOpenAL.alGetSourcefv( source, name, val ); \ - mOpenAL.alSourcefv( source, name, val ); \ + alGetSourcefv( source, name, val ); \ + alSourcefv( source, name, val ); \ } COPY_F( AL_REFERENCE_DISTANCE ); @@ -232,7 +228,7 @@ void SFXALBuffer::_flush() COPY_FV( AL_DIRECTION ); _getUniqueVoice()->mSourceName = newSource; - mOpenAL.alDeleteSources( 1, &source ); + alDeleteSources( 1, &source ); #endif } diff --git a/Engine/source/sfx/openal/sfxALBuffer.h b/Engine/source/sfx/openal/sfxALBuffer.h index 26864a3d0..609add4f1 100644 --- a/Engine/source/sfx/openal/sfxALBuffer.h +++ b/Engine/source/sfx/openal/sfxALBuffer.h @@ -24,13 +24,13 @@ #define _SFXALBUFFER_H_ #ifndef _LOADOAL_H - #include "sfx/openal/LoadOAL.h" +#include "sfx/openal/LoadOAL.h" #endif #ifndef _SFXINTERNAL_H_ - #include "sfx/sfxInternal.h" +#include "sfx/sfxInternal.h" #endif #ifndef _TVECTOR_H_ - #include "core/util/tVector.h" +#include "core/util/tVector.h" #endif @@ -39,81 +39,95 @@ class SFXALVoice; class SFXALBuffer : public SFXBuffer { - public: +public: - typedef SFXBuffer Parent; + typedef SFXBuffer Parent; - friend class SFXALDevice; - friend class SFXALVoice; + friend class SFXALDevice; + friend class SFXALVoice; - protected: - - /// AL buffer in case this is a static, non-streaming buffer. - ALuint mALBuffer; - - /// Free buffers for use in queuing in case this is a streaming buffer. - Vector< ALuint > mFreeBuffers; +protected: - /// - SFXALBuffer( const OPENALFNTABLE &oalft, - const ThreadSafeRef< SFXStream >& stream, - SFXDescription* description, - bool useHardware ); + /// AL buffer in case this is a static, non-streaming buffer. + ALuint mALBuffer; - /// - bool mIs3d; + /// Free buffers for use in queuing in case this is a streaming buffer. + Vector< ALuint > mFreeBuffers; - /// - bool mUseHardware; + /// + SFXALBuffer(const ThreadSafeRef< SFXStream >& stream, + SFXDescription* description, + bool useHardware); - const OPENALFNTABLE &mOpenAL; + /// + bool mIs3d; - /// - ALenum _getALFormat() const + /// + bool mUseHardware; + /// + ALenum _getALFormat() const + { + return _sfxFormatToALFormat(getFormat()); + } + + /// + static ALenum _sfxFormatToALFormat(const SFXFormat& format) + { + const U32 channels = format.getChannels(); + const SFXSampleType type = format.getSampleType(); + + switch (type) { - return _sfxFormatToALFormat( getFormat() ); + case Sample_Int8: + if (channels == 1) return AL_FORMAT_MONO8; + if (channels == 2) return AL_FORMAT_STEREO8; + break; + + case Sample_Int16: + if (channels == 1) return AL_FORMAT_MONO16; + if (channels == 2) return AL_FORMAT_STEREO16; + break; + + case Sample_Float: + if (channels == 1) return AL_FORMAT_MONO_FLOAT32; + if (channels == 2) return AL_FORMAT_STEREO_FLOAT32; + break; + + case Sample_IMA4: + if (channels == 1) return AL_FORMAT_MONO_IMA4; + if (channels == 2) return AL_FORMAT_STEREO_IMA4; + break; + + case Sample_MSADPCM: + // Requires OpenAL Soft MSADPCM extension + if (channels == 1) return AL_FORMAT_MONO_MSADPCM_SOFT; + if (channels == 2) return AL_FORMAT_STEREO_MSADPCM_SOFT; + break; } - /// - static ALenum _sfxFormatToALFormat( const SFXFormat& format ) - { - if( format.getChannels() == 2 ) - { - const U32 bps = format.getBitsPerSample(); - if( bps == 16 ) - return AL_FORMAT_STEREO8; - else if( bps == 32 ) - return AL_FORMAT_STEREO16; - } - else if( format.getChannels() == 1 ) - { - const U32 bps = format.getBitsPerSample(); - if( bps == 8 ) - return AL_FORMAT_MONO8; - else if( bps == 16 ) - return AL_FORMAT_MONO16; - } - return 0; - } + // Unsupported channel count or layout + Con::errorf("_sfxFormatToALFormat - Unsupported format: channels=%d, type=%d", + channels, type); + return 0; + } - /// - SFXALVoice* _getUniqueVoice() const - { - return ( SFXALVoice* ) mUniqueVoice.getPointer(); - } + /// + SFXALVoice* _getUniqueVoice() const + { + return (SFXALVoice*)mUniqueVoice.getPointer(); + } - // SFXBuffer. - void write( SFXInternal::SFXStreamPacket* const* packets, U32 num ) override; - void _flush() override; + // SFXBuffer. + void write(SFXInternal::SFXStreamPacket* const* packets, U32 num) override; + void _flush() override; - public: +public: - static SFXALBuffer* create( const OPENALFNTABLE &oalft, - const ThreadSafeRef< SFXStream >& stream, - SFXDescription* description, - bool useHardware ); + static SFXALBuffer* create(const ThreadSafeRef< SFXStream >& stream, + SFXDescription* description, + bool useHardware); - virtual ~SFXALBuffer(); + virtual ~SFXALBuffer(); }; -#endif // _SFXALBUFFER_H_ \ No newline at end of file +#endif // _SFXALBUFFER_H_ diff --git a/Engine/source/sfx/openal/sfxALDevice.cpp b/Engine/source/sfx/openal/sfxALDevice.cpp index 765cb01ff..36372a58f 100644 --- a/Engine/source/sfx/openal/sfxALDevice.cpp +++ b/Engine/source/sfx/openal/sfxALDevice.cpp @@ -24,50 +24,411 @@ #include "sfx/openal/sfxALBuffer.h" #include "platform/async/asyncUpdate.h" +#include "AL/al.h" +#include "AL/alc.h" +#include "AL/efx.h" +#include "AL/alext.h" + +#ifndef ALC_CONNECTED +#define ALC_CONNECTED 0x313 +#endif + +#ifndef ALC_DEVICE_CLOCK_SOFT +#define ALC_DEVICE_CLOCK_SOFT 0x1600 +#endif + +#ifndef ALC_DEVICE_LATENCY_SOFT +#define ALC_DEVICE_LATENCY_SOFT 0x1601 +#endif + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define FUNCTION_CAST(T, ptr) (union{void *p; T f;}){ptr}.f +#elif defined(__cplusplus) +#define FUNCTION_CAST(T, ptr) reinterpret_cast(ptr) +#else +#define FUNCTION_CAST(T, ptr) (T)(ptr) +#endif + +#define SFX_LOAD_AL_PROC(T, x) \ + (x) = FUNCTION_CAST(T, alGetProcAddress(#x)); \ + if (!(x)) Con::warnf("SFXALDevice - Failed to load " #x); + +#define SFX_LOAD_ALC_PROC(T, x) \ + (x) = FUNCTION_CAST(T, alcGetProcAddress(mDevice, #x)); \ + if (!(x)) Con::warnf("SFXALDevice - Failed to load " #x); + +/* Effect object functions */ +static LPALGENFILTERS alGenFilters{ nullptr }; +static LPALDELETEFILTERS alDeleteFilters{ nullptr }; +static LPALISFILTER alIsFilter{ nullptr }; +static LPALFILTERF alFilterf{ nullptr }; +static LPALFILTERFV alFilterfv{ nullptr }; +static LPALFILTERI alFilteri{ nullptr }; +static LPALFILTERIV alFilteriv{ nullptr }; +static LPALGETFILTERF alGetFilterf{ nullptr }; +static LPALGETFILTERFV alGetFilterfv{ nullptr }; +static LPALGETFILTERI alGetFilteri{ nullptr }; +static LPALGETFILTERIV alGetFilteriv{ nullptr }; +static LPALGENEFFECTS alGenEffects{ nullptr }; +static LPALDELETEEFFECTS alDeleteEffects{ nullptr }; +static LPALISEFFECT alIsEffect{ nullptr }; +static LPALEFFECTF alEffectf{ nullptr }; +static LPALEFFECTFV alEffectfv{ nullptr }; +static LPALEFFECTI alEffecti{ nullptr }; +static LPALEFFECTIV alEffectiv{ nullptr }; +static LPALGETEFFECTF alGetEffectf{ nullptr }; +static LPALGETEFFECTFV alGetEffectfv{ nullptr }; +static LPALGETEFFECTI alGetEffecti{ nullptr }; +static LPALGETEFFECTIV alGetEffectiv{ nullptr }; +static LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots{ nullptr }; +static LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots{ nullptr }; +static LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot{ nullptr }; +static LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf{ nullptr }; +static LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv{ nullptr }; +static LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti{ nullptr }; +static LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv{ nullptr }; +static LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf{ nullptr }; +static LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv{ nullptr }; +static LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti{ nullptr }; +static LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv{ nullptr }; +static LPALCGETSTRINGISOFT alcGetStringiSOFT{ nullptr }; +static LPALCRESETDEVICESOFT alcResetDeviceSOFT{ nullptr }; +static LPALCREOPENDEVICESOFT alcReopenDeviceSOFT{ nullptr }; +static LPALCGETINTEGER64VSOFT alcGetInteger64vSOFT{ nullptr }; + +class SFXALRegisterProvider +{ +public: + SFXALRegisterProvider() + { + SFXSystem::getRegisterProviderSignal().notify(&SFXALDevice::enumerateProviders); + } +}; + +static SFXALRegisterProvider pSFXALRegisterProvider; + +SFXProvider::CreateProviderInstanceDelegate SFXALDevice::mCreateDeviceInstance(SFXALDevice::createInstance); + +SFXDevice* SFXALDevice::createInstance(U32 providerIndex) +{ + SFXALDevice* dev = new SFXALDevice(providerIndex); + return dev; +} + +void SFXALDevice::_initExtensions() +{ + // Device-level soft extensions — must be loaded before context creation + if (alcIsExtensionPresent(mDevice, "ALC_SOFT_reopen_device")) + { + SFX_LOAD_ALC_PROC(LPALCREOPENDEVICESOFT, alcReopenDeviceSOFT); + SFX_LOAD_ALC_PROC(LPALCRESETDEVICESOFT, alcResetDeviceSOFT); + if (alcReopenDeviceSOFT && alcResetDeviceSOFT) + { + mHasSoftReopen = true; + mCaps |= CAPS_HotReconnect; + } + } + + if (alcIsExtensionPresent(mDevice, "ALC_SOFT_HRTF")) + { + SFX_LOAD_ALC_PROC(LPALCGETSTRINGISOFT, alcGetStringiSOFT); + if (alcGetStringiSOFT) + { + mHasSoftHRTF = true; + mCaps |= CAPS_HRTF; + } + } + + if (alcIsExtensionPresent(mDevice, "ALC_SOFT_device_clock")) + { + SFX_LOAD_ALC_PROC(LPALCGETINTEGER64VSOFT, alcGetInteger64vSOFT); + if (alcGetInteger64vSOFT) + mCaps |= CAPS_DeviceClock; + } + + if (alcIsExtensionPresent(mDevice, "ALC_EXT_disconnect")) + mCaps |= CAPS_DisconnectDetect; + + // Context-level AL extensions — loaded after context is current + if (alIsExtensionPresent("AL_EXT_float32")) + mCaps |= CAPS_Float32; + if (alIsExtensionPresent("AL_EXT_MCFORMATS")) + mCaps |= CAPS_MonoStereo; + if (alIsExtensionPresent("AL_SOFT_source_spatialize")) + mCaps |= CAPS_SourceSpatialize; +} + +void SFXALDevice::_initEFX() +{ + if (alcIsExtensionPresent(mDevice, "ALC_EXT_EFX") != AL_TRUE) + return; + + // Load all EFX procs + SFX_LOAD_AL_PROC(LPALGENEFFECTS, alGenEffects); + SFX_LOAD_AL_PROC(LPALDELETEEFFECTS, alDeleteEffects); + SFX_LOAD_AL_PROC(LPALISEFFECT, alIsEffect); + SFX_LOAD_AL_PROC(LPALEFFECTI, alEffecti); + SFX_LOAD_AL_PROC(LPALEFFECTIV, alEffectiv); + SFX_LOAD_AL_PROC(LPALEFFECTF, alEffectf); + SFX_LOAD_AL_PROC(LPALEFFECTFV, alEffectfv); + SFX_LOAD_AL_PROC(LPALGETEFFECTI, alGetEffecti); + SFX_LOAD_AL_PROC(LPALGETEFFECTIV, alGetEffectiv); + SFX_LOAD_AL_PROC(LPALGETEFFECTF, alGetEffectf); + SFX_LOAD_AL_PROC(LPALGETEFFECTFV, alGetEffectfv); + SFX_LOAD_AL_PROC(LPALGENAUXILIARYEFFECTSLOTS, alGenAuxiliaryEffectSlots); + SFX_LOAD_AL_PROC(LPALDELETEAUXILIARYEFFECTSLOTS, alDeleteAuxiliaryEffectSlots); + SFX_LOAD_AL_PROC(LPALISAUXILIARYEFFECTSLOT, alIsAuxiliaryEffectSlot); + SFX_LOAD_AL_PROC(LPALAUXILIARYEFFECTSLOTI, alAuxiliaryEffectSloti); + SFX_LOAD_AL_PROC(LPALAUXILIARYEFFECTSLOTIV, alAuxiliaryEffectSlotiv); + SFX_LOAD_AL_PROC(LPALAUXILIARYEFFECTSLOTF, alAuxiliaryEffectSlotf); + SFX_LOAD_AL_PROC(LPALAUXILIARYEFFECTSLOTFV, alAuxiliaryEffectSlotfv); + SFX_LOAD_AL_PROC(LPALGETAUXILIARYEFFECTSLOTI, alGetAuxiliaryEffectSloti); + SFX_LOAD_AL_PROC(LPALGETAUXILIARYEFFECTSLOTIV, alGetAuxiliaryEffectSlotiv); + SFX_LOAD_AL_PROC(LPALGETAUXILIARYEFFECTSLOTF, alGetAuxiliaryEffectSlotf); + SFX_LOAD_AL_PROC(LPALGETAUXILIARYEFFECTSLOTFV, alGetAuxiliaryEffectSlotfv); + SFX_LOAD_AL_PROC(LPALGENFILTERS, alGenFilters); + SFX_LOAD_AL_PROC(LPALDELETEFILTERS, alDeleteFilters); + SFX_LOAD_AL_PROC(LPALISFILTER, alIsFilter); + SFX_LOAD_AL_PROC(LPALFILTERI, alFilteri); + SFX_LOAD_AL_PROC(LPALFILTERIV, alFilteriv); + SFX_LOAD_AL_PROC(LPALFILTERF, alFilterf); + SFX_LOAD_AL_PROC(LPALFILTERFV, alFilterfv); + SFX_LOAD_AL_PROC(LPALGETFILTERI, alGetFilteri); + SFX_LOAD_AL_PROC(LPALGETFILTERIV, alGetFilteriv); + SFX_LOAD_AL_PROC(LPALGETFILTERF, alGetFilterf); + SFX_LOAD_AL_PROC(LPALGETFILTERFV, alGetFilterfv); + + // Verify the minimum set we can't live without + if (!alGenEffects || !alDeleteEffects || + !alGenAuxiliaryEffectSlots || !alDeleteAuxiliaryEffectSlots || + !alAuxiliaryEffectSloti) + { + Con::warnf("SFXALDevice - EFX proc loading incomplete, disabling reverb"); + return; + } + + mCaps |= CAPS_Reverb | CAPS_Occlusion; + + // Filters require their own procs + if (alGenFilters && alDeleteFilters && alFilteri && alFilterf) + mCaps |= CAPS_SourceFilters; + + // Probe individual effect type support and slot count + _probeEFXEffectCaps(); +} + +void SFXALDevice::_probeEFXEffectCaps() +{ + // Probe which effect types this driver actually supports + // by attempting to set each type on a temporary effect object. + // Some drivers report ALC_EXT_EFX but don't implement all types. + + struct EffectProbe { ALenum alType; U32 cap; const char* name; }; + static const EffectProbe probes[] = + { + { AL_EFFECT_EAXREVERB, CAPS_Reverb | CAPS_EXTReverb, "EAX Reverb" }, + { AL_EFFECT_REVERB, CAPS_Reverb, "EAXReverb" }, + { AL_EFFECT_EQUALIZER, CAPS_EFX_EQ, "Equalizer" }, + { AL_EFFECT_COMPRESSOR, CAPS_EFX_Compressor,"Compressor" }, + { AL_EFFECT_ECHO, CAPS_EFX_Echo, "Echo" }, + { AL_EFFECT_CHORUS, CAPS_EFX_Chorus, "Chorus" }, + { AL_EFFECT_DISTORTION, CAPS_EFX_Distortion,"Distortion" }, + { AL_EFFECT_FLANGER, CAPS_EFX_Flanger, "Flanger" }, + }; + + ALuint testEffect = 0; + alGenEffects(1, &testEffect); + + for (const EffectProbe& probe : probes) + { + alGetError(); + alEffecti(testEffect, AL_EFFECT_TYPE, probe.alType); + if (alGetError() == AL_NO_ERROR) + mCaps |= probe.cap; + } + + alDeleteEffects(1, &testEffect); + alGetError(); + + // Probe aux slot count + Vector slots; + alGetError(); + while (slots.size() < 64) + { + ALuint slot = 0; + alGenAuxiliaryEffectSlots(1, &slot); + if (alGetError() != AL_NO_ERROR) + break; + slots.push_back(slot); + } + + Con::setIntVariable("$pref::SFX::maxEffectSlots", (S32)slots.size()); + + ALCint sends = 0; + alcGetIntegerv(mDevice, ALC_MAX_AUXILIARY_SENDS, 1, &sends); + Con::setIntVariable("$pref::SFX::maxSendsPerSource", (S32)sends); + + for (ALuint slot : slots) + alDeleteAuxiliaryEffectSlots(1, &slot); + alGetError(); + + // Allocate the device-level global reverb slot + alGenAuxiliaryEffectSlots(1, &mAuxSlot); + if (alGetError() != AL_NO_ERROR) + { + Con::warnf("SFXALDevice - Failed to create primary EFX slot"); + mCaps &= ~(CAPS_Reverb | CAPS_Occlusion); + mAuxSlot = 0; + } +} + //---------------------------------------------------------------------------- // STATIC OPENAL FUNCTIONS //---------------------------------------------------------------------------- void SFXALDevice::printALInfo(ALCdevice* device) { + if (!device) + return; + + Con::printBlankLine(); + Con::printf("SFX Device Info:"); + Con::printf("|------------------------------------------------"); + + // --- Device name --- + const ALCchar* devname = alcIsExtensionPresent(device, "ALC_ENUMERATE_ALL_EXT") + ? alcGetString(device, ALC_ALL_DEVICES_SPECIFIER) + : alcGetString(device, ALC_DEVICE_SPECIFIER); + Con::printf("| Device: %s", devname); + + // --- OpenAL version --- ALCint major, minor; - if (device) + alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major); + alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor); + Con::printf("| OpenAL: %d.%d", major, minor); + + // --- Audio format --- + ALCint freq = 0; + alcGetIntegerv(device, ALC_FREQUENCY, 1, &freq); + Con::printf("| Sample Rate: %d Hz", freq > 0 ? freq : 44100); + Con::printf("| Bit Depth: %d-bit", (mCaps & CAPS_Float32) ? 32 : 16); + Con::printf("| Max Voices: %d", mMaxBuffers); + + Con::printf("|------------------------------------------------"); + Con::printf("| Capabilities:"); + + // --- Hot reconnect --- + Con::printf("| Hot Reconnect: %s", (mCaps & CAPS_HotReconnect) ? "Yes" : "No"); + Con::printf("| Disconnect Detect: %s", (mCaps & CAPS_DisconnectDetect) ? "Yes" : "No"); + Con::printf("| Device Clock: %s", (mCaps & CAPS_DeviceClock) ? "Yes" : "No"); + Con::printf("| Multi-Listener: %s", (mCaps & CAPS_MultiListener) ? "Yes" : "No"); + Con::printf("| Float32 Playback: %s", (mCaps & CAPS_Float32) ? "Yes" : "No"); + Con::printf("| Multi-Channel: %s", (mCaps & CAPS_MonoStereo) ? "Yes" : "No"); + Con::printf("| Spatialize: %s", (mCaps & CAPS_SourceSpatialize) ? "Yes" : "No"); + + // --- HRTF --- + Con::printf("| HRTF: %s", (mCaps & CAPS_HRTF) ? "Yes" : "No"); + if (mCaps & CAPS_HRTF) { - const ALCchar* devname = NULL; - Con::printBlankLine(); + ALCint hrtfStatus = 0; + alcGetIntegerv(device, ALC_HRTF_STATUS_SOFT, 1, &hrtfStatus); - if (mOpenAL.alcIsExtensionPresent(device, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE) + const char* statusStr = "Unknown"; + switch (hrtfStatus) { - devname = mOpenAL.alcGetString(device, ALC_ALL_DEVICES_SPECIFIER); - } - else - { - devname = mOpenAL.alcGetString(device, ALC_DEVICE_SPECIFIER); + case ALC_HRTF_DISABLED_SOFT: statusStr = "Disabled"; break; + case ALC_HRTF_ENABLED_SOFT: statusStr = "Enabled"; break; + case ALC_HRTF_DENIED_SOFT: statusStr = "Denied by device"; break; + case ALC_HRTF_REQUIRED_SOFT: statusStr = "Required by device"; break; + case ALC_HRTF_HEADPHONES_DETECTED_SOFT: statusStr = "Headphones detected"; break; + case ALC_HRTF_UNSUPPORTED_FORMAT_SOFT: statusStr = "Unsupported format"; break; } + Con::printf("| Status: %s", statusStr); - Con::printf("| Device info for: %s ", devname); + ALCint profileCount = 0; + alcGetIntegerv(device, ALC_NUM_HRTF_SPECIFIERS_SOFT, 1, &profileCount); + Con::printf("| Profiles: %d", profileCount); + + if (alcGetStringiSOFT && profileCount > 0) + for (ALCint i = 0; i < profileCount; i++) + Con::printf("| [%d] %s", i, + alcGetStringiSOFT(device, ALC_HRTF_SPECIFIER_SOFT, i)); + + bool use_hrtf = Con::getBoolVariable("$pref::SFX::useHRTF"); + if (use_hrtf && (mCaps & CAPS_HotReconnect)) + { + ALCint attr[5]; + ALCint index = Con::getIntVariable("$pref::SFX::hrtfProfile"); + ALCint i; + + i = 0; + attr[i++] = ALC_HRTF_SOFT; + attr[i++] = ALC_TRUE; + // load the default device hrtf. + if (index >= 0 && index < profileCount) + { + attr[i++] = ALC_HRTF_ID_SOFT; + attr[i++] = index; + } + attr[i] = 0; + + if (!alcResetDeviceSOFT(mDevice, attr)) + { + Con::printf("Failed to reset device: %s", alcGetString(mDevice, alcGetError(mDevice))); + } + } } - mOpenAL.alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major); - mOpenAL.alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor); - Con::printf("| OpenAL Version: %d.%d", major, minor); - - if (device) + // --- EFX --- + Con::printf("| EFX Reverb: %s", (mCaps & CAPS_Reverb) ? "Yes" : "No"); + if (mCaps & CAPS_Reverb) { - Con::printf("%s", mOpenAL.alcGetString(device, ALC_EXTENSIONS)); + Con::printf("| EQ: %s", (mCaps & CAPS_EFX_EQ) ? "Yes" : "No"); + Con::printf("| Compressor: %s", (mCaps & CAPS_EFX_Compressor) ? "Yes" : "No"); + Con::printf("| Echo: %s", (mCaps & CAPS_EFX_Echo) ? "Yes" : "No"); + Con::printf("| Chorus: %s", (mCaps & CAPS_EFX_Chorus) ? "Yes" : "No"); + Con::printf("| Distortion: %s", (mCaps & CAPS_EFX_Distortion) ? "Yes" : "No"); + Con::printf("| Flanger: %s", (mCaps & CAPS_EFX_Flanger) ? "Yes" : "No"); + Con::printf("| Filters: %s", (mCaps & CAPS_SourceFilters) ? "Yes" : "No"); - U32 err = mOpenAL.alcGetError(device); - if (err != ALC_NO_ERROR) - Con::errorf("SFXALDevice - Error Retrieving ALC Extensions: %s", mOpenAL.alcGetString(device, err)); + Con::printf("| Effect Slots: %d", + Con::getIntVariable("$pref::SFX::maxEffectSlots")); + Con::printf("| Sends/Source: %d", + Con::getIntVariable("$pref::SFX::maxSendsPerSource")); } + + Con::printf("|------------------------------------------------"); + + // --- Full extension list last so it doesn't bury the important info --- + const ALchar* extStr = alcGetString(device, ALC_EXTENSIONS); + if (extStr) + { + Con::printf("| ALC Extensions:"); + char* extCopy = dStrdup(extStr); + char* token = dStrtok(extCopy, " "); + while (token) + { + Con::printf("| %s", token); + token = dStrtok(NULL, " "); + } + dFree(extCopy); + } + + Con::printf("|------------------------------------------------"); + Con::printBlankLine(); + + U32 err = alcGetError(device); + if (err != ALC_NO_ERROR) + Con::errorf("SFXALDevice - ALC error after info query: %s", + alcGetString(device, err)); } S32 SFXALDevice::getMaxSources() { - mOpenAL.alGetError(); + alGetError(); ALCint nummono; - mOpenAL.alcGetIntegerv(mDevice, ALC_MONO_SOURCES, 1, &nummono); + alcGetIntegerv(mDevice, ALC_MONO_SOURCES, 1, &nummono); if(nummono == 0) nummono = getMaxSourcesOld(); @@ -81,21 +442,21 @@ S32 SFXALDevice::getMaxSourcesOld() S32 sourceCount = 0; // clear errors. - mOpenAL.alGetError(); + alGetError(); for(sourceCount = 0; sourceCount < 256; sourceCount++) { - mOpenAL.alGenSources(1,&uiSource[sourceCount]); - if(mOpenAL.alGetError() != AL_NO_ERROR) + alGenSources(1,&uiSource[sourceCount]); + if(alGetError() != AL_NO_ERROR) break; } - mOpenAL.alDeleteSources(sourceCount, uiSource); - if(mOpenAL.alGetError() != AL_NO_ERROR) + alDeleteSources(sourceCount, uiSource); + if(alGetError() != AL_NO_ERROR) { for(U32 i = 0; i < 256; i++) { - mOpenAL.alDeleteSources(1,&uiSource[i]); + alDeleteSources(1,&uiSource[i]); } } @@ -103,85 +464,69 @@ S32 SFXALDevice::getMaxSourcesOld() } -//----------------------------------------------------------------------------- - -SFXALDevice::SFXALDevice( SFXProvider *provider, - const OPENALFNTABLE &openal, - String name, - bool useHardware, - S32 maxBuffers ) - : Parent( name, provider, useHardware, maxBuffers ), - mOpenAL( openal ), - mContext( NULL ), - mDevice( NULL ), +SFXALDevice::SFXALDevice(U32 providerIndex) + : mContext(NULL), + mDevice(NULL), mDistanceModel(SFXDistanceModelLinear), mDistanceFactor(1.0f), - mRolloffFactor( 1.0f ), - mUserRolloffFactor(1.0f) + mRolloffFactor(1.0f), + mUserRolloffFactor(1.0f), + mHasEFX(false), + mHasSoftReopen(false), + mHasSoftHRTF(false), + mEffect(0), + mAuxSlot(0) { - mMaxBuffers = getMax( maxBuffers, 8 ); + SFXProvider* p = SFXSystem::getProvider(providerIndex); - // TODO: The OpenAL device doesn't set the primary buffer - // $pref::SFX::frequency or $pref::SFX::bitrate! - //check auxiliary device sends 4 and add them to the device - ALint attribs[4] = { 0 }; -#if defined(AL_ALEXT_PROTOTYPES) - ALCint iSends = 0; - attribs[0] = ALC_MAX_AUXILIARY_SENDS; -#endif - attribs[1] = 4; - - printALInfo(NULL); - - mDevice = mOpenAL.alcOpenDevice( name ); - U32 err = mOpenAL.alcGetError(mDevice); - if (err != ALC_NO_ERROR) - Con::errorf("SFXALDevice - Device Initialization Error: %s", mOpenAL.alcGetString(mDevice, err)); - - if( mDevice ) + mDevice = alcOpenDevice(p->getName()); + if (!mDevice) { - mContext = mOpenAL.alcCreateContext( mDevice, attribs ); - - if( mContext ) - mOpenAL.alcMakeContextCurrent( mContext ); - -#if defined(AL_ALEXT_PROTOTYPES) - mOpenAL.alcGetIntegerv(mDevice, ALC_MAX_AUXILIARY_SENDS, 1, &iSends); -#endif - err = mOpenAL.alcGetError( mDevice ); - - if( err != ALC_NO_ERROR ) - Con::errorf( "SFXALDevice - Context Initialization Error: %s", mOpenAL.alcGetString( mDevice, err ) ); + Con::errorf("SFXALDevice - Failed to open '%s'", p->getName()); + return; } - AssertFatal( mDevice != NULL && mContext != NULL, "Failed to create OpenAL device and/or context!" ); + // Extensions that must be loaded before context creation + _initExtensions(); - // Start the update thread. - // TODO AsyncPeriodicUpdateThread support for Linux/Mac -#ifdef TORQUE_OS_WIN - if( !Con::getBoolVariable( "$_forceAllMainThread" ) ) + mContext = alcCreateContext(mDevice, NULL); + if (!mContext) { - SFXInternal::gUpdateThread = new AsyncPeriodicUpdateThread - ( "OpenAL Update Thread", SFXInternal::gBufferUpdateList, - Con::getIntVariable( "$pref::SFX::updateInterval", SFXInternal::DEFAULT_UPDATE_INTERVAL ) ); + Con::errorf("SFXALDevice - Failed to create context (error %d)", + alcGetError(mDevice)); + alcCloseDevice(mDevice); + mDevice = NULL; + return; + } + + alcMakeContextCurrent(mContext); + +#ifdef TORQUE_OS_WIN + + if (!Con::getBoolVariable("$_forceAllMainThread")) + { + SFXInternal::gUpdateThread = new AsyncPeriodicUpdateThread( + "OpenAL Update Thread", SFXInternal::gBufferUpdateList, + Con::getIntVariable("$pref::SFX::updateInterval", + SFXInternal::DEFAULT_UPDATE_INTERVAL)); SFXInternal::gUpdateThread->start(); } #endif -#if defined(AL_ALEXT_PROTOTYPES) - dMemset(effectSlot, 0, sizeof(effectSlot)); - dMemset(effect, 0, sizeof(effect)); - uLoop = 0; -#endif + // Context is current — load context-level extensions and EFX + _initExtensions(); // second pass picks up AL_* extensions now context is current + _initEFX(); + + // Read back what the device actually settled on + ALCint freq = 0; + alcGetIntegerv(mDevice, ALC_FREQUENCY, 1, &freq); + Con::setIntVariable("$pref::SFX::frequency", freq > 0 ? freq : 44100); + Con::setIntVariable("$pref::SFX::bitrate", (mCaps & CAPS_Float32) ? 32 : 16); printALInfo(mDevice); - mMaxBuffers = getMaxSources(); - - // this should be max sources. - Con::printf("| Max Sources: %d", mMaxBuffers); - + Con::setIntVariable("$pref::SFX::maxSoftwareBuffers", mMaxBuffers); } //----------------------------------------------------------------------------- @@ -189,26 +534,66 @@ SFXALDevice::SFXALDevice( SFXProvider *provider, SFXALDevice::~SFXALDevice() { _releaseAllResources(); - ///cleanup our effects -#if defined(AL_ALEXT_PROTOTYPES) - mOpenAL.alDeleteAuxiliaryEffectSlots(4, effectSlot); - mOpenAL.alDeleteEffects(2, effect); -#endif + + if (alIsEffect(mEffect)) + { + alDeleteAuxiliaryEffectSlots(1, &mAuxSlot); + alDeleteEffects(1, &mEffect); + } + ///cleanup of effects ends - mOpenAL.alcMakeContextCurrent( NULL ); - mOpenAL.alcDestroyContext( mContext ); - mOpenAL.alcCloseDevice( mDevice ); + alcMakeContextCurrent( NULL ); + alcDestroyContext( mContext ); + alcCloseDevice( mDevice ); } //----------------------------------------------------------------------------- +void SFXALDevice::enumerateProviders(Vector& providerList) +{ + const ALCchar* devices; + U32 index = providerList.size(); + const ALCchar* defaultDeviceName; + + if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") == AL_TRUE) + { + devices = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); + defaultDeviceName = alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER); + } + else + { + devices = alcGetString(NULL, ALC_DEVICE_SPECIFIER); + defaultDeviceName = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); + } + + const ALCchar* currentDevice = devices; + + while (*currentDevice != '\0') + { + SFXProvider* toAdd = new SFXProvider; + toAdd->mName = String::ToString(currentDevice); + toAdd->mIndex = index; + toAdd->mDeviceType = Output; + toAdd->mType = OpenAL; + toAdd->mCreateDeviceInstanceDelegate = mCreateDeviceInstance; + + if (String::compare(currentDevice, defaultDeviceName) == 0) + toAdd->mDefault = true; + + currentDevice += dStrlen(currentDevice) + 1; + index++; + + providerList.push_back(toAdd); + } + +} + SFXBuffer* SFXALDevice::createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description ) { AssertFatal( stream, "SFXALDevice::createBuffer() - Got null stream!" ); AssertFatal( description, "SFXALDevice::createBuffer() - Got null description!" ); - SFXALBuffer* buffer = SFXALBuffer::create( mOpenAL, - stream, + SFXALBuffer* buffer = SFXALBuffer::create( stream, description, mUseHardware ); if ( !buffer ) @@ -258,14 +643,9 @@ void SFXALDevice::setListener( U32 index, const SFXListenerProperties& listener const VectorF &velocity = listener.getVelocity(); - mOpenAL.alListenerfv( AL_POSITION, pos ); - mOpenAL.alListenerfv( AL_VELOCITY, velocity ); - mOpenAL.alListenerfv( AL_ORIENTATION, (const F32 *)&tupple[0] ); - ///Pass a unit size to openal, 1.0 assumes 1 meter to 1 game unit. - ///Crucial for air absorbtion calculations. -#if defined(AL_ALEXT_PROTOTYPES) - mOpenAL.alListenerf(AL_METERS_PER_UNIT, 1.0f); -#endif + alListenerfv( AL_POSITION, pos ); + alListenerfv( AL_VELOCITY, velocity ); + alListenerfv( AL_ORIENTATION, (const F32 *)&tupple[0] ); } //----------------------------------------------------------------------------- @@ -275,19 +655,19 @@ void SFXALDevice::setDistanceModel( SFXDistanceModel model ) switch( model ) { case SFXDistanceModelLinear: - mOpenAL.alDistanceModel( AL_LINEAR_DISTANCE_CLAMPED ); + alDistanceModel( AL_LINEAR_DISTANCE_CLAMPED ); if( mRolloffFactor != 1.0f ) _setRolloffFactor( 1.0f ); // No rolloff on linear. break; case SFXDistanceModelLogarithmic: - mOpenAL.alDistanceModel( AL_INVERSE_DISTANCE_CLAMPED ); + alDistanceModel( AL_INVERSE_DISTANCE_CLAMPED ); if( mUserRolloffFactor != mRolloffFactor ) _setRolloffFactor( mUserRolloffFactor ); break; /// create a case for our exponential distance model case SFXDistanceModelExponent: - mOpenAL.alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED); + alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED); if (mUserRolloffFactor != mRolloffFactor) _setRolloffFactor(mUserRolloffFactor); break; @@ -301,19 +681,103 @@ void SFXALDevice::setDistanceModel( SFXDistanceModel model ) //----------------------------------------------------------------------------- -void SFXALDevice::setDopplerFactor( F32 factor ) +void SFXALDevice::setReverb(const SFXReverbProperties& r) { - mOpenAL.alDopplerFactor( factor ); + if (!(mCaps & CAPS_Reverb)) + return; + + /* Clear error state. */ + alGetError(); + + if (alIsEffect(mEffect)) + alDeleteEffects(1, &mEffect); + + /* Create the effect object and check if we can do EAX reverb. */ + alGenEffects(1, &mEffect); + + // Map your engine's properties to EFX parameters. + // Using EAX Reverb as an example: + if (mCaps & CAPS_EXTReverb) + { + // Full EAX parameter set — panning vectors, LF params, modulation etc. + alEffecti(mEffect, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB); + if (alGetError() == AL_NO_ERROR) + { + alEffectf(mEffect, AL_EAXREVERB_DENSITY, r.flDensity); + alEffectf(mEffect, AL_EAXREVERB_DIFFUSION, r.flDiffusion); + alEffectf(mEffect, AL_EAXREVERB_GAIN, r.flGain); + alEffectf(mEffect, AL_EAXREVERB_GAINHF, r.flGainHF); + alEffectf(mEffect, AL_EAXREVERB_GAINLF, r.flGainLF); + alEffectf(mEffect, AL_EAXREVERB_DECAY_TIME, r.flDecayTime); + alEffectf(mEffect, AL_EAXREVERB_DECAY_HFRATIO, r.flDecayHFRatio); + alEffectf(mEffect, AL_EAXREVERB_DECAY_LFRATIO, r.flDecayLFRatio); + + alEffectf(mEffect, AL_EAXREVERB_REFLECTIONS_GAIN, r.flReflectionsGain); + alEffectf(mEffect, AL_EAXREVERB_REFLECTIONS_DELAY, r.flReflectionsDelay); + alEffectfv(mEffect, AL_EAXREVERB_REFLECTIONS_PAN, r.flReflectionsPan); + + alEffectf(mEffect, AL_EAXREVERB_LATE_REVERB_GAIN, r.flLateReverbGain); + alEffectf(mEffect, AL_EAXREVERB_LATE_REVERB_DELAY, r.flLateReverbDelay); + alEffectfv(mEffect, AL_EAXREVERB_LATE_REVERB_PAN, r.flLateReverbPan); + + alEffectf(mEffect, AL_EAXREVERB_ECHO_TIME, r.flEchoTime); + alEffectf(mEffect, AL_EAXREVERB_ECHO_DEPTH, r.flEchoDepth); + alEffectf(mEffect, AL_EAXREVERB_MODULATION_TIME, r.flModulationTime); + alEffectf(mEffect, AL_EAXREVERB_MODULATION_DEPTH, r.flModulationDepth); + + alEffectf(mEffect, AL_EAXREVERB_AIR_ABSORPTION_GAINHF, r.flAirAbsorptionGainHF); + alEffectf(mEffect, AL_EAXREVERB_HFREFERENCE, r.flHFReference); + alEffectf(mEffect, AL_EAXREVERB_LFREFERENCE, r.flLFReference); + alEffectf(mEffect, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, r.flRoomRolloffFactor); + alEffecti(mEffect, AL_EAXREVERB_DECAY_HFLIMIT, r.iDecayHFLimit); + } + } + else + { + // Standard reverb — subset of EAX, no panning/LF/modulation params + alEffecti(mEffect, AL_EFFECT_TYPE, AL_EFFECT_REVERB); + if (alGetError() == AL_NO_ERROR) + { + alEffectf(mEffect, AL_REVERB_DENSITY, r.flDensity); + alEffectf(mEffect, AL_REVERB_DIFFUSION, r.flDiffusion); + alEffectf(mEffect, AL_REVERB_GAIN, r.flGain); + alEffectf(mEffect, AL_REVERB_GAINHF, r.flGainHF); + alEffectf(mEffect, AL_REVERB_DECAY_TIME, r.flDecayTime); + alEffectf(mEffect, AL_REVERB_DECAY_HFRATIO, r.flDecayHFRatio); + alEffectf(mEffect, AL_REVERB_REFLECTIONS_GAIN, r.flReflectionsGain); + alEffectf(mEffect, AL_REVERB_REFLECTIONS_DELAY, r.flReflectionsDelay); + alEffectf(mEffect, AL_REVERB_LATE_REVERB_GAIN, r.flLateReverbGain); + alEffectf(mEffect, AL_REVERB_LATE_REVERB_DELAY, r.flLateReverbDelay); + alEffectf(mEffect, AL_REVERB_AIR_ABSORPTION_GAINHF, r.flAirAbsorptionGainHF); + alEffectf(mEffect, AL_REVERB_ROOM_ROLLOFF_FACTOR, r.flRoomRolloffFactor); + alEffecti(mEffect, AL_REVERB_DECAY_HFLIMIT, r.iDecayHFLimit); + } + } + + if (alGetError() == AL_NO_ERROR) + alAuxiliaryEffectSloti(mAuxSlot, AL_EFFECTSLOT_EFFECT, (ALint)mEffect); + else + { + Con::warnf("SFXALDevice::setReverb - failed applying reverb parameters"); + if (alIsEffect(mEffect)) + alDeleteEffects(1, &mEffect); + mEffect = 0; + } } //----------------------------------------------------------------------------- +void SFXALDevice::setDopplerFactor( F32 factor ) +{ + alDopplerFactor( factor ); +} + void SFXALDevice::_setRolloffFactor( F32 factor ) { mRolloffFactor = factor; for( U32 i = 0, num = mVoices.size(); i < num; ++ i ) - mOpenAL.alSourcef( ( ( SFXALVoice* ) mVoices[ i ] )->mSourceName, AL_ROLLOFF_FACTOR, factor ); + alSourcef( ( ( SFXALVoice* ) mVoices[ i ] )->mSourceName, AL_ROLLOFF_FACTOR, factor ); } //----------------------------------------------------------------------------- @@ -328,110 +792,83 @@ void SFXALDevice::setRolloffFactor( F32 factor ) mUserRolloffFactor = factor; } -#if defined(AL_ALEXT_PROTOTYPES) -void SFXALDevice::openSlots() +void SFXALDevice::setSpeedOfSound(F32 speedOfSound) { - for (uLoop = 0; uLoop < 4; uLoop++) - { - mOpenAL.alGenAuxiliaryEffectSlots(1, &effectSlot[uLoop]); - } - - for (uLoop = 0; uLoop < 2; uLoop++) - { - mOpenAL.alGenEffects(1, &effect[uLoop]); - } - ///debug string output so we know our slots are open - Platform::outputDebugString("Slots Open"); + alSpeedOfSound(speedOfSound); } -///create reverb effect -void SFXALDevice::setReverb(const SFXReverbProperties& reverb) +bool SFXALDevice::isDeviceConnected() { - ///output a debug string so we know each time the reverb changes - Platform::outputDebugString("Updated"); + if (!mDevice) + return false; - ///load an efxeaxreverb default and add our values from - ///sfxreverbproperties to it - EFXEAXREVERBPROPERTIES prop = EFX_REVERB_PRESET_GENERIC; - - prop.flDensity = reverb.flDensity; - prop.flDiffusion = reverb.flDiffusion; - prop.flGain = reverb.flGain; - prop.flGainHF = reverb.flGainHF; - prop.flGainLF = reverb.flGainLF; - prop.flDecayTime = reverb.flDecayTime; - prop.flDecayHFRatio = reverb.flDecayHFRatio; - prop.flDecayLFRatio = reverb.flDecayLFRatio; - prop.flReflectionsGain = reverb.flReflectionsGain; - prop.flReflectionsDelay = reverb.flReflectionsDelay; - prop.flLateReverbGain = reverb.flLateReverbGain; - prop.flLateReverbDelay = reverb.flLateReverbDelay; - prop.flEchoTime = reverb.flEchoTime; - prop.flEchoDepth = reverb.flEchoDepth; - prop.flModulationTime = reverb.flModulationTime; - prop.flModulationDepth = reverb.flModulationDepth; - prop.flAirAbsorptionGainHF = reverb.flAirAbsorptionGainHF; - prop.flHFReference = reverb.flHFReference; - prop.flLFReference = reverb.flLFReference; - prop.flRoomRolloffFactor = reverb.flRoomRolloffFactor; - prop.iDecayHFLimit = reverb.iDecayHFLimit; - - if (mOpenAL.alGetEnumValue("AL_EFFECT_EAXREVERB") != 0) + // ALC_CONNECTED is a standard-ish extension, check it first + if (alcIsExtensionPresent(mDevice, "ALC_EXT_disconnect") == AL_TRUE) { + ALCint connected = ALC_FALSE; + alcGetIntegerv(mDevice, ALC_CONNECTED, 1, &connected); - /// EAX Reverb is available. Set the EAX effect type - - mOpenAL.alEffecti(effect[0], AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB); - - ///add our values to the setup of the reverb - - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_DENSITY, prop.flDensity); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_DIFFUSION, prop.flDiffusion); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_GAIN, prop.flGain); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_GAINHF, prop.flGainHF); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_GAINLF, prop.flGainLF); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_DECAY_TIME, prop.flDecayTime); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_DECAY_HFRATIO, prop.flDecayHFRatio); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_DECAY_LFRATIO, prop.flDecayLFRatio); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_REFLECTIONS_GAIN, prop.flReflectionsGain); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_REFLECTIONS_DELAY, prop.flReflectionsDelay); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_LATE_REVERB_GAIN, prop.flLateReverbGain); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_LATE_REVERB_DELAY, prop.flLateReverbDelay); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_ECHO_TIME, prop.flEchoTime); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_ECHO_DEPTH, prop.flEchoDepth); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_MODULATION_TIME, prop.flModulationTime); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_MODULATION_DEPTH, prop.flModulationDepth); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_AIR_ABSORPTION_GAINHF, prop.flAirAbsorptionGainHF); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_HFREFERENCE, prop.flHFReference); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_LFREFERENCE, prop.flLFReference); - mOpenAL.alEffectf(effect[0], AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, prop.flRoomRolloffFactor); - mOpenAL.alEffecti(effect[0], AL_EAXREVERB_DECAY_HFLIMIT, prop.iDecayHFLimit); - mOpenAL.alAuxiliaryEffectSloti(1, AL_EFFECTSLOT_EFFECT, effect[0]); - Platform::outputDebugString("eax reverb properties set"); - - } - else - { - - /// No EAX Reverb. Set the standard reverb effect - mOpenAL.alEffecti(effect[0], AL_EFFECT_TYPE, AL_EFFECT_REVERB); - - mOpenAL.alEffectf(effect[0], AL_REVERB_DENSITY, prop.flDensity); - mOpenAL.alEffectf(effect[0], AL_REVERB_DIFFUSION, prop.flDiffusion); - mOpenAL.alEffectf(effect[0], AL_REVERB_GAIN, prop.flGain); - mOpenAL.alEffectf(effect[0], AL_REVERB_GAINHF, prop.flGainHF); - mOpenAL.alEffectf(effect[0], AL_REVERB_DECAY_TIME, prop.flDecayTime); - mOpenAL.alEffectf(effect[0], AL_REVERB_DECAY_HFRATIO, prop.flDecayHFRatio); - mOpenAL.alEffectf(effect[0], AL_REVERB_REFLECTIONS_GAIN, prop.flReflectionsGain); - mOpenAL.alEffectf(effect[0], AL_REVERB_REFLECTIONS_DELAY, prop.flReflectionsDelay); - mOpenAL.alEffectf(effect[0], AL_REVERB_LATE_REVERB_GAIN, prop.flLateReverbGain); - mOpenAL.alEffectf(effect[0], AL_REVERB_LATE_REVERB_DELAY, prop.flLateReverbDelay); - mOpenAL.alEffectf(effect[0], AL_REVERB_AIR_ABSORPTION_GAINHF, prop.flAirAbsorptionGainHF); - mOpenAL.alEffectf(effect[0], AL_REVERB_ROOM_ROLLOFF_FACTOR, prop.flRoomRolloffFactor); - mOpenAL.alEffecti(effect[0], AL_REVERB_DECAY_HFLIMIT, prop.iDecayHFLimit); - mOpenAL.alAuxiliaryEffectSloti(1, AL_EFFECTSLOT_EFFECT, effect[0]); + if (connected == ALC_FALSE) + { + //SFXSystem::removeProvider(mDevice->getProvider()); + } + return (connected == ALC_TRUE); } + // If the extension isn't available, assume connected + return true; +} + +bool SFXALDevice::reconnectDevice(U32 providerIndex) +{ + if (!mDevice || !mContext) + { + Con::errorf("SFXALDevice::reconnectDevice - no active device/context to reconnect"); + return false; + } + + SFXProvider* p = SFXSystem::getProvider(providerIndex); + + // If no new name given, reuse the current device name (i.e. reconnect same device) + if (!p->getName() || p->getName()[0] == '\0') + { + Con::errorf("SFXALDevice::reconnectDevice - unsupported provider given."); + return false; + } + + Con::printf("SFXALDevice::reconnectDevice - reconnecting to '%s'", p->getName()); + + // Fast path: use ALC_SOFT_reopen_device to swap device without losing context. + // All sources/buffers remain valid, playback resumes automatically. + if (mHasSoftReopen && alcReopenDeviceSOFT) + { + // Build attribute list matching current device settings + ALCint attribs[] = + { + ALC_FREQUENCY, smDeviceFrequency, + ALC_MONO_SOURCES, mMaxBuffers, + 0 + }; + + if (alcReopenDeviceSOFT(mDevice, p->getName(), attribs) == ALC_TRUE) + { + Con::printf("SFXALDevice::reconnectDevice - soft reopen succeeded"); + return true; + } + + Con::warnf("SFXALDevice::reconnectDevice - soft reopen failed (error %d), " + "falling back to full recreate", alcGetError(mDevice)); + } + + // Slow path: destroy context and reopen device from scratch. + // SFXSystem::createDevice will handle transitioning sounds to virtual playback. + Con::printf("SFXALDevice::reconnectDevice - performing full device recreate"); + + alcMakeContextCurrent(NULL); + alcDestroyContext(mContext); + mContext = NULL; + alcCloseDevice(mDevice); + mDevice = NULL; + return false; } -#endif diff --git a/Engine/source/sfx/openal/sfxALDevice.h b/Engine/source/sfx/openal/sfxALDevice.h index 3d2bf5e78..5ccf3e270 100644 --- a/Engine/source/sfx/openal/sfxALDevice.h +++ b/Engine/source/sfx/openal/sfxALDevice.h @@ -23,8 +23,6 @@ #ifndef _SFXALDEVICE_H_ #define _SFXALDEVICE_H_ -class SFXProvider; - #ifndef _SFXDEVICE_H_ # include "sfx/sfxDevice.h" #endif @@ -45,65 +43,70 @@ class SFXProvider; # include "sfx/openal/LoadOAL.h" #endif +#ifndef _SFXSYSTEM_H_ +#include "sfx/sfxSystem.h" +#endif class SFXALDevice : public SFXDevice { - public: +private: + void _initExtensions(); + void _initEFX(); + void _probeEFXEffectCaps(); +public: - typedef SFXDevice Parent; - friend class SFXALVoice; // mDistanceFactor, mRolloffFactor + typedef SFXDevice Parent; + friend class SFXALVoice; // mDistanceFactor, mRolloffFactor - void printALInfo(ALCdevice* device); - void printHRTFInfo(ALCdevice* device); - void getEFXInfo(ALCdevice* device); - S32 getMaxSources(); + static SFXDevice* createInstance(U32 adapterIndex); + + void printALInfo(ALCdevice* device); + S32 getMaxSources(); - // Compatibility with pre openal 1.2 - S32 getMaxSourcesOld(); + // Compatibility with pre openal 1.2 + S32 getMaxSourcesOld(); - SFXALDevice( SFXProvider *provider, - const OPENALFNTABLE &openal, - String name, - bool useHardware, - S32 maxBuffers ); + SFXALDevice(U32 providerIndex); - virtual ~SFXALDevice(); + virtual ~SFXALDevice(); - protected: +protected: + static SFXProvider::CreateProviderInstanceDelegate mCreateDeviceInstance; + OPENALFNTABLE mOpenAL; - OPENALFNTABLE mOpenAL; + ALCcontext *mContext; - ALCcontext *mContext; - - ALCdevice *mDevice; + ALCdevice *mDevice; - SFXDistanceModel mDistanceModel; - F32 mDistanceFactor; - F32 mRolloffFactor; - F32 mUserRolloffFactor; - - void _setRolloffFactor( F32 factor ); + SFXDistanceModel mDistanceModel; + F32 mDistanceFactor; + F32 mRolloffFactor; + F32 mUserRolloffFactor; - public: + ALuint mEffect; + ALuint mAuxSlot; + bool mHasEFX; + bool mHasSoftHRTF; + bool mHasSoftReopen; - // SFXDevice. - SFXBuffer* createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description ) override; - SFXVoice* createVoice( bool is3D, SFXBuffer *buffer ) override; - void setListener( U32 index, const SFXListenerProperties& listener ) override; - void setDistanceModel( SFXDistanceModel model ) override; - void setDopplerFactor( F32 factor ) override; - void setRolloffFactor( F32 factor ) override; -#if defined(AL_ALEXT_PROTOTYPES) - //function for openAL to open slots - virtual void openSlots(); - //slots - ALuint effectSlot[4] = { 0 }; - ALuint effect[2] = { 0 }; - ALuint uLoop; - //get values from sfxreverbproperties and pass it to openal device - virtual void setReverb(const SFXReverbProperties& reverb); -#endif - void resetReverb() override {} + void _setRolloffFactor( F32 factor ); + +public: + static void enumerateProviders(Vector& providerList); + // SFXDevice. + SFXBuffer* createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description ) override; + SFXVoice* createVoice( bool is3D, SFXBuffer *buffer ) override; + void setListener( U32 index, const SFXListenerProperties& listener ) override; + void setDistanceModel( SFXDistanceModel model ) override; + void setDopplerFactor( F32 factor ) override; + void setReverb(const SFXReverbProperties& reverb) override; + void setRolloffFactor( F32 factor ) override; + void resetReverb() override {} + void setSpeedOfSound(F32 speedOfSound) override; + bool isDeviceConnected() override; + bool reconnectDevice(U32 providerIndex) override; + + ALuint getDeviceAuxSlot() { return mAuxSlot; } }; #endif // _SFXALDEVICE_H_ diff --git a/Engine/source/sfx/openal/sfxALProvider.cpp b/Engine/source/sfx/openal/sfxALProvider.cpp deleted file mode 100644 index b3a62c4ba..000000000 --- a/Engine/source/sfx/openal/sfxALProvider.cpp +++ /dev/null @@ -1,127 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- -#include "platform/platform.h" - -#include "sfx/sfxProvider.h" -#include "sfx/openal/sfxALDevice.h" -#include "sfx/openal/aldlist.h" -#include "sfx/openal/LoadOAL.h" - -#include "core/strings/stringFunctions.h" -#include "console/console.h" -#include "core/module.h" - - -class SFXALProvider : public SFXProvider -{ -public: - - SFXALProvider() - : SFXProvider( "OpenAL" ) { dMemset(&mOpenAL,0,sizeof(mOpenAL)); mALDL = NULL; } - virtual ~SFXALProvider(); - -protected: - OPENALFNTABLE mOpenAL; - ALDeviceList *mALDL; - - struct ALDeviceInfo : SFXDeviceInfo - { - - }; - - void init() override; - -public: - SFXDevice *createDevice( const String& deviceName, bool useHardware, S32 maxBuffers ) override; - -}; - -MODULE_BEGIN( OpenAL ) - - MODULE_INIT_BEFORE( SFX ) - MODULE_SHUTDOWN_AFTER( SFX ) - - SFXALProvider* mProvider = NULL; - - MODULE_INIT - { - mProvider = new SFXALProvider; - } - - MODULE_SHUTDOWN - { - delete mProvider; - } - -MODULE_END; - -void SFXALProvider::init() -{ - if( LoadOAL10Library( NULL, &mOpenAL ) != AL_TRUE ) - { - Con::printf( "SFXALProvider - OpenAL not available." ); - return; - } - mALDL = new ALDeviceList( mOpenAL ); - - // Did we get any devices? - if ( mALDL->GetNumDevices() < 1 ) - { - Con::printf( "SFXALProvider - No valid devices found!" ); - return; - } - - // Cool, loop through them, and caps em - //const char *deviceFormat = "OpenAL v%d.%d %s"; - - for( S32 i = 0; i < mALDL->GetNumDevices(); i++ ) - { - ALDeviceInfo* info = new ALDeviceInfo; - - //info->internalName = String( mALDL->GetInternalDeviceName( i ) ); - info->name = String( mALDL->GetDeviceName( i ) ); - - mDeviceInfo.push_back( info ); - } - - regProvider( this ); -} - -SFXALProvider::~SFXALProvider() -{ - UnloadOAL10Library(); - - if (mALDL) - delete mALDL; -} - -SFXDevice* SFXALProvider::createDevice(const String& deviceName, bool useHardware, S32 maxBuffers) -{ - ALDeviceInfo* info = dynamic_cast - (_findDeviceInfo(deviceName)); - - // Do we find one to create? - if (info) - return new SFXALDevice(this, mOpenAL, info->name, useHardware, maxBuffers); - - return NULL; -} diff --git a/Engine/source/sfx/openal/sfxALVoice.cpp b/Engine/source/sfx/openal/sfxALVoice.cpp index 12267d3c0..8bfbe2d83 100644 --- a/Engine/source/sfx/openal/sfxALVoice.cpp +++ b/Engine/source/sfx/openal/sfxALVoice.cpp @@ -28,7 +28,7 @@ #ifdef TORQUE_DEBUG # define AL_SANITY_CHECK() \ - AssertFatal( mOpenAL.alIsSource( mSourceName ), "AL Source Sanity Check Failed!" ); + AssertFatal( alIsSource( mSourceName ), "AL Source Sanity Check Failed!" ); #else # define AL_SANITY_CHECK() #endif @@ -42,8 +42,8 @@ SFXALVoice* SFXALVoice::create( SFXALDevice* device, SFXALBuffer *buffer ) AssertFatal( buffer, "SFXALVoice::create() - Got null buffer!" ); ALuint sourceName; - device->mOpenAL.alGenSources( 1, &sourceName ); - AssertFatal( device->mOpenAL.alIsSource( sourceName ), "AL Source Sanity Check Failed!" ); + alGenSources( 1, &sourceName ); + AssertFatal( alIsSource( sourceName ), "AL Source Sanity Check Failed!" ); // Is this 3d? // Okay, this looks odd, but bear with me for a moment. AL_SOURCE_RELATIVE does NOT indicate @@ -52,34 +52,41 @@ SFXALVoice* SFXALVoice::create( SFXALDevice* device, SFXALBuffer *buffer ) // does do is dictate if the position of THIS SOURCE is relative to the listener. If AL_SOURCE_RELATIVE is AL_TRUE // and the source's position is 0, 0, 0, then the source is directly on top of the listener at all times, which is what // we want for non-3d sounds. - device->mOpenAL.alSourcei( sourceName, AL_SOURCE_RELATIVE, ( buffer->mIs3d ? AL_FALSE : AL_TRUE ) ); + alSourcei( sourceName, AL_SOURCE_RELATIVE, ( buffer->mIs3d ? AL_FALSE : AL_TRUE ) ); if( buffer->mIs3d ) - device->mOpenAL.alSourcef( sourceName, AL_ROLLOFF_FACTOR, device->mRolloffFactor ); + alSourcef( sourceName, AL_ROLLOFF_FACTOR, device->mRolloffFactor ); - SFXALVoice *voice = new SFXALVoice( device->mOpenAL, - buffer, + SFXALVoice *voice = new SFXALVoice( buffer, sourceName ); + // does our device support reverb + if (device->mCaps & SFXDevice::ECaps::CAPS_Reverb) + { + voice->mDeviceAuxSlot = (ALint)device->getDeviceAuxSlot(); + alSource3i(sourceName, AL_AUXILIARY_SEND_FILTER, voice->mDeviceAuxSlot, 0, AL_FILTER_NULL); + } + return voice; } -SFXALVoice::SFXALVoice( const OPENALFNTABLE &oalft, - SFXALBuffer *buffer, +SFXALVoice::SFXALVoice( SFXALBuffer *buffer, ALuint sourceName ) : Parent( buffer ), mSourceName( sourceName ), mResumeAtSampleOffset( -1.0f ), + mDeviceAuxSlot(0), mSampleOffset( 0 ), - mOpenAL( oalft ) + mUseReverb(false) { AL_SANITY_CHECK(); } SFXALVoice::~SFXALVoice() { - mOpenAL.alDeleteSources( 1, &mSourceName ); + alSourcei(mSourceName, AL_BUFFER, 0); + alDeleteSources( 1, &mSourceName ); } void SFXALVoice::_lateBindStaticBufferIfNecessary() @@ -87,9 +94,9 @@ void SFXALVoice::_lateBindStaticBufferIfNecessary() if( !mBuffer->isStreaming() ) { ALint bufferId; - mOpenAL.alGetSourcei( mSourceName, AL_BUFFER, &bufferId ); + alGetSourcei( mSourceName, AL_BUFFER, &bufferId ); if( !bufferId ) - mOpenAL.alSourcei( mSourceName, AL_BUFFER, _getBuffer()->mALBuffer ); + alSourcei( mSourceName, AL_BUFFER, _getBuffer()->mALBuffer ); } } @@ -99,7 +106,7 @@ SFXStatus SFXALVoice::_status() const AL_SANITY_CHECK(); ALint state; - mOpenAL.alGetSourcei( mSourceName, AL_SOURCE_STATE, &state ); + alGetSourcei( mSourceName, AL_SOURCE_STATE, &state ); switch( state ) { @@ -118,18 +125,15 @@ void SFXALVoice::_play() #ifdef DEBUG_SPEW Platform::outputDebugString( "[SFXALVoice] Starting playback" ); #endif -#if defined(AL_ALEXT_PROTOTYPES) - //send every voice that plays to the alauxiliary slot that has the reverb - mOpenAL.alSource3i(mSourceName, AL_AUXILIARY_SEND_FILTER, 1, 0, AL_FILTER_NULL); -#endif - mOpenAL.alSourcePlay( mSourceName ); + + alSourcePlay( mSourceName ); //WORKAROUND: Adjust play cursor for buggy OAL when resuming playback. Do this after alSourcePlay // as it is the play function that will cause the cursor to jump. if( mResumeAtSampleOffset != -1.0f ) { - mOpenAL.alSourcef( mSourceName, AL_SAMPLE_OFFSET, mResumeAtSampleOffset ); + alSourcef( mSourceName, AL_SAMPLE_OFFSET, mResumeAtSampleOffset ); mResumeAtSampleOffset = -1.0f; } } @@ -142,12 +146,12 @@ void SFXALVoice::_pause() Platform::outputDebugString( "[SFXALVoice] Pausing playback" ); #endif - mOpenAL.alSourcePause( mSourceName ); + alSourcePause( mSourceName ); //WORKAROUND: Another workaround for buggy OAL. Resuming playback of a paused source will cause the // play cursor to jump. Save the cursor so we can manually move it into position in _play(). Sigh. - mOpenAL.alGetSourcef( mSourceName, AL_SAMPLE_OFFSET, &mResumeAtSampleOffset ); + alGetSourcef( mSourceName, AL_SAMPLE_OFFSET, &mResumeAtSampleOffset ); } void SFXALVoice::_stop() @@ -158,7 +162,7 @@ void SFXALVoice::_stop() Platform::outputDebugString( "[SFXALVoice] Stopping playback" ); #endif - mOpenAL.alSourceStop( mSourceName ); + alSourceStop( mSourceName ); mSampleOffset = 0; mResumeAtSampleOffset = -1.0f; @@ -169,7 +173,7 @@ void SFXALVoice::_seek( U32 sample ) AL_SANITY_CHECK(); _lateBindStaticBufferIfNecessary(); - mOpenAL.alSourcei( mSourceName, AL_SAMPLE_OFFSET, sample ); + alSourcei( mSourceName, AL_SAMPLE_OFFSET, sample ); mResumeAtSampleOffset = -1.0f; } @@ -183,7 +187,7 @@ U32 SFXALVoice::_tell() const mBuffer->write( NULL, 0 ); ALint pos; - mOpenAL.alGetSourcei( mSourceName, AL_SAMPLE_OFFSET, &pos ); + alGetSourcei( mSourceName, AL_SAMPLE_OFFSET, &pos ); return ( pos + mSampleOffset ); } @@ -191,17 +195,17 @@ void SFXALVoice::setMinMaxDistance( F32 min, F32 max ) { AL_SANITY_CHECK(); - mOpenAL.alSourcef( mSourceName, AL_REFERENCE_DISTANCE, min ); - mOpenAL.alSourcef( mSourceName, AL_MAX_DISTANCE, max ); + alSourcef( mSourceName, AL_REFERENCE_DISTANCE, min ); + alSourcef( mSourceName, AL_MAX_DISTANCE, max ); } void SFXALVoice::play( bool looping ) { AL_SANITY_CHECK(); - mOpenAL.alSourceStop( mSourceName ); + alSourceStop( mSourceName ); if( !mBuffer->isStreaming() ) - mOpenAL.alSourcei( mSourceName, AL_LOOPING, ( looping ? AL_TRUE : AL_FALSE ) ); + alSourcei( mSourceName, AL_LOOPING, ( looping ? AL_TRUE : AL_FALSE ) ); Parent::play( looping ); } @@ -213,7 +217,7 @@ void SFXALVoice::setVelocity( const VectorF& velocity ) // Torque and OpenAL are both right handed // systems, so no coordinate flipping is needed. - mOpenAL.alSourcefv( mSourceName, AL_VELOCITY, velocity ); + alSourcefv( mSourceName, AL_VELOCITY, velocity ); } void SFXALVoice::setTransform( const MatrixF& transform ) @@ -227,34 +231,47 @@ void SFXALVoice::setTransform( const MatrixF& transform ) transform.getColumn( 3, &pos ); transform.getColumn( 1, &dir ); - mOpenAL.alSourcefv( mSourceName, AL_POSITION, pos ); - mOpenAL.alSourcefv( mSourceName, AL_DIRECTION, dir ); + alSourcefv( mSourceName, AL_POSITION, pos ); + alSourcefv( mSourceName, AL_DIRECTION, dir ); +} + +void SFXALVoice::setReverb(bool useReverb) +{ + if (useReverb == mUseReverb) + return; + + if (!useReverb) + alSource3i(mSourceName, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL); + else + alSource3i(mSourceName, AL_AUXILIARY_SEND_FILTER, mDeviceAuxSlot, 0, AL_FILTER_NULL); + + mUseReverb = useReverb; } void SFXALVoice::setVolume( F32 volume ) { AL_SANITY_CHECK(); - mOpenAL.alSourcef( mSourceName, AL_GAIN, volume ); + alSourcef( mSourceName, AL_GAIN, volume ); } void SFXALVoice::setPitch( F32 pitch ) { AL_SANITY_CHECK(); - mOpenAL.alSourcef( mSourceName, AL_PITCH, pitch ); + alSourcef( mSourceName, AL_PITCH, pitch ); } void SFXALVoice::setCone( F32 innerAngle, F32 outerAngle, F32 outerVolume ) { AL_SANITY_CHECK(); - mOpenAL.alSourcef( mSourceName, AL_CONE_INNER_ANGLE, innerAngle ); - mOpenAL.alSourcef( mSourceName, AL_CONE_OUTER_ANGLE, outerAngle ); - mOpenAL.alSourcef( mSourceName, AL_CONE_OUTER_GAIN, outerVolume ); + alSourcef( mSourceName, AL_CONE_INNER_ANGLE, innerAngle ); + alSourcef( mSourceName, AL_CONE_OUTER_ANGLE, outerAngle ); + alSourcef( mSourceName, AL_CONE_OUTER_GAIN, outerVolume ); } void SFXALVoice::setRolloffFactor( F32 factor ) { - mOpenAL.alSourcef( mSourceName, AL_ROLLOFF_FACTOR, factor ); + alSourcef( mSourceName, AL_ROLLOFF_FACTOR, factor ); } diff --git a/Engine/source/sfx/openal/sfxALVoice.h b/Engine/source/sfx/openal/sfxALVoice.h index 2f3dd8eca..770918fec 100644 --- a/Engine/source/sfx/openal/sfxALVoice.h +++ b/Engine/source/sfx/openal/sfxALVoice.h @@ -47,14 +47,15 @@ class SFXALVoice : public SFXVoice protected: - SFXALVoice( const OPENALFNTABLE &oalft, - SFXALBuffer *buffer, + SFXALVoice( SFXALBuffer *buffer, ALuint sourceName ); ALuint mSourceName; /// Buggy OAL jumps around when pausing. Save playback cursor here. F32 mResumeAtSampleOffset; + + bool mUseReverb; /// Amount by which OAL's reported sample position is offset. /// @@ -63,9 +64,9 @@ class SFXALVoice : public SFXVoice /// queue we are. U32 mSampleOffset; - Mutex mMutex; + ALint mDeviceAuxSlot; - const OPENALFNTABLE &mOpenAL; + Mutex mMutex; /// SFXALBuffer* _getBuffer() const @@ -98,10 +99,11 @@ class SFXALVoice : public SFXVoice void play( bool looping ) override; void setVelocity( const VectorF& velocity ) override; void setTransform( const MatrixF& transform ) override; + void setReverb(bool useReverb) override; void setVolume( F32 volume ) override; void setPitch( F32 pitch ) override; void setCone( F32 innerAngle, F32 outerAngle, F32 outerVolume ) override; void setRolloffFactor( F32 factor ) override; }; -#endif // _SFXALVOICE_H_ \ No newline at end of file +#endif // _SFXALVOICE_H_ diff --git a/Engine/source/sfx/openal/win32/LoadOAL.cpp b/Engine/source/sfx/openal/win32/LoadOAL.cpp deleted file mode 100644 index 4c1888a69..000000000 --- a/Engine/source/sfx/openal/win32/LoadOAL.cpp +++ /dev/null @@ -1,601 +0,0 @@ -/* - * Copyright (c) 2006, Creative Labs 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: - * - * * Redistributions of source code must retain the above copyright notice, this list of conditions and - * the following disclaimer. - * * 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. - * * Neither the name of Creative Labs Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT OWNER OR 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. - */ - -#include -#include "sfx/openal/LoadOAL.h" - -HINSTANCE g_hOpenALDLL = NULL; - -ALboolean LoadOAL10Library(char *szOALFullPathName, LPOPENALFNTABLE lpOALFnTable) -{ - if (!lpOALFnTable) - return AL_FALSE; - - if (szOALFullPathName) - g_hOpenALDLL = LoadLibraryA(szOALFullPathName); - else - { -#ifdef TORQUE_DEBUG - g_hOpenALDLL = LoadLibraryA("openal32d.dll"); -#else - g_hOpenALDLL = LoadLibraryA("openal32.dll"); -#endif - } - if (!g_hOpenALDLL) - return AL_FALSE; - - memset(lpOALFnTable, 0, sizeof(OPENALFNTABLE)); - - // Get function pointers - lpOALFnTable->alEnable = (LPALENABLE)GetProcAddress(g_hOpenALDLL, "alEnable"); - if (lpOALFnTable->alEnable == NULL) - { - OutputDebugStringA("Failed to retrieve 'alEnable' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDisable = (LPALDISABLE)GetProcAddress(g_hOpenALDLL, "alDisable"); - if (lpOALFnTable->alDisable == NULL) - { - OutputDebugStringA("Failed to retrieve 'alDisable' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsEnabled = (LPALISENABLED)GetProcAddress(g_hOpenALDLL, "alIsEnabled"); - if (lpOALFnTable->alIsEnabled == NULL) - { - OutputDebugStringA("Failed to retrieve 'alIsEnabled' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetBoolean = (LPALGETBOOLEAN)GetProcAddress(g_hOpenALDLL, "alGetBoolean"); - if (lpOALFnTable->alGetBoolean == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetBoolean' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetInteger = (LPALGETINTEGER)GetProcAddress(g_hOpenALDLL, "alGetInteger"); - if (lpOALFnTable->alGetInteger == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetInteger' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetFloat = (LPALGETFLOAT)GetProcAddress(g_hOpenALDLL, "alGetFloat"); - if (lpOALFnTable->alGetFloat == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetFloat' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetDouble = (LPALGETDOUBLE)GetProcAddress(g_hOpenALDLL, "alGetDouble"); - if (lpOALFnTable->alGetDouble == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetDouble' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetBooleanv = (LPALGETBOOLEANV)GetProcAddress(g_hOpenALDLL, "alGetBooleanv"); - if (lpOALFnTable->alGetBooleanv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetBooleanv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetIntegerv = (LPALGETINTEGERV)GetProcAddress(g_hOpenALDLL, "alGetIntegerv"); - if (lpOALFnTable->alGetIntegerv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetIntegerv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetFloatv = (LPALGETFLOATV)GetProcAddress(g_hOpenALDLL, "alGetFloatv"); - if (lpOALFnTable->alGetFloatv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetFloatv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetDoublev = (LPALGETDOUBLEV)GetProcAddress(g_hOpenALDLL, "alGetDoublev"); - if (lpOALFnTable->alGetDoublev == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetDoublev' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetString = (LPALGETSTRING)GetProcAddress(g_hOpenALDLL, "alGetString"); - if (lpOALFnTable->alGetString == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetString' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetError = (LPALGETERROR)GetProcAddress(g_hOpenALDLL, "alGetError"); - if (lpOALFnTable->alGetError == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetError' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsExtensionPresent = (LPALISEXTENSIONPRESENT)GetProcAddress(g_hOpenALDLL, "alIsExtensionPresent"); - if (lpOALFnTable->alIsExtensionPresent == NULL) - { - OutputDebugStringA("Failed to retrieve 'alIsExtensionPresent' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetProcAddress = (LPALGETPROCADDRESS)GetProcAddress(g_hOpenALDLL, "alGetProcAddress"); - if (lpOALFnTable->alGetProcAddress == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetProcAddress' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetEnumValue = (LPALGETENUMVALUE)GetProcAddress(g_hOpenALDLL, "alGetEnumValue"); - if (lpOALFnTable->alGetEnumValue == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetEnumValue' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alListeneri = (LPALLISTENERI)GetProcAddress(g_hOpenALDLL, "alListeneri"); - if (lpOALFnTable->alListeneri == NULL) - { - OutputDebugStringA("Failed to retrieve 'alListeneri' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alListenerf = (LPALLISTENERF)GetProcAddress(g_hOpenALDLL, "alListenerf"); - if (lpOALFnTable->alListenerf == NULL) - { - OutputDebugStringA("Failed to retrieve 'alListenerf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alListener3f = (LPALLISTENER3F)GetProcAddress(g_hOpenALDLL, "alListener3f"); - if (lpOALFnTable->alListener3f == NULL) - { - OutputDebugStringA("Failed to retrieve 'alListener3f' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alListenerfv = (LPALLISTENERFV)GetProcAddress(g_hOpenALDLL, "alListenerfv"); - if (lpOALFnTable->alListenerfv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alListenerfv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetListeneri = (LPALGETLISTENERI)GetProcAddress(g_hOpenALDLL, "alGetListeneri"); - if (lpOALFnTable->alGetListeneri == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetListeneri' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetListenerf =(LPALGETLISTENERF)GetProcAddress(g_hOpenALDLL, "alGetListenerf"); - if (lpOALFnTable->alGetListenerf == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetListenerf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetListener3f = (LPALGETLISTENER3F)GetProcAddress(g_hOpenALDLL, "alGetListener3f"); - if (lpOALFnTable->alGetListener3f == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetListener3f' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetListenerfv = (LPALGETLISTENERFV)GetProcAddress(g_hOpenALDLL, "alGetListenerfv"); - if (lpOALFnTable->alGetListenerfv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetListenerfv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGenSources = (LPALGENSOURCES)GetProcAddress(g_hOpenALDLL, "alGenSources"); - if (lpOALFnTable->alGenSources == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGenSources' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDeleteSources = (LPALDELETESOURCES)GetProcAddress(g_hOpenALDLL, "alDeleteSources"); - if (lpOALFnTable->alDeleteSources == NULL) - { - OutputDebugStringA("Failed to retrieve 'alDeleteSources' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsSource = (LPALISSOURCE)GetProcAddress(g_hOpenALDLL, "alIsSource"); - if (lpOALFnTable->alIsSource == NULL) - { - OutputDebugStringA("Failed to retrieve 'alIsSource' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcei = (LPALSOURCEI)GetProcAddress(g_hOpenALDLL, "alSourcei"); - if (lpOALFnTable->alSourcei == NULL) - { - OutputDebugStringA("Failed to retrieve 'alSourcei' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcef = (LPALSOURCEF)GetProcAddress(g_hOpenALDLL, "alSourcef"); - if (lpOALFnTable->alSourcef == NULL) - { - OutputDebugStringA("Failed to retrieve 'alSourcef' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSource3f = (LPALSOURCE3F)GetProcAddress(g_hOpenALDLL, "alSource3f"); - if (lpOALFnTable->alSource3f == NULL) - { - OutputDebugStringA("Failed to retrieve 'alSource3f' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcefv = (LPALSOURCEFV)GetProcAddress(g_hOpenALDLL, "alSourcefv"); - if (lpOALFnTable->alSourcefv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alSourcefv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetSourcei = (LPALGETSOURCEI)GetProcAddress(g_hOpenALDLL, "alGetSourcei"); - if (lpOALFnTable->alGetSourcei == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetSourcei' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetSourcef = (LPALGETSOURCEF)GetProcAddress(g_hOpenALDLL, "alGetSourcef"); - if (lpOALFnTable->alGetSourcef == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetSourcef' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetSourcefv = (LPALGETSOURCEFV)GetProcAddress(g_hOpenALDLL, "alGetSourcefv"); - if (lpOALFnTable->alGetSourcefv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetSourcefv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcePlayv = (LPALSOURCEPLAYV)GetProcAddress(g_hOpenALDLL, "alSourcePlayv"); - if (lpOALFnTable->alSourcePlayv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alSourcePlayv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourceStopv = (LPALSOURCESTOPV)GetProcAddress(g_hOpenALDLL, "alSourceStopv"); - if (lpOALFnTable->alSourceStopv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alSourceStopv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcePlay = (LPALSOURCEPLAY)GetProcAddress(g_hOpenALDLL, "alSourcePlay"); - if (lpOALFnTable->alSourcePlay == NULL) - { - OutputDebugStringA("Failed to retrieve 'alSourcePlay' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourcePause = (LPALSOURCEPAUSE)GetProcAddress(g_hOpenALDLL, "alSourcePause"); - if (lpOALFnTable->alSourcePause == NULL) - { - OutputDebugStringA("Failed to retrieve 'alSourcePause' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourceStop = (LPALSOURCESTOP)GetProcAddress(g_hOpenALDLL, "alSourceStop"); - if (lpOALFnTable->alSourceStop == NULL) - { - OutputDebugStringA("Failed to retrieve 'alSourceStop' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourceRewind = (LPALSOURCEREWIND)GetProcAddress(g_hOpenALDLL, "alSourceRewind"); - if (lpOALFnTable->alSourceRewind == NULL) - { - OutputDebugStringA("Failed to retrieve 'alSourceRewind' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGenBuffers = (LPALGENBUFFERS)GetProcAddress(g_hOpenALDLL, "alGenBuffers"); - if (lpOALFnTable->alGenBuffers == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGenBuffers' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDeleteBuffers = (LPALDELETEBUFFERS)GetProcAddress(g_hOpenALDLL, "alDeleteBuffers"); - if (lpOALFnTable->alDeleteBuffers == NULL) - { - OutputDebugStringA("Failed to retrieve 'alDeleteBuffers' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alIsBuffer = (LPALISBUFFER)GetProcAddress(g_hOpenALDLL, "alIsBuffer"); - if (lpOALFnTable->alIsBuffer == NULL) - { - OutputDebugStringA("Failed to retrieve 'alIsBuffer' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alBufferData = (LPALBUFFERDATA)GetProcAddress(g_hOpenALDLL, "alBufferData"); - if (lpOALFnTable->alBufferData == NULL) - { - OutputDebugStringA("Failed to retrieve 'alBufferData' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetBufferi = (LPALGETBUFFERI)GetProcAddress(g_hOpenALDLL, "alGetBufferi"); - if (lpOALFnTable->alGetBufferi == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetBufferi' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alGetBufferf = (LPALGETBUFFERF)GetProcAddress(g_hOpenALDLL, "alGetBufferf"); - if (lpOALFnTable->alGetBufferf == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetBufferf' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourceQueueBuffers = (LPALSOURCEQUEUEBUFFERS)GetProcAddress(g_hOpenALDLL, "alSourceQueueBuffers"); - if (lpOALFnTable->alSourceQueueBuffers == NULL) - { - OutputDebugStringA("Failed to retrieve 'alSourceQueueBuffers' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alSourceUnqueueBuffers = (LPALSOURCEUNQUEUEBUFFERS)GetProcAddress(g_hOpenALDLL, "alSourceUnqueueBuffers"); - if (lpOALFnTable->alSourceUnqueueBuffers == NULL) - { - OutputDebugStringA("Failed to retrieve 'alSourceUnqueueBuffers' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDistanceModel = (LPALDISTANCEMODEL)GetProcAddress(g_hOpenALDLL, "alDistanceModel"); - if (lpOALFnTable->alDistanceModel == NULL) - { - OutputDebugStringA("Failed to retrieve 'alDistanceModel' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDopplerFactor = (LPALDOPPLERFACTOR)GetProcAddress(g_hOpenALDLL, "alDopplerFactor"); - if (lpOALFnTable->alDopplerFactor == NULL) - { - OutputDebugStringA("Failed to retrieve 'alDopplerFactor' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alDopplerVelocity = (LPALDOPPLERVELOCITY)GetProcAddress(g_hOpenALDLL, "alDopplerVelocity"); - if (lpOALFnTable->alDopplerVelocity == NULL) - { - OutputDebugStringA("Failed to retrieve 'alDopplerVelocity' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetString = (LPALCGETSTRING)GetProcAddress(g_hOpenALDLL, "alcGetString"); - if (lpOALFnTable->alcGetString == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcGetString' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetIntegerv = (LPALCGETINTEGERV)GetProcAddress(g_hOpenALDLL, "alcGetIntegerv"); - if (lpOALFnTable->alcGetIntegerv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcGetIntegerv' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcOpenDevice = (LPALCOPENDEVICE)GetProcAddress(g_hOpenALDLL, "alcOpenDevice"); - if (lpOALFnTable->alcOpenDevice == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcOpenDevice' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcCloseDevice = (LPALCCLOSEDEVICE)GetProcAddress(g_hOpenALDLL, "alcCloseDevice"); - if (lpOALFnTable->alcCloseDevice == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcCloseDevice' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcCreateContext = (LPALCCREATECONTEXT)GetProcAddress(g_hOpenALDLL, "alcCreateContext"); - if (lpOALFnTable->alcCreateContext == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcCreateContext' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcMakeContextCurrent = (LPALCMAKECONTEXTCURRENT)GetProcAddress(g_hOpenALDLL, "alcMakeContextCurrent"); - if (lpOALFnTable->alcMakeContextCurrent == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcMakeContextCurrent' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcProcessContext = (LPALCPROCESSCONTEXT)GetProcAddress(g_hOpenALDLL, "alcProcessContext"); - if (lpOALFnTable->alcProcessContext == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcProcessContext' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetCurrentContext = (LPALCGETCURRENTCONTEXT)GetProcAddress(g_hOpenALDLL, "alcGetCurrentContext"); - if (lpOALFnTable->alcGetCurrentContext == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcGetCurrentContext' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetContextsDevice = (LPALCGETCONTEXTSDEVICE)GetProcAddress(g_hOpenALDLL, "alcGetContextsDevice"); - if (lpOALFnTable->alcGetContextsDevice == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcGetContextsDevice' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcSuspendContext = (LPALCSUSPENDCONTEXT)GetProcAddress(g_hOpenALDLL, "alcSuspendContext"); - if (lpOALFnTable->alcSuspendContext == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcSuspendContext' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcDestroyContext = (LPALCDESTROYCONTEXT)GetProcAddress(g_hOpenALDLL, "alcDestroyContext"); - if (lpOALFnTable->alcDestroyContext == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcDestroyContext' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetError = (LPALCGETERROR)GetProcAddress(g_hOpenALDLL, "alcGetError"); - if (lpOALFnTable->alcGetError == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcGetError' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcIsExtensionPresent = (LPALCISEXTENSIONPRESENT)GetProcAddress(g_hOpenALDLL, "alcIsExtensionPresent"); - if (lpOALFnTable->alcIsExtensionPresent == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcIsExtensionPresent' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetProcAddress = (LPALCGETPROCADDRESS)GetProcAddress(g_hOpenALDLL, "alcGetProcAddress"); - if (lpOALFnTable->alcGetProcAddress == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcGetProcAddress' function address\n"); - return AL_FALSE; - } - lpOALFnTable->alcGetEnumValue = (LPALCGETENUMVALUE)GetProcAddress(g_hOpenALDLL, "alcGetEnumValue"); - if (lpOALFnTable->alcGetEnumValue == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcGetEnumValue' function address\n"); - return AL_FALSE; - } -#if defined(AL_ALEXT_PROTOTYPES) - lpOALFnTable->alGenEffects = (LPALGENEFFECTS)GetProcAddress(g_hOpenALDLL, "alGenEffects"); - if (lpOALFnTable->alGenEffects == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGenEffects' function address\n"); - } - lpOALFnTable->alEffecti = (LPALEFFECTI)GetProcAddress(g_hOpenALDLL, "alEffecti"); - if (lpOALFnTable->alEffecti == NULL) - { - OutputDebugStringA("Failed to retrieve 'alEffecti' function address\n"); - } - lpOALFnTable->alEffectiv = (LPALEFFECTIV)GetProcAddress(g_hOpenALDLL, "alEffectiv"); - if (lpOALFnTable->alEffectiv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alEffectiv' function address\n"); - } - lpOALFnTable->alEffectf = (LPALEFFECTF)GetProcAddress(g_hOpenALDLL, "alEffectf"); - if (lpOALFnTable->alEffectf == NULL) - { - OutputDebugStringA("Failed to retrieve 'alEffectf' function address\n"); - } - lpOALFnTable->alEffectfv = (LPALEFFECTFV)GetProcAddress(g_hOpenALDLL, "alEffectfv"); - if (lpOALFnTable->alEffectfv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alEffectfv' function address\n"); - } - lpOALFnTable->alGetEffecti = (LPALGETEFFECTI)GetProcAddress(g_hOpenALDLL, "alGetEffecti"); - if (lpOALFnTable->alGetEffecti == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetEffecti' function address\n"); - } - lpOALFnTable->alGetEffectiv = (LPALGETEFFECTIV)GetProcAddress(g_hOpenALDLL, "alGetEffectiv"); - if (lpOALFnTable->alGetEffectiv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetEffectiv' function address\n"); - } - lpOALFnTable->alGetEffectf = (LPALGETEFFECTF)GetProcAddress(g_hOpenALDLL, "alGetEffectf"); - if (lpOALFnTable->alGetEffectf == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetEffectf' function address\n"); - } - lpOALFnTable->alGetEffectfv = (LPALGETEFFECTFV)GetProcAddress(g_hOpenALDLL, "alGetEffectfv"); - if (lpOALFnTable->alGetEffectfv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetEffectfv' function address\n"); - } - - lpOALFnTable->alDeleteEffects = (LPALDELETEEFFECTS)GetProcAddress(g_hOpenALDLL, "alDeleteEffects"); - if (lpOALFnTable->alDeleteEffects == NULL) - { - OutputDebugStringA("Failed to retrieve 'alDeleteEffects' function address\n"); - } - lpOALFnTable->alIsEffect = (LPALISEFFECT)GetProcAddress(g_hOpenALDLL, "alIsEffect"); - if (lpOALFnTable->alIsEffect == NULL) - { - OutputDebugStringA("Failed to retrieve 'alIsEffect' function address\n"); - } - lpOALFnTable->alAuxiliaryEffectSlotf = (LPALAUXILIARYEFFECTSLOTF)GetProcAddress(g_hOpenALDLL, "alAuxiliaryEffectSlotf"); - if (lpOALFnTable->alAuxiliaryEffectSlotf == NULL) - { - OutputDebugStringA("Failed to retrieve 'alAuxiliaryEffectSlotf' function address\n"); - } - lpOALFnTable->alAuxiliaryEffectSlotfv = (LPALAUXILIARYEFFECTSLOTFV)GetProcAddress(g_hOpenALDLL, "alAuxiliaryEffectSlotfv"); - if (lpOALFnTable->alAuxiliaryEffectSlotfv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alAuxiliaryEffectSlotfv' function address\n"); - } - lpOALFnTable->alAuxiliaryEffectSloti = (LPALAUXILIARYEFFECTSLOTI)GetProcAddress(g_hOpenALDLL, "alAuxiliaryEffectSloti"); - if (lpOALFnTable->alAuxiliaryEffectSloti == NULL) - { - OutputDebugStringA("Failed to retrieve 'alAuxiliaryEffectSloti' function address\n"); - } - lpOALFnTable->alAuxiliaryEffectSlotiv = (LPALAUXILIARYEFFECTSLOTIV)GetProcAddress(g_hOpenALDLL, "alAuxiliaryEffectSlotiv"); - if (lpOALFnTable->alAuxiliaryEffectSlotiv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alAuxiliaryEffectSlotiv' function address\n"); - } - lpOALFnTable->alIsAuxiliaryEffectSlot = (LPALISAUXILIARYEFFECTSLOT)GetProcAddress(g_hOpenALDLL, "alIsAuxiliaryEffectSlot"); - if (lpOALFnTable->alIsAuxiliaryEffectSlot == NULL) - { - OutputDebugStringA("Failed to retrieve 'alIsAuxiliaryEffectSlot' function address\n"); - } - lpOALFnTable->alGenAuxiliaryEffectSlots = (LPALGENAUXILIARYEFFECTSLOTS)GetProcAddress(g_hOpenALDLL, "alGenAuxiliaryEffectSlots"); - if (lpOALFnTable->alGenAuxiliaryEffectSlots == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGenAuxiliaryEffectSlots' function address\n"); - } - lpOALFnTable->alDeleteAuxiliaryEffectSlots = (LPALDELETEAUXILIARYEFFECTSLOTS)GetProcAddress(g_hOpenALDLL, "alDeleteAuxiliaryEffectSlots"); - if (lpOALFnTable->alDeleteAuxiliaryEffectSlots == NULL) - { - OutputDebugStringA("Failed to retrieve 'alDeleteAuxiliaryEffectSlots' function address\n"); - } - lpOALFnTable->alGetAuxiliaryEffectSlotf = (LPALGETAUXILIARYEFFECTSLOTF)GetProcAddress(g_hOpenALDLL, "alGetAuxiliaryEffectSlotf"); - if (lpOALFnTable->alGetAuxiliaryEffectSlotf == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetAuxiliaryEffectSlotf' function address\n"); - } - lpOALFnTable->alGetAuxiliaryEffectSlotfv = (LPALGETAUXILIARYEFFECTSLOTFV)GetProcAddress(g_hOpenALDLL, "alGetAuxiliaryEffectSlotfv"); - if (lpOALFnTable->alGetAuxiliaryEffectSlotfv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetAuxiliaryEffectSlotfv' function address\n"); - } - lpOALFnTable->alGetAuxiliaryEffectSloti = (LPALGETAUXILIARYEFFECTSLOTI)GetProcAddress(g_hOpenALDLL, "alGetAuxiliaryEffectSloti"); - if (lpOALFnTable->alGetAuxiliaryEffectSloti == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetAuxiliaryEffectSloti' function address\n"); - } - lpOALFnTable->alGetAuxiliaryEffectSlotiv = (LPALGETAUXILIARYEFFECTSLOTIV)GetProcAddress(g_hOpenALDLL, "alGetAuxiliaryEffectSlotiv"); - if (lpOALFnTable->alGetAuxiliaryEffectSlotiv == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGetAuxiliaryEffectSlotiv' function address\n"); - } - lpOALFnTable->alSource3i = (LPALSOURCE3I)GetProcAddress(g_hOpenALDLL, "alSource3i"); - - lpOALFnTable->alGenFilters = (LPALGENFILTERS)GetProcAddress(g_hOpenALDLL, "alGenFilters"); - if (lpOALFnTable->alGenFilters == NULL) - { - OutputDebugStringA("Failed to retrieve 'alGenFilters' function address\n"); - return AL_FALSE; - } - - lpOALFnTable->alDeleteFilters = (LPALDELETEFILTERS)GetProcAddress(g_hOpenALDLL, "alDeleteFilters"); - if (lpOALFnTable->alGenFilters == NULL) - { - OutputDebugStringA("Failed to retrieve 'alDeleteFilters' function address\n"); - return AL_FALSE; - } - - lpOALFnTable->alFilteri = (LPALFILTERI)GetProcAddress(g_hOpenALDLL, "alFilteri"); - if (lpOALFnTable->alGenFilters == NULL) - { - OutputDebugStringA("Failed to retrieve 'alFilteri' function address\n"); - return AL_FALSE; - } - - lpOALFnTable->alcGetStringiSOFT = (LPALCGETSTRINGISOFT)GetProcAddress(g_hOpenALDLL, "alcGetStringiSOFT"); - if (lpOALFnTable->alcGetStringiSOFT == NULL) - { - OutputDebugStringA("Failed to retrieve 'alcGetStringiSOFT' function address\n"); - return AL_FALSE; - } - -#endif - return AL_TRUE; -} - -ALvoid UnloadOAL10Library() -{ - // Unload the dll - if (g_hOpenALDLL) - { - FreeLibrary(g_hOpenALDLL); - g_hOpenALDLL = NULL; - } -} diff --git a/Engine/source/sfx/sfxAmbience.cpp b/Engine/source/sfx/sfxAmbience.cpp index 285ffc03a..6074369a5 100644 --- a/Engine/source/sfx/sfxAmbience.cpp +++ b/Engine/source/sfx/sfxAmbience.cpp @@ -85,6 +85,7 @@ SFXAmbience::ChangeSignal SFXAmbience::smChangeSignal; SFXAmbience::SFXAmbience() : mDopplerFactor( 0.5f ), mRolloffFactor( 1.f ), + mSpeedOfSound(343.3f), mEnvironment( NULL ) { dMemset( mState, 0, sizeof( mState ) ); @@ -112,6 +113,10 @@ void SFXAmbience::initPersistFields() "The factor to apply to the doppler affect in this space.\n" "Defaults to 0.5.\n\n" "@ref SFXSource_doppler" ); + addFieldV("speedOfSound", TypeRangedF32, Offset(mSpeedOfSound, SFXAmbience), &CommonValidators::PositiveFloat, + "The speed of sound in this space.\n" + "Defaults to 343.3.\n\n" + "@ref SFXSource_speedofsound"); addField( "states", TypeSFXStateName, Offset( mState, SFXAmbience ), MaxStates, "States to activate when the ambient zone is entered.\n" @@ -177,6 +182,7 @@ void SFXAmbience::packData( BitStream* stream ) stream->write( mRolloffFactor ); stream->write( mDopplerFactor ); + stream->write(mSpeedOfSound); for( U32 i = 0; i < MaxStates; ++ i ) sfxWrite( stream, mState[ i ] ); @@ -193,6 +199,7 @@ void SFXAmbience::unpackData( BitStream* stream ) stream->read( &mRolloffFactor ); stream->read( &mDopplerFactor ); + stream->read(&mSpeedOfSound); for( U32 i = 0; i < MaxStates; ++ i ) sfxRead( stream, &mState[ i ] ); diff --git a/Engine/source/sfx/sfxAmbience.h b/Engine/source/sfx/sfxAmbience.h index bd36a1547..d429e5570 100644 --- a/Engine/source/sfx/sfxAmbience.h +++ b/Engine/source/sfx/sfxAmbience.h @@ -61,6 +61,9 @@ class SFXAmbience : public SimDataBlock /// Doppler shift factor for this space. F32 mDopplerFactor; + + /// Speed of sound for this space. + F32 mSpeedOfSound; /// Rolloff factor for this space. Only applies to logarithmic distance model. F32 mRolloffFactor; @@ -90,6 +93,8 @@ class SFXAmbience : public SimDataBlock /// Return the doppler shift factor to apply in this space. F32 getDopplerFactor() const { return mDopplerFactor; } + + F32 getSpeedOfSound() const { return mSpeedOfSound; } /// Return the reverb environment of the ambient space. SFXEnvironment* getEnvironment() const { return mEnvironment; } diff --git a/Engine/source/sfx/sfxCommon.h b/Engine/source/sfx/sfxCommon.h index 784f612f6..22ff258c1 100644 --- a/Engine/source/sfx/sfxCommon.h +++ b/Engine/source/sfx/sfxCommon.h @@ -24,25 +24,25 @@ #define _SFXCOMMON_H_ #ifndef _PLATFORM_H_ - #include "platform/platform.h" +#include "platform/platform.h" #endif #ifndef _MMATHFN_H_ - #include "math/mMathFn.h" +#include "math/mMathFn.h" #endif #ifndef _MRANDOM_H_ - #include "math/mRandom.h" +#include "math/mRandom.h" #endif #ifndef _MMATRIX_H_ - #include "math/mMatrix.h" +#include "math/mMatrix.h" #endif #ifndef _MPOINT3_H_ - #include "math/mPoint3.h" +#include "math/mPoint3.h" #endif #ifndef _TYPETRAITS_H_ - #include "platform/typetraits.h" +#include "platform/typetraits.h" #endif #ifndef _DYNAMIC_CONSOLETYPES_H_ - #include "console/dynamicTypes.h" +#include "console/dynamicTypes.h" #endif @@ -51,13 +51,37 @@ class SFXEnvironment; class SFXPlayList; +//----------------------------------------------------------------------------- +// SFXProviderType. +//----------------------------------------------------------------------------- +enum SFXProviderType +{ + OpenAL, + XAudio, + DirectSound, + NullProvider, + SFXProviderType_Count +}; +DefineEnumType(SFXProviderType); + +//----------------------------------------------------------------------------- +// SFXDeviceType. +//----------------------------------------------------------------------------- +enum SFXDeviceType +{ + Output, + Input, + SFXDeviceType_Count +}; +DefineEnumType(SFXDeviceType); + //----------------------------------------------------------------------------- // SFXStatus. //----------------------------------------------------------------------------- /// The sound playback state. -enum SFXStatus +enum SFXStatus { /// Initial state; no operation yet performed on sound. SFXStatusNull, @@ -83,23 +107,23 @@ enum SFXStatus SFXStatusTransition, }; -DefineEnumType( SFXStatus ); +DefineEnumType(SFXStatus); -inline const char* SFXStatusToString( SFXStatus status ) +inline const char* SFXStatusToString(SFXStatus status) { - switch ( status ) + switch (status) { - case SFXStatusPlaying: return "playing"; - case SFXStatusStopped: return "stopped"; - case SFXStatusPaused: return "paused"; - case SFXStatusBlocked: return "blocked"; - case SFXStatusTransition: return "transition"; - - case SFXStatusNull: - default: ; + case SFXStatusPlaying: return "playing"; + case SFXStatusStopped: return "stopped"; + case SFXStatusPaused: return "paused"; + case SFXStatusBlocked: return "blocked"; + case SFXStatusTransition: return "transition"; + + case SFXStatusNull: + default:; } - + return "null"; } @@ -135,12 +159,12 @@ enum SFXChannel SFXChannelUser1, SFXChannelUser2, SFXChannelUser3, - + /// Total number of animatable channels. SFX_NUM_CHANNELS }; -DefineEnumType( SFXChannel ); +DefineEnumType(SFXChannel); //----------------------------------------------------------------------------- @@ -156,7 +180,7 @@ enum SFXDistanceModel SFXDistanceModelExponent, /// exponential falloff for distance attenuation. }; -DefineEnumType( SFXDistanceModel ); +DefineEnumType(SFXDistanceModel); /// Compute the distance attenuation based on the given distance model. /// @@ -167,46 +191,52 @@ DefineEnumType( SFXDistanceModel ); /// @param rolloffFactor Rolloff curve scale factor. /// /// @return The attenuated volume. -inline F32 SFXDistanceAttenuation( SFXDistanceModel model, F32 minDistance, F32 maxDistance, F32 distance, F32 volume, F32 rolloffFactor ) +inline F32 SFXDistanceAttenuation(SFXDistanceModel model, F32 minDistance, F32 maxDistance, F32 distance, F32 volume, F32 rolloffFactor) { F32 gain = 1.0f; - - switch( model ) + + switch (model) { - case SFXDistanceModelLinear: - - distance = getMax( distance, minDistance ); - distance = getMin( distance, maxDistance ); - - gain = ( 1 - ( distance - minDistance ) / ( maxDistance - minDistance ) ); - break; - - case SFXDistanceModelLogarithmic: - - distance = getMax( distance, minDistance ); - distance = getMin( distance, maxDistance ); - - gain = minDistance / ( minDistance + rolloffFactor * ( distance - minDistance ) ); - break; + case SFXDistanceModelLinear: - ///create exponential distance model - case SFXDistanceModelExponent: - distance = getMax(distance, minDistance); - distance = getMin(distance, maxDistance); + distance = getMax(distance, minDistance); + distance = getMin(distance, maxDistance); + + gain = (1 - rolloffFactor * (distance - minDistance) / (maxDistance - minDistance)); + break; + + case SFXDistanceModelLogarithmic: + + distance = getMax(distance, minDistance); + distance = getMin(distance, maxDistance); + + gain = minDistance / (minDistance + rolloffFactor * (distance - minDistance)); + break; + + ///create exponential distance model + case SFXDistanceModelExponent: + distance = getMax(distance, minDistance); + distance = getMin(distance, maxDistance); + + gain = pow((distance / minDistance), (-rolloffFactor)); + break; - gain = pow((distance / minDistance), (-rolloffFactor)); - break; - } - - return ( volume * gain ); + + return (volume * gain); } //----------------------------------------------------------------------------- // SFXFormat. //----------------------------------------------------------------------------- - +enum SFXSampleType { + Sample_Int8, + Sample_Int16, + Sample_Float, + Sample_IMA4, + Sample_MSADPCM +}; /// This class defines the various types of sound data that may be /// used in the sound system. @@ -216,101 +246,111 @@ inline F32 SFXDistanceAttenuation( SFXDistanceModel model, F32 minDistance, F32 /// channel. class SFXFormat { - protected: +protected: - /// The number of sound channels in the data. - U8 mChannels; + /// The number of sound channels in the data. + U8 mChannels; - /// The number of bits per sound sample. - U8 mBitsPerSample; + /// The number of bits per sound sample. + U8 mBitsPerSample; - /// The frequency in samples per second. - U32 mSamplesPerSecond; + /// The frequency in samples per second. + U32 mSamplesPerSecond; - public: + SFXSampleType mSampleType; +public: - SFXFormat( U8 channels = 0, - U8 bitsPerSample = 0, - U32 samplesPerSecond = 0 ) - : mChannels( channels ), - mBitsPerSample( bitsPerSample ), - mSamplesPerSecond( samplesPerSecond ) - {} + SFXFormat(U8 channels = 0, + U8 bitsPerSample = 0, + U32 samplesPerSecond = 0) + : mChannels(channels), + mBitsPerSample(bitsPerSample), + mSamplesPerSecond(samplesPerSecond), + mSampleType(SFXSampleType::Sample_Int16) + { + } - /// Copy constructor. - SFXFormat( const SFXFormat &format ) - : mChannels( format.mChannels ), - mBitsPerSample( format.mBitsPerSample ), - mSamplesPerSecond( format.mSamplesPerSecond ) - {} + /// Copy constructor. + SFXFormat(const SFXFormat& format) + : mChannels(format.mChannels), + mBitsPerSample(format.mBitsPerSample), + mSamplesPerSecond(format.mSamplesPerSecond), + mSampleType(format.mSampleType) + { + } - public: +public: - /// Sets the format. - void set( U8 channels, - U8 bitsPerSample, - U32 samplesPerSecond ) - { - mChannels = channels; - mBitsPerSample = bitsPerSample; - mSamplesPerSecond = samplesPerSecond; - } + /// Sets the format. + void set(U8 channels, + U8 bitsPerSample, + U32 samplesPerSecond, + SFXSampleType sampleType = Sample_Int16) + { + mChannels = channels; + mBitsPerSample = bitsPerSample; + mSamplesPerSecond = samplesPerSecond; + mSampleType = sampleType; + } - /// Comparision between formats. - bool operator == ( const SFXFormat& format ) const - { - return mChannels == format.mChannels && - mBitsPerSample == format.mBitsPerSample && - mSamplesPerSecond == format.mSamplesPerSecond; - } + /// Comparision between formats. + bool operator == (const SFXFormat& format) const + { + return mChannels == format.mChannels && + mBitsPerSample == format.mBitsPerSample && + mSamplesPerSecond == format.mSamplesPerSecond && + mSampleType == format.mSampleType; + } - /// Returns the number of sound channels. - U8 getChannels() const { return mChannels; } + /// Returns the number of sound channels. + U8 getChannels() const { return mChannels; } - /// Returns true if there is a single sound channel. - bool isMono() const { return mChannels == 1; } + /// Returns true if there is a single sound channel. + bool isMono() const { return mChannels == 1; } - /// Is true if there are two sound channels. - bool isStereo() const { return mChannels == 2; } + /// Is true if there are two sound channels. + bool isStereo() const { return mChannels == 2; } - /// Is true if there are more than two sound channels. - bool isMultiChannel() const { return mChannels > 2; } + /// Is true if there are more than two sound channels. + bool isMultiChannel() const { return mChannels > 2; } - /// - U32 getSamplesPerSecond() const { return mSamplesPerSecond; } + /// + U32 getSamplesPerSecond() const { return mSamplesPerSecond; } - /// The bits of data per channel. - U8 getBitsPerChannel() const { return mBitsPerSample / mChannels; } + /// The bits of data per channel. + U8 getBitsPerChannel() const { return mBitsPerSample / mChannels; } - /// The number of bytes of data per channel. - U8 getBytesPerChannel() const { return getBitsPerChannel() / 8; } + /// The number of bytes of data per channel. + U8 getBytesPerChannel() const { return getBitsPerChannel() / 8; } - /// The number of bits per sound sample. - U8 getBitsPerSample() const { return mBitsPerSample; } + /// The number of bits per sound sample. + U8 getBitsPerSample() const { return mBitsPerSample; } - /// The number of bytes of data per sample. - /// @note Be aware that this comprises all channels. - U8 getBytesPerSample() const { return mBitsPerSample / 8; } + SFXSampleType getSampleType() const { return mSampleType; } - /// Returns the duration from the sample count. - U32 getDuration( U32 samples ) const - { - // Use 64bit types to avoid overflow during division. - return ( (U64)samples * (U64)1000 ) / (U64)mSamplesPerSecond; - } + /// The number of bytes of data per sample. + /// @note Be aware that this comprises all channels. + U8 getBytesPerSample() const { return mBitsPerSample / 8; } - /// - U32 getSampleCount( U32 ms ) const - { - return U64( mSamplesPerSecond ) * U64( ms ) / U64( 1000 ); - } + /// Returns the duration from the sample count. + U32 getDuration(U32 samples) const + { + // Use 64bit types to avoid overflow during division. + return ((U64)samples * (U64)1000) / (U64)mSamplesPerSecond; + } - /// Returns the data length in bytes. - U32 getDataLength( U32 ms ) const - { - U32 bytes = ( ( (U64)ms * (U64)mSamplesPerSecond ) * (U64)getBytesPerSample() ) / (U64)1000; - return bytes; - } + /// + U32 getSampleCount(U32 ms) const + { + return U64(mSamplesPerSecond) * U64(ms) / U64(1000); + } + + /// Returns the data length in bytes. + U32 getDataLength(U32 ms) const + { + U32 bytes = (((U64)ms * (U64)mSamplesPerSecond) * (U64)getBytesPerSample()) / (U64)1000; + return bytes; + } }; @@ -363,8 +403,8 @@ public: flGain = 0.0f; flGainHF = 0.0f; flGainLF = 0.0000f; - flDecayTime = 0.0f; - flDecayHFRatio = 0.0f; + flDecayTime = 0.1f; + flDecayHFRatio = 0.1f; flDecayLFRatio = 0.0f; flReflectionsGain = 0.0f; flReflectionsDelay = 0.0f; @@ -372,15 +412,17 @@ public: flLateReverbGain = 0.0f; flLateReverbDelay = 0.0f; dMemset(flLateReverbPan, 0, sizeof(flLateReverbPan)); - flEchoTime = 0.0f; + flEchoTime = 0.075f; flEchoDepth = 0.0f; - flModulationTime = 0.0f; + flModulationTime = 0.04f; flModulationDepth = 0.0f; - flAirAbsorptionGainHF = 0.0f; + flAirAbsorptionGainHF = 0.892f; flHFReference = 0.0f; flLFReference = 0.0f; flRoomRolloffFactor = 0.0f; iDecayHFLimit = 0; + + validate(); } void validate() @@ -528,31 +570,33 @@ public: /// class SFXListenerProperties { - public: - - typedef void Parent; - - /// Position and orientation of the listener. - MatrixF mTransform; - - /// - Point3F mVelocity; +public: - SFXListenerProperties() - : mTransform( true ), - mVelocity( 0.0f, 0.0f, 0.0f ) {} - - SFXListenerProperties( const MatrixF& transform, const Point3F& velocity ) - : mTransform( transform ), - mVelocity( velocity ) {} - - /// - const MatrixF& getTransform() const { return mTransform; } - MatrixF& getTransform() { return mTransform; } - - /// - const Point3F& getVelocity() const { return mVelocity; } - Point3F& getVelocity() { return mVelocity; } + typedef void Parent; + + /// Position and orientation of the listener. + MatrixF mTransform; + + /// + Point3F mVelocity; + + SFXListenerProperties() + : mTransform(true), + mVelocity(0.0f, 0.0f, 0.0f) { + } + + SFXListenerProperties(const MatrixF& transform, const Point3F& velocity) + : mTransform(transform), + mVelocity(velocity) { + } + + /// + const MatrixF& getTransform() const { return mTransform; } + MatrixF& getTransform() { return mTransform; } + + /// + const Point3F& getVelocity() const { return mVelocity; } + Point3F& getVelocity() { return mVelocity; } }; @@ -564,29 +608,30 @@ class SFXListenerProperties /// class SFXMaterialProperties { - public: - - typedef void Parent; - - /// - bool mDoubleSided; - - /// - F32 mDirectOcclusion; - - /// - F32 mReverbOcclusion; - - SFXMaterialProperties() - : mDoubleSided( false ), - mDirectOcclusion( 0.5f ), - mReverbOcclusion( 0.5f ) {} - - void validate() - { - mDirectOcclusion = mClampF( mDirectOcclusion, 0.0f, 1.0f ); - mReverbOcclusion = mClampF( mReverbOcclusion, 0.0f, 1.0f ); - } +public: + + typedef void Parent; + + /// + bool mDoubleSided; + + /// + F32 mDirectOcclusion; + + /// + F32 mReverbOcclusion; + + SFXMaterialProperties() + : mDoubleSided(false), + mDirectOcclusion(0.5f), + mReverbOcclusion(0.5f) { + } + + void validate() + { + mDirectOcclusion = mClampF(mDirectOcclusion, 0.0f, 1.0f); + mReverbOcclusion = mClampF(mReverbOcclusion, 0.0f, 1.0f); + } }; @@ -600,28 +645,28 @@ template< S32 NUM_VALUES > struct SFXVariantFloat { /// Base value. - F32 mValue[ NUM_VALUES ]; - + F32 mValue[NUM_VALUES]; + /// Variance of value. Final value will be /// /// mClampF( randF( mValue + mVariance[ 0 ], mValue + mVariance[ 1 ] ), min, max ) /// /// with min and max being dependent on the context of the value. - F32 mVariance[ NUM_VALUES ][ 2 ]; - - F32 getValue( U32 index = 0, F32 min = TypeTraits< F32 >::MIN, F32 max = TypeTraits< F32 >::MAX ) const + F32 mVariance[NUM_VALUES][2]; + + F32 getValue(U32 index = 0, F32 min = TypeTraits< F32 >::MIN, F32 max = TypeTraits< F32 >::MAX) const { - AssertFatal( index < NUM_VALUES, "SFXVariantFloat::getValue() - index out of range!" ); - - return mClampF( gRandGen.randF( mValue[ index ] + mVariance[ index ][ 0 ], - mValue[ index ] + mVariance[ index ][ 1 ] ), - min, max ); + AssertFatal(index < NUM_VALUES, "SFXVariantFloat::getValue() - index out of range!"); + + return mClampF(gRandGen.randF(mValue[index] + mVariance[index][0], + mValue[index] + mVariance[index][1]), + min, max); } - + void validate() { - for( U32 i = 0; i < NUM_VALUES; ++ i ) - mVariance[ i ][ 0 ] = getMin( mVariance[ i ][ 0 ], mVariance[ i ][ 1 ] ); + for (U32 i = 0; i < NUM_VALUES; ++i) + mVariance[i][0] = getMin(mVariance[i][0], mVariance[i][1]); } }; diff --git a/Engine/source/sfx/sfxDescription.cpp b/Engine/source/sfx/sfxDescription.cpp index 4bb152441..a4f0a616f 100644 --- a/Engine/source/sfx/sfxDescription.cpp +++ b/Engine/source/sfx/sfxDescription.cpp @@ -173,7 +173,6 @@ SFXDescription::SFXDescription( const SFXDescription& desc ) mStreamPacketSize( desc.mStreamPacketSize ), mUseReverb( desc.mUseReverb ), mStreamReadAhead( desc.mStreamReadAhead ), - mReverb( desc.mReverb ), mScatterDistance( desc.mScatterDistance ), mPriority( desc.mPriority ) { @@ -206,7 +205,6 @@ SFXDescription::SFXDescription(const SFXDescription& other, bool temp_clone) mStreamPacketSize( other.mStreamPacketSize ), mStreamReadAhead( other.mStreamReadAhead ), mUseReverb( other.mUseReverb ), - mReverb( other.mReverb ), mPriority( other.mPriority ), mScatterDistance( other.mScatterDistance ) { @@ -396,48 +394,6 @@ void SFXDescription::initPersistFields() "a custom reverb setup can be defined using the \"Reverb\" properties that will then be assigned " "to sounds playing with the description.\n\n" "@ref SFX_reverb"); - addFieldV("reverbDensity", TypeRangedF32, Offset(mReverb.flDensity, SFXDescription), &CommonValidators::PositiveFloat, - "Density of reverb environment."); - addFieldV("reverbDiffusion", TypeRangedF32, Offset(mReverb.flDiffusion, SFXDescription), &CommonValidators::PositiveFloat, - "Environment diffusion."); - addFieldV("reverbGain", TypeRangedF32, Offset(mReverb.flGain, SFXDescription), &CommonValidators::PositiveFloat, - "Reverb Gain Level."); - addFieldV("reverbGainHF", TypeRangedF32, Offset(mReverb.flGainHF, SFXDescription), &CommonValidators::PositiveFloat, - "Reverb Gain to high frequencies"); - addFieldV("reverbGainLF", TypeRangedF32, Offset(mReverb.flGainLF, SFXDescription), &CommonValidators::PositiveFloat, - "Reverb Gain to high frequencies"); - addFieldV("reverbDecayTime", TypeRangedF32, Offset(mReverb.flDecayTime, SFXDescription), &CommonValidators::PositiveFloat, - "Decay time for the reverb."); - addFieldV("reverbDecayHFRatio", TypeRangedF32, Offset(mReverb.flDecayHFRatio, SFXDescription), &CommonValidators::PositiveFloat, - "High frequency decay time ratio."); - addFieldV("reverbDecayLFRatio", TypeRangedF32, Offset(mReverb.flDecayLFRatio, SFXDescription), &CommonValidators::PositiveFloat, - "High frequency decay time ratio."); - addFieldV("reflectionsGain", TypeRangedF32, Offset(mReverb.flReflectionsGain, SFXDescription), &CommonValidators::PositiveFloat, - "Reflection Gain."); - addFieldV("reflectionDelay", TypeRangedF32, Offset(mReverb.flReflectionsDelay, SFXDescription), &CommonValidators::PositiveFloat, - "How long to delay reflections."); - addFieldV("lateReverbGain", TypeRangedF32, Offset(mReverb.flLateReverbGain, SFXDescription), &CommonValidators::PositiveFloat, - "Late reverb gain amount."); - addFieldV("lateReverbDelay", TypeRangedF32, Offset(mReverb.flLateReverbDelay, SFXDescription), &CommonValidators::PositiveFloat, - "Late reverb delay time."); - addFieldV("reverbEchoTime", TypeRangedF32, Offset(mReverb.flEchoTime, SFXDescription), &CommonValidators::PositiveFloat, - "Reverb echo time."); - addFieldV("reverbEchoDepth", TypeRangedF32, Offset(mReverb.flEchoDepth, SFXDescription), &CommonValidators::PositiveFloat, - "Reverb echo depth."); - addFieldV("reverbModTime", TypeRangedF32, Offset(mReverb.flModulationTime, SFXDescription), &CommonValidators::PositiveFloat, - "Reverb Modulation time."); - addFieldV("reverbModDepth", TypeRangedF32, Offset(mReverb.flModulationDepth, SFXDescription), &CommonValidators::NormalizedFloat, - "Reverb Modulation Depth."); - addFieldV("airAbsorbtionGainHF", TypeRangedF32, Offset(mReverb.flAirAbsorptionGainHF, SFXDescription), &CommonValidators::PositiveFloat, - "High Frequency air absorbtion"); - addFieldV("reverbHFRef", TypeRangedF32, Offset(mReverb.flHFReference, SFXDescription), &CommonValidators::PositiveFloat, - "Reverb High Frequency Reference."); - addFieldV("reverbLFRef", TypeRangedF32, Offset(mReverb.flLFReference, SFXDescription), &CommonValidators::PositiveFloat, - "Reverb Low Frequency Reference."); - addFieldV("roomRolloffFactor", TypeRangedF32, Offset(mReverb.flRoomRolloffFactor, SFXDescription), &CommonValidators::NegDefaultF32, - "Rolloff factor for reverb."); - addFieldV("decayHFLimit", TypeRangedS32, Offset(mReverb.iDecayHFLimit, SFXDescription), &CommonValidators::PositiveInt, - "High Frequency decay limit."); endGroup("Reverb"); Parent::initPersistFields(); @@ -496,10 +452,6 @@ void SFXDescription::validate() mConeOutsideAngle = mClamp( mConeOutsideAngle, mConeInsideAngle, 360 ); mConeOutsideVolume = mClampF( mConeOutsideVolume, 0, 1 ); - if( !mIs3D ) - mUseReverb = false; - - mReverb.validate(); } //----------------------------------------------------------------------------- @@ -534,30 +486,6 @@ void SFXDescription::packData( BitStream *stream ) stream->writeFloat( mConeOutsideVolume, 6 ); - if( mUseReverb ) - { - stream->write(mReverb.flDensity); - stream->write(mReverb.flDiffusion); - stream->write(mReverb.flGain); - stream->write(mReverb.flGainHF); - stream->write(mReverb.flGainLF); - stream->write(mReverb.flDecayTime); - stream->write(mReverb.flDecayHFRatio); - stream->write(mReverb.flDecayLFRatio); - stream->write(mReverb.flReflectionsGain); - stream->write(mReverb.flReflectionsDelay); - stream->write(mReverb.flLateReverbGain); - stream->write(mReverb.flLateReverbDelay); - stream->write(mReverb.flEchoTime); - stream->write(mReverb.flEchoDepth); - stream->write(mReverb.flModulationTime); - stream->write(mReverb.flModulationDepth); - stream->write(mReverb.flAirAbsorptionGainHF); - stream->write(mReverb.flHFReference); - stream->write(mReverb.flLFReference); - stream->write(mReverb.flRoomRolloffFactor); - stream->write(mReverb.iDecayHFLimit); - } } stream->write( mFadeInTime ); @@ -607,30 +535,6 @@ void SFXDescription::unpackData( BitStream *stream ) mConeOutsideVolume = stream->readFloat( 6 ); - if( mUseReverb ) - { - stream->read(&mReverb.flDensity); - stream->read(&mReverb.flDiffusion); - stream->read(&mReverb.flGain); - stream->read(&mReverb.flGainHF); - stream->read(&mReverb.flGainLF); - stream->read(&mReverb.flDecayTime); - stream->read(&mReverb.flDecayHFRatio); - stream->read(&mReverb.flDecayLFRatio); - stream->read(&mReverb.flReflectionsGain); - stream->read(&mReverb.flReflectionsDelay); - stream->read(&mReverb.flLateReverbGain); - stream->read(&mReverb.flLateReverbDelay); - stream->read(&mReverb.flEchoTime); - stream->read(&mReverb.flEchoDepth); - stream->read(&mReverb.flModulationTime); - stream->read(&mReverb.flModulationDepth); - stream->read(&mReverb.flAirAbsorptionGainHF); - stream->read(&mReverb.flHFReference); - stream->read(&mReverb.flLFReference); - stream->read(&mReverb.flRoomRolloffFactor); - stream->read(&mReverb.iDecayHFLimit); - } } stream->read( &mFadeInTime ); diff --git a/Engine/source/sfx/sfxDescription.h b/Engine/source/sfx/sfxDescription.h index 8f4d31134..dc0aecc20 100644 --- a/Engine/source/sfx/sfxDescription.h +++ b/Engine/source/sfx/sfxDescription.h @@ -170,9 +170,6 @@ class SFXDescription : public SimDataBlock /// The number of streaming packets to read and buffer in advance. /// Only relevant if "isStreaming" is true. U32 mStreamReadAhead; - - /// Reverb properties for sound playback. - SFXSoundReverbProperties mReverb; /// Parameters to which sources playing with this description should automatically /// connect when created. @@ -202,4 +199,4 @@ class SFXDescription : public SimDataBlock }; -#endif // _SFXDESCRIPTION_H_ \ No newline at end of file +#endif // _SFXDESCRIPTION_H_ diff --git a/Engine/source/sfx/sfxDevice.cpp b/Engine/source/sfx/sfxDevice.cpp index a069b0564..0c5d2c8ee 100644 --- a/Engine/source/sfx/sfxDevice.cpp +++ b/Engine/source/sfx/sfxDevice.cpp @@ -29,20 +29,55 @@ #include "console/consoleTypes.h" -//----------------------------------------------------------------------------- +S32 SFXDevice::smUpdateInterval = SFXInternal::DEFAULT_UPDATE_INTERVAL; +S32 SFXDevice::smDeviceFrequency = 44100; +S32 SFXDevice::smMaxSendsPerSource = 4; +S32 SFXDevice::smMaxEffectSlots = 4; +S32 SFXDevice::smDeviceHRTFProfile = -1; +S8 SFXDevice::smDeviceBitrate = 16; +bool SFXDevice::smDeviceHRTF = false; -SFXDevice::SFXDevice( const String& name, SFXProvider* provider, bool useHardware, S32 maxBuffers ) - : mName( name ), - mProvider( provider ), - mUseHardware( useHardware ), - mMaxBuffers( maxBuffers ), - mCaps( 0 ), - mStatNumBuffers( 0 ), - mStatNumVoices( 0 ), - mStatNumBufferBytes( 0 ) +void SFXDevice::initConsole() { - AssertFatal( provider, "We must have a provider pointer on device creation!" ); + // Add global preferences for sfx devices. + Con::addVariable("$pref::SFX::bitrate", TypeS8, &smDeviceBitrate, + "The devices bitrate.\n" + "@ingroup SFX\n"); + Con::addVariable("$pref::SFX::frequency", TypeS32, &smDeviceFrequency, + "The devices frequency.\n" + "@ingroup SFX\n"); + + Con::addVariable("$pref::SFX::useHRTF", TypeBool, &smDeviceHRTF, + "The device uses hrtf.\n" + "@ingroup SFX\n"); + + Con::addVariable("$pref::SFX::hrtfProfile", TypeS32, &smDeviceHRTFProfile, + "Index of the HRTF profile to use. -1 = driver default. " + "Use sfxGetHRTFProfileCount/sfxGetHRTFProfileName to enumerate available profiles.\n" + "@ingroup SFX\n"); + + Con::addVariable("$pref::SFX::updateInterval", TypeS32, &smUpdateInterval, + "The update interval.\n" + "@ingroup SFX\n"); + + Con::addVariable("$pref::SFX::maxSendsPerSource", TypeS32, &smMaxSendsPerSource, + "The maximum number sends allowed per source.\n" + "@ingroup SFX\n"); + + Con::addVariable("$pref::SFX::maxEffectSlots", TypeS32, &smMaxEffectSlots, + "The maximum number of effect slots supported by this device.\n" + "@ingroup SFX\n"); +} + +SFXDevice::SFXDevice() + : mStatNumBuffers( 0 ), + mStatNumVoices( 0 ), + mStatNumBufferBytes( 0 ), + mMaxBuffers(16), + mUseHardware(false), + mCaps(0) +{ VECTOR_SET_ASSOCIATION( mBuffers ); VECTOR_SET_ASSOCIATION( mVoices ); @@ -54,8 +89,6 @@ SFXDevice::SFXDevice( const String& name, SFXProvider* provider, bool useHardwar Con::addVariable( "SFX::Device::numBufferBytes", TypeS32, &mStatNumBufferBytes ); } -//----------------------------------------------------------------------------- - SFXDevice::~SFXDevice() { Con::removeVariable( "SFX::Device::numBuffers" ); @@ -78,13 +111,13 @@ void SFXDevice::_releaseAllResources() ThreadSafeRef< SFXUpdateThread > sfxThread = UPDATE_THREAD(); if( sfxThread != NULL ) { - gUpdateThread = NULL; // Kill the global reference. - sfxThread->stop(); sfxThread->triggerUpdate(); sfxThread->join(); sfxThread = NULL; + gUpdateThread = NULL; // Kill the global reference. + } // Clean up voices. Do this before cleaning up buffers so that @@ -92,9 +125,11 @@ void SFXDevice::_releaseAllResources() // get released properly. SFXVoice::smVoiceDestroyedSignal.remove( this, &SFXDevice::_removeVoice ); - for( VoiceIterator voice = mVoices.begin(); - voice != mVoices.end(); voice++ ) - ( *voice )->destroySelf(); + for (VoiceIterator voice = mVoices.begin(); voice != mVoices.end(); voice++) + { + (*voice)->stop(); + (*voice)->destroySelf(); + } mVoices.clear(); // Clean up buffers. diff --git a/Engine/source/sfx/sfxDevice.h b/Engine/source/sfx/sfxDevice.h index a2389f587..d75d6aacf 100644 --- a/Engine/source/sfx/sfxDevice.h +++ b/Engine/source/sfx/sfxDevice.h @@ -23,21 +23,19 @@ #ifndef _SFXDEVICE_H_ #define _SFXDEVICE_H_ +#ifndef _SFXPROVIDER_H_ +#include "sfx/sfxProvider.h" +#endif #ifndef _PLATFORM_H_ #include "platform/platform.h" #endif #ifndef _TVECTOR_H_ #include "core/util/tVector.h" #endif -#ifndef _SFXCOMMON_H_ - #include "sfx/sfxCommon.h" -#endif #ifndef _THREADSAFEREF_H_ #include "platform/threads/threadSafeRefCount.h" #endif - -class SFXProvider; class SFXListener; class SFXBuffer; class SFXVoice; @@ -46,8 +44,6 @@ class SFXDevice; class SFXStream; class SFXDescription; - - /// Abstract base class for back-end sound API implementations. class SFXDevice { @@ -58,13 +54,43 @@ class SFXDevice /// Device capability flags. enum ECaps { - CAPS_Reverb = BIT( 0 ), ///< Device supports reverb environments. - CAPS_VoiceManagement = BIT( 1 ), ///< Device manages voices on its own; deactivates virtualization code in SFX system. - CAPS_Occlusion = BIT( 2 ), ///< Device has its own sound occlusion handling (SFXOcclusionManager). - CAPS_DSPEffects = BIT( 3 ), ///< Device implements DSP effects (SFXDSPManager). - CAPS_MultiListener = BIT( 4 ), ///< Device supports multiple listeners. + CAPS_Reverb = BIT(0), ///< Device supports reverb environments. + CAPS_EXTReverb = BIT(1), ///< Device supports extended reverb environments. + CAPS_VoiceManagement = BIT(2), ///< Device manages voices on its own; deactivates virtualization code in SFX system. + CAPS_Occlusion = BIT(3), ///< Device has its own sound occlusion handling (SFXOcclusionManager). + CAPS_DSPEffects = BIT(4), ///< Device implements DSP effects (SFXDSPManager). + CAPS_MultiListener = BIT(5), ///< Device supports multiple listeners. + CAPS_HRTF = BIT(6), ///< Device supports HRTF (3D audio positioning). + CAPS_Float32 = BIT(7), ///< Device supports 32-bit float playback. + CAPS_MonoStereo = BIT(8), ///< Device supports mono/stereo output modes. + CAPS_EFX_EQ = BIT(9), ///< Device Supports Equalizer effect + CAPS_EFX_Compressor = BIT(10), ///< Device Supports Compressor effect + CAPS_EFX_Echo = BIT(11), ///< Device Supports Echo effect + CAPS_EFX_Chorus = BIT(12), ///< Device Supports Chorus effect + CAPS_EFX_Distortion = BIT(13), ///< Device Supports Distortion effect + CAPS_EFX_Flanger = BIT(14), ///< Device Supports Flanger effect + CAPS_SourceFilters = BIT(15), ///< Device Supports Per-source send filters (low/high/band pass) + CAPS_SourceSpatialize = BIT(16), ///< Device Supports Explicit per-source spatialize control + CAPS_HotReconnect = BIT(17), ///< Device Supports Device can be reopened without destroying context + CAPS_DeviceClock = BIT(18), ///< Device Supports High precision device clock + CAPS_DisconnectDetect = BIT(19), ///< Device Can detect hardware disconnection }; + + static void initConsole(); + static S32 smUpdateInterval; + /// The device frequency, used when reading in buffers for the device. + static S32 smDeviceFrequency; + /// The device hrtf profile to use. + static S32 smDeviceHRTFProfile; + /// The device bitrate. + static S8 smDeviceBitrate; + /// Does the device use hrtf + static bool smDeviceHRTF; + /// How many effect slots does this device support. + static S32 smMaxEffectSlots; + /// How many sends can each source have. + static S32 smMaxSendsPerSource; protected: typedef Vector< SFXBuffer* > BufferVector; @@ -73,11 +99,6 @@ class SFXDevice typedef BufferVector::iterator BufferIterator; typedef VoiceVector::iterator VoiceIterator; - SFXDevice( const String& name, SFXProvider* provider, bool useHardware, S32 maxBuffers ); - - /// The name of this device. - String mName; - /// The provider which created this device. SFXProvider* mProvider; @@ -125,11 +146,12 @@ class SFXDevice void _releaseAllResources(); public: - + SFXDevice(); virtual ~SFXDevice(); /// Returns the provider which created this device. - SFXProvider* getProvider() const { return mProvider; } + virtual SFXProvider* getProvider() { return mProvider; } + virtual void setProvider(SFXProvider* provider) { mProvider = provider; } /// Is the device set to use hardware processing. bool getUseHardware() const { return mUseHardware; } @@ -138,7 +160,7 @@ public: S32 getMaxBuffers() const { return mMaxBuffers; } /// Returns the name of this device. - const String& getName() const { return mName; } + const String& getName() const { return mProvider->getName(); } /// Return the device capability flags. U32 getCaps() const { return mCaps; } @@ -174,6 +196,9 @@ public: /// Set the scale factor to use for doppler effects on 3D sounds. virtual void setDopplerFactor( F32 factor ) {} + + /// Set the speed of sound for the device. + virtual void setSpeedOfSound(F32 speedOfSound) {} /// Set the rolloff scale factor for distance attenuation of 3D sounds. virtual void setRolloffFactor( F32 factor ) {} @@ -183,6 +208,9 @@ public: /// Set the global reverb environment. virtual void setReverb( const SFXReverbProperties& reverb ) {} + + virtual bool isDeviceConnected() { return true; } + virtual bool reconnectDevice(U32 provider) { return false; } /// Reset the global reverb environment to its default. virtual void resetReverb() {} diff --git a/Engine/source/sfx/sfxProvider.cpp b/Engine/source/sfx/sfxProvider.cpp deleted file mode 100644 index 73de67d44..000000000 --- a/Engine/source/sfx/sfxProvider.cpp +++ /dev/null @@ -1,95 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "core/strings/stringFunctions.h" -#include "sfx/sfxProvider.h" - -SFXProvider* SFXProvider::smProviders = NULL; -Vector SFXProvider::sAllProviders( __FILE__, __LINE__ ); - -SFXProvider* SFXProvider::findProvider( String providerName ) -{ - if( providerName.isEmpty() ) - return NULL; - - SFXProvider* curr = smProviders; - for ( ; curr != NULL; curr = curr->mNextProvider ) - { - if( curr->getName().equal( providerName, String::NoCase ) ) - return curr; - } - - return NULL; -} - -void SFXProvider::regProvider( SFXProvider* provider ) -{ - AssertFatal( provider, "Got null provider!" ); - AssertFatal( findProvider( provider->getName() ) == NULL, "Can't register provider twice!" ); - AssertFatal( provider->mNextProvider == NULL, "Can't register provider twice!" ); - - SFXProvider* oldHead = smProviders; - smProviders = provider; - provider->mNextProvider = oldHead; -} - -SFXProvider::SFXProvider( const String& name ) - : mNextProvider( NULL ), - mName( name ) -{ - VECTOR_SET_ASSOCIATION( mDeviceInfo ); - - sAllProviders.push_back( this ); -} - -void SFXProvider::initializeAllProviders() -{ - - for (U32 i = 0; i < sAllProviders.size(); i++) - sAllProviders[i]->init(); - -} - -SFXProvider::~SFXProvider() -{ - SFXDeviceInfoVector::iterator iter = mDeviceInfo.begin(); - for ( ; iter != mDeviceInfo.end(); iter++ ) - delete *iter; -} - -SFXDeviceInfo* SFXProvider::_findDeviceInfo( const String& deviceName ) -{ - SFXDeviceInfoVector::iterator iter = mDeviceInfo.begin(); - for ( ; iter != mDeviceInfo.end(); iter++ ) - { - if( deviceName.equal( ( *iter )->name, String::NoCase ) ) - return *iter; - } - - // If not found and deviceName is empty, - // return first (default) device. - - if( deviceName.isEmpty() && mDeviceInfo.size() > 0 ) - return mDeviceInfo[ 0 ]; - - return NULL; -} diff --git a/Engine/source/sfx/sfxProvider.h b/Engine/source/sfx/sfxProvider.h index 34cbc832c..aa4209be9 100644 --- a/Engine/source/sfx/sfxProvider.h +++ b/Engine/source/sfx/sfxProvider.h @@ -23,102 +23,44 @@ #ifndef _SFXPROVIDER_H_ #define _SFXPROVIDER_H_ -#ifndef _TVECTOR_H_ - #include "core/util/tVector.h" +#ifndef _SFXCOMMON_H_ +#include "sfx/sfxCommon.h" #endif +#ifndef _TVECTOR_H_ +#include "core/util/tVector.h" +#endif + +#ifndef _UTIL_DELEGATE_H_ +#include "core/util/delegate.h" +#endif class SFXDevice; - - -struct SFXDeviceInfo +struct SFXProvider { - String driver; - String internalName; - String name; - bool hasHardware = false; - S32 maxBuffers =0; +public: + typedef Delegate CreateProviderInstanceDelegate; - virtual ~SFXDeviceInfo() {} -}; + String mName; + bool mHasHardware; + SFXProviderType mType; + SFXDeviceType mDeviceType; + U32 mIndex; + bool mDefault; + CreateProviderInstanceDelegate mCreateDeviceInstanceDelegate; -typedef Vector SFXDeviceInfoVector; - -class SFXProvider -{ - friend class SFXSystem; - - private: - - /// The head of the linked list of avalible providers. - static SFXProvider* smProviders; - - /// The next provider in the linked list of available providers. - SFXProvider* mNextProvider; - - /// The provider name which is passed by the concrete provider - /// class to the SFXProvider constructor. - String mName; - - static Vector sAllProviders; - - protected: - - /// The array of avaIlable devices from this provider. The - /// concrete provider class will fill this on construction. - SFXDeviceInfoVector mDeviceInfo; - - /// This registers the provider to the available provider list. It should be called - /// for providers that are properly initialized and available for device enumeration and creation. - /// the add and registration process is 2 steps to avoid issues when TGEA is used as a shared library (specifically on Windows) - static void regProvider( SFXProvider* provider ); - - virtual void init() = 0; - - SFXProvider( const String& name ); - ~SFXProvider(); - - /// Look up the SFXDeviceInfo for the given device in mDeviceInfo. - /// Return default device (first in list) if no other device matches (or null if device list is empty). - SFXDeviceInfo* _findDeviceInfo( const String& deviceName ); - - /// This is called from SFXSystem to create a new device. Must be implemented - /// by all contrete provider classes. - /// - /// @param deviceName The case sensitive name of the device or NULL to create the - // default device. - /// @param useHardware Toggles the use of hardware processing when available. - /// @param maxBuffers The maximum buffers for this device to use or -1 - /// for the device to pick a reasonable default for that device. - /// - /// @return Returns the created device or NULL for failure. - /// - virtual SFXDevice* createDevice( const String& deviceName, bool useHardware, S32 maxBuffers ) = 0; - - public: - - /// Returns a specific provider by searching the provider list - /// for the first provider with the case sensitive name. - static SFXProvider* findProvider( String providerName ); - - /// Returns the first provider in the provider list. Use - /// getNextProvider() to iterate over list. - static SFXProvider* getFirstProvider() { return smProviders; } - - /// Returns the next provider in the provider list or NULL - /// when the end of the list is reached. - SFXProvider* getNextProvider() const { return mNextProvider; } - - /// The case sensitive name of this provider. - const String& getName() const { return mName; } - - /// Returns a read only vector with device information for - /// all creatable devices available from this provider. - const SFXDeviceInfoVector& getDeviceInfo() const { return mDeviceInfo; } - - static void initializeAllProviders(); + const char* getName() const { return mName; } + SFXProvider() + { + mName = String::EmptyString; + mHasHardware = false; + mType = NullProvider; + mIndex = 0; + mDefault = false; + mDeviceType = Output; + } }; diff --git a/Engine/source/sfx/sfxSound.cpp b/Engine/source/sfx/sfxSound.cpp index 447eb993b..32b580013 100644 --- a/Engine/source/sfx/sfxSound.cpp +++ b/Engine/source/sfx/sfxSound.cpp @@ -261,11 +261,6 @@ bool SFXSound::_allocVoice( SFXDevice* device ) _setCone( mConeInsideAngle, mConeOutsideAngle, mConeOutsideVolume ); } - // Set reverb, if enabled. - - if( mDescription->mUseReverb ) - mVoice->setReverb( mDescription->mReverb ); - // Update the duration... it shouldn't have changed, but // its probably better that we're accurate if it did. mDuration = mBuffer->getDuration(); @@ -395,8 +390,10 @@ void SFXSound::_play() { Parent::_play(); - if( mVoice ) - mVoice->play( isLooping() ); + if (mVoice) + { + mVoice->play(isLooping()); + } else { // To ensure the fastest possible reaction @@ -447,6 +444,11 @@ void SFXSound::_updateStatus() if( mVoice ) { + + // properties can change while a voice is playing, respect that. + if (getSourceGroup()) + mVoice->setReverb(getSourceGroup()->getDescription()->mUseReverb); + SFXStatus voiceStatus = mVoice->getStatus(); // Filter out SFXStatusBlocked. diff --git a/Engine/source/sfx/sfxSoundscape.cpp b/Engine/source/sfx/sfxSoundscape.cpp index b65c573d7..48b448e91 100644 --- a/Engine/source/sfx/sfxSoundscape.cpp +++ b/Engine/source/sfx/sfxSoundscape.cpp @@ -131,14 +131,30 @@ void SFXSoundscapeManager::update() SFXAmbience* ambience = mStack[ reverbIndex ]->getAmbience(); AssertFatal( ambience->getEnvironment(), "SFXSoundscapeManager::update - Reverb lookup return ambience without reverb!" ); - SFX->setRolloffFactor( ambience->getRolloffFactor() ); - SFX->setDopplerFactor( ambience->getDopplerFactor() ); - SFX->setReverb( ambience->getEnvironment()->getReverb() ); + SFX->setRolloffFactor(ambience->getRolloffFactor()); + SFX->setDopplerFactor(ambience->getDopplerFactor()); + SFX->setSpeedOfSound(ambience->getSpeedOfSound()); + if (ambience->getEnvironment()) + SFX->setReverb(ambience->getEnvironment()->getReverb()); } mCurrentReverbIndex = reverbIndex; } - + + if (mStack[mStack.size() - 1]->mDirtyBits.test(SFXSoundscape::AmbienceDirty)) + { + SFXAmbience* ambience = mStack[mStack.size() - 1]->getAmbience(); + SFX->setRolloffFactor(ambience->getRolloffFactor()); + SFX->setDopplerFactor(ambience->getDopplerFactor()); + SFX->setSpeedOfSound(ambience->getSpeedOfSound()); + if (ambience->getEnvironment()) + SFX->setReverb(ambience->getEnvironment()->getReverb()); + + mCurrentReverbIndex = mStack.size() - 1; + + mStack[mStack.size() - 1]->mDirtyBits.clear(SFXSoundscape::AmbienceDirty); + } + // Update the active soundscapes. for( U32 i = 0; i < mStack.size(); ++ i ) diff --git a/Engine/source/sfx/sfxSystem.cpp b/Engine/source/sfx/sfxSystem.cpp index 37133de0d..32db952e5 100644 --- a/Engine/source/sfx/sfxSystem.cpp +++ b/Engine/source/sfx/sfxSystem.cpp @@ -42,8 +42,11 @@ #include "platform/platformTimer.h" #include "core/util/autoPtr.h" #include "core/module.h" +#include "T3D/sfx/sfx3DWorld.h" +Vector SFXSystem::smProviders(__FILE__, __LINE__); +SFXSystem::RegisterProviderSignal* SFXSystem::smRegisterProviderSignal; MODULE_BEGIN( SFX ) @@ -54,6 +57,8 @@ MODULE_BEGIN( SFX ) MODULE_INIT { SFXSystem::init(); + if (engineAPI::gUseConsoleInterop) + SFXDevice::initConsole(); } MODULE_SHUTDOWN @@ -69,6 +74,25 @@ SFXSystem* SFXSystem::smSingleton = NULL; /// Default SFXAmbience used to reset the global soundscape. SFXAmbience *sDefaultAmbience; +// Provider type +ImplementEnumType(SFXProviderType, + "The sfx provider.\n" + "@ingroup SFX") +{ SFXProviderType::OpenAL, "OpenAL", "OpenAL Provider." }, +{ SFXProviderType::DirectSound, "DirectSound", "DirectSound Provider." }, +{ SFXProviderType::XAudio, "XAudio", "XAudio Provider." }, +{ SFXProviderType::NullProvider, "NullProvider","NullProvider Provider." } +EndImplementEnumType; + +// Device type +ImplementEnumType(SFXDeviceType, + "The sfx device type input/output.\n" + "@ingroup SFX") +{ SFXDeviceType::Input, "InputDevice", "Input/Capture device" }, +{ SFXDeviceType::Output, "OutputDevice", "Output Device." }, +EndImplementEnumType; + + // Excludes Null and Blocked as these are not passed out to the control layer. ImplementEnumType( SFXStatus, "Playback status of sound source.\n" @@ -185,6 +209,165 @@ static const U32 sDeviceInfoMaxBuffers = 3; //----------------------------------------------------------------------------- +SFXSystem::RegisterProviderSignal& SFXSystem::getRegisterProviderSignal() +{ + if (smRegisterProviderSignal) + return *smRegisterProviderSignal; + smRegisterProviderSignal = new RegisterProviderSignal(); + return *smRegisterProviderSignal; +} + +S32 SFXSystem::getProviderCount() +{ + return smProviders.size(); +} + +inline static void _SFXInitReportProviders(Vector& providers) +{ + for (U32 i = 0; i < providers.size(); i++) + { + switch (providers[i]->mType) + { + case OpenAL: + Con::printf(" OpenAL Device Found: %s Device %s %s", providers[i]->mDeviceType == Input ? "Input" : "Output", providers[i]->getName(), providers[i]->mDefault ? "(Default)" : ""); + break; + case NullProvider: + Con::printf(" Null device found"); + break; + case XAudio: + Con::printf(" XAudio Device Found: %s Device %s %s", providers[i]->mDeviceType == Input ? "Input" : "Output", providers[i]->getName(), providers[i]->mDefault ? "(Default)" : ""); + break; + case DirectSound: + Con::printf(" DirectSound Device Found: %s Device %s %s", providers[i]->mDeviceType == Input ? "Input" : "Output", providers[i]->getName(), providers[i]->mDefault ? "(Default)" : ""); + break; + default: + Con::printf(" Unknown device found"); + break; + } + } +} + +void SFXSystem::getProviders(Vector* providers) +{ + providers->clear(); + for (U32 k = 0; k < smProviders.size(); k++) + providers->push_back(smProviders[k]); +} + +const char* SFXSystem::getProviderNameFromType(SFXProviderType type) +{ + static const char* _names[] = { "OpenAL", "DirectSound", "XAudio", "NullProvider" }; + if (type < 0 || type >= SFXProviderType_Count) + return _names[OpenAL]; + + return _names[type]; +} + +SFXProviderType SFXSystem::getProviderTypeFromName(const char* name) +{ + for (U32 i = 0; i < SFXProviderType_Count; i++) + { + if (dStrcmp(getProviderNameFromType((SFXProviderType)i), name) == 0) + return (SFXProviderType)i; + } + + // Default to NullProvider if no match rather than silently falling through + Con::warnf("SFXSystem::getProviderTypeFromName - unknown provider '%s', defaulting to NullProvider", name); + return SFXProviderType::NullProvider; +} + +SFXProvider* SFXSystem::getProviderByTypeAndName(SFXProviderType type, const char* deviceName) +{ + // First try exact type+name match + for (U32 i = 0; i < smProviders.size(); i++) + { + if (smProviders[i]->mType == type && + String::compare(smProviders[i]->getName(), deviceName) == 0) + return smProviders[i]; + } + + // Fall back to default device for that type + for (U32 i = 0; i < smProviders.size(); i++) + { + if (smProviders[i]->mType == type && smProviders[i]->mDefault) + return smProviders[i]; + } + + // Last resort: any device of that type + for (U32 i = 0; i < smProviders.size(); i++) + { + if (smProviders[i]->mType == type) + return smProviders[i]; + } + + return NULL; +} + +SFXProvider* SFXSystem::getBestProviderChoice() +{ + const String preferredProvider = Con::getVariable("$pref::SFX::provider"); + const String preferredDevice = Con::getVariable("$pref::SFX::device"); + + // Resolve provider type. + SFXProviderType providerType = OpenAL; + + if (!preferredProvider.isEmpty()) + { + for (U32 i = 0; i < SFXProviderType_Count; i++) + { + if (!dStrcmp(getProviderNameFromType((SFXProviderType)i),preferredProvider)) + { + providerType = (SFXProviderType)i; + break; + } + } + } + + if (!preferredDevice.isEmpty()) + { + for (U32 i = 0; i < smProviders.size(); i++) + { + SFXProvider* provider = smProviders[i]; + + if (provider->mType != providerType) + continue; + + if (String::compare(provider->getName(), preferredDevice.c_str()) == 0) + { + return provider; + } + } + } + + for (U32 i = 0; i < smProviders.size(); i++) + { + SFXProvider* provider = smProviders[i]; + + if (provider->mType != providerType) + continue; + + if (provider->mDefault) + return provider; + } + + for (U32 i = 0; i < smProviders.size(); i++) + { + SFXProvider* provider = smProviders[i]; + + if (provider->mType != providerType) + continue; + + return provider; + } + + return NULL; +} + +SFXProvider* SFXSystem::getProvider(U32 index) +{ + return smProviders[index]; +} + SFXSystem::SFXSystem() : mDevice( NULL ), mLastSourceUpdateTime( 0 ), @@ -200,6 +383,7 @@ SFXSystem::SFXSystem() mDistanceModel( SFXDistanceModelLinear ), mStatAmbientUpdateTime( 0 ), mDopplerFactor( 0.5 ), + mSpeedOfSound(343.3f), mRolloffFactor( 1.0 ), mSoundscapeMgr( NULL ) { @@ -340,15 +524,36 @@ SFXSystem::~SFXSystem() deleteDevice(); } +void SFXSystem::enumerateProviders() +{ + if (smProviders.size()) + { + return; + } + + getRegisterProviderSignal().trigger(SFXSystem::smProviders); +} + //----------------------------------------------------------------------------- void SFXSystem::init() { AssertWarn( smSingleton == NULL, "SFX has already been initialized!" ); - SFXProvider::initializeAllProviders(); - - // Create the stream thread pool. + // SFXProvider::initializeAllProviders(); + Con::printf("SFX Init:"); + + // find our providers + Vector providers( __FILE__, __LINE__ ); + SFXSystem::enumerateProviders(); + SFXSystem::getProviders(&providers); + + if (!providers.size()) + Con::errorf("Could not find a sound provider"); + + //loop through and tell the user what kind of provider we found + _SFXInitReportProviders(providers); + Con::printf(""); SFXInternal::SFXThreadPool::createSingleton(); @@ -366,6 +571,13 @@ void SFXSystem::destroy() { AssertWarn( smSingleton != NULL, "SFX has not been initialized!" ); + while (smProviders.size()) + { + SFXProvider* provider = smProviders.last(); + smProviders.decrement(); + delete provider; + } + delete smSingleton; smSingleton = NULL; @@ -373,6 +585,9 @@ void SFXSystem::destroy() SFXInternal::SFXThreadPool::deleteSingleton(); delete(sDefaultAmbience); + + if (smRegisterProviderSignal) + SAFE_DELETE(smRegisterProviderSignal); } //----------------------------------------------------------------------------- @@ -397,61 +612,54 @@ void SFXSystem::removePlugin( SFXSystemPlugin* plugin ) } } -//----------------------------------------------------------------------------- - -bool SFXSystem::createDevice( const String& providerName, const String& deviceName, bool useHardware, S32 maxBuffers, bool changeDevice ) +bool SFXSystem::createDeviceByName(const char* providerName, const char* deviceName) { - // Make sure we don't have a device already. - - if( mDevice && !changeDevice ) - return false; + SFXProviderType type = getProviderTypeFromName(providerName); + SFXProvider* provider = getProviderByTypeAndName(type, deviceName); - // Lookup the provider. - - SFXProvider* provider = SFXProvider::findProvider( providerName ); - if( !provider ) - return false; - - // If we have already created this device and are using it then no need to do anything. - - if( mDevice - && providerName.equal( mDevice->getProvider()->getName(), String::NoCase ) - && deviceName.equal( mDevice->getName(), String::NoCase ) - && useHardware == mDevice->getUseHardware() ) - return true; - - // If we have an existing device remove it. - - if( mDevice ) - deleteDevice(); - - // Create the new device.. - - mDevice = provider->createDevice( deviceName, useHardware, maxBuffers ); - if( !mDevice ) + if (!provider) { - Con::errorf( "SFXSystem::createDevice - failed creating %s device '%s'", providerName.c_str(), deviceName.c_str() ); + Con::errorf("SFXSystem::createDeviceByName - could not find provider '%s' device '%s'", + providerName, deviceName); return false; } - - // Print capabilities. - Con::printf( "SFXSystem::createDevice - created %s device '%s'", providerName.c_str(), deviceName.c_str() ); - if( mDevice->getCaps() & SFXDevice::CAPS_Reverb ) - Con::printf( " CAPS_Reverb" ); - if( mDevice->getCaps() & SFXDevice::CAPS_VoiceManagement ) - Con::printf( " CAPS_VoiceManagement" ); - if( mDevice->getCaps() & SFXDevice::CAPS_Occlusion ) - Con::printf( "\tCAPS_Occlusion" ); - if( mDevice->getCaps() & SFXDevice::CAPS_MultiListener ) - Con::printf( "\tCAPS_MultiListener" ); - - // Set defaults. + return createDevice(provider); +} + +//----------------------------------------------------------------------------- + +bool SFXSystem::createDevice(SFXProvider* provider) +{ + // this should probably just happen tbh. + if (mDevice) + { + // called to create the same device bug out. + // this may need to be changed later to check if + // the provider names also match. + if (String::compare(mDevice->getName(), provider->getName()) == 0) + return false; + + deleteDevice(); + } + + mDevice = provider->mCreateDeviceInstanceDelegate(provider->mIndex); + if( !mDevice ) + { + Con::errorf( "SFXSystem::createDevice - failed creating device '%s'", provider->getName()); + return false; + } + + mDevice->setProvider(provider); + + // device is responsible for printing its information. + // Set defaults. mDevice->setNumListeners( getNumListeners() ); mDevice->setDistanceModel( mDistanceModel ); mDevice->setDopplerFactor( mDopplerFactor ); mDevice->setRolloffFactor( mRolloffFactor ); + mDevice->setSpeedOfSound( mSpeedOfSound ); //OpenAL requires slots for effects, this creates an empty function //that will run when a sfxdevice is created. mDevice->openSlots(); @@ -464,17 +672,15 @@ bool SFXSystem::createDevice( const String& providerName, const String& deviceNa return true; } -//----------------------------------------------------------------------------- - String SFXSystem::getDeviceInfoString() { // Make sure we have a valid device. if( !mDevice ) return String(); - return String::ToString( "%s\t%s\t%s\t%d\t%d", - mDevice->getProvider()->getName().c_str(), - mDevice->getName().c_str(), + return String::ToString( "%s\t%s\t%s\t%d\t%d", + getProviderNameFromType(mDevice->getProvider()->mType), + mDevice->getProvider()->getName(), mDevice->getUseHardware() ? "1" : "0", mDevice->getMaxBuffers(), mDevice->getCaps() ); @@ -794,8 +1000,10 @@ void SFXSystem::_update() } // If we have a device then update it. - if( mDevice ) + if (mDevice) + { mDevice->update(); + } } //----------------------------------------------------------------------------- @@ -1020,6 +1228,18 @@ void SFXSystem::setDopplerFactor( F32 factor ) //----------------------------------------------------------------------------- + +void SFXSystem::setSpeedOfSound(F32 speedOfSound) +{ + const bool changed = (speedOfSound != mSpeedOfSound); + + mSpeedOfSound = speedOfSound; + if (mDevice && changed) + mDevice->setSpeedOfSound(speedOfSound); +} + +//----------------------------------------------------------------------------- + void SFXSystem::setRolloffFactor( F32 factor ) { const bool changed = ( factor != mRolloffFactor ); @@ -1210,6 +1430,43 @@ void SFXSystem::dumpSources( StringBuilder* toString, bool excludeGroups ) //----------------------------------------------------------------------------- +DefineEngineFunction(sfxGetProviderCount, S32, (), , + "Returns the number of sound providers available\n\n" + "@ingroup SFX") +{ + return SFXSystem::getProviderCount(); +} + +DefineEngineFunction(sfxGetProviderType, SFXProviderType, (S32 index), , + "Returns the type (OpenAL, XAudio, DirectSound, Null) of a sound provider.\n" + "@param index The index of the adapter.") +{ + Vector providers(__FILE__, __LINE__); + SFXSystem::getProviders(&providers); + + if (index >= 0 && index < providers.size()) + return providers[index]->mType; + + Con::errorf("SFXSystem::sfxGetProviderType - Out of range provider index."); + return SFXProviderType_Count; +} + +DefineEngineFunction(sfxGetProviderDevice, const char*, (S32 index), , + "Returns the device name of the sound provider.\n" + "@param index The index of the adapter.") +{ + Vector providers(__FILE__, __LINE__); + SFXSystem::getProviders(&providers); + + if (index >= 0 && index < providers.size()) + return providers[index]->getName(); + + Con::errorf("SFXSystem::sfxGetProviderDevice - Out of range provider index."); + return ""; +} + + + DefineEngineFunction( sfxGetAvailableDevices, const char*, (),, "Get a list of all available sound devices.\n" "The return value will be a newline-separated list of entries where each line describes one available sound " @@ -1240,27 +1497,14 @@ DefineEngineFunction( sfxGetAvailableDevices, const char*, (),, char *ptr = deviceList; *ptr = 0; - SFXProvider* provider = SFXProvider::getFirstProvider(); - while ( provider ) + Vector providers(__FILE__, __LINE__); + SFXSystem::getProviders(&providers); + + for (U32 i = 0; i < providers.size(); i++) { - // List the devices in this provider. - const SFXDeviceInfoVector& deviceInfo = provider->getDeviceInfo(); - for ( S32 d=0; d < deviceInfo.size(); d++ ) - { - const SFXDeviceInfo* info = deviceInfo[d]; - const char *providerName = provider->getName().c_str(); - char *infoName = (char*)info->name.c_str(); - - dSprintf(ptr, len, "%s\t%s\t%s\t%i\n", providerName, infoName, info->hasHardware ? "1" : "0", info->maxBuffers); - - ptr += dStrlen(ptr); - len = bufferSize - (ptr - deviceList); - - if (len <= 0) - return deviceList; - } - - provider = provider->getNextProvider(); + dSprintf(ptr, len, "%s\t", providers[i]->getName()); + ptr += dStrlen(ptr); + len = bufferSize - (ptr - deviceList); } return deviceList; @@ -1268,7 +1512,7 @@ DefineEngineFunction( sfxGetAvailableDevices, const char*, (),, //----------------------------------------------------------------------------- -DefineEngineFunction( sfxCreateDevice, bool, ( const char* provider, const char* device, bool useHardware, S32 maxBuffers ),, +DefineEngineFunction( sfxCreateDevice, bool, (),, "Try to create a new sound device using the given properties.\n" "If a sound device is currently initialized, it will be uninitialized first. However, be aware that in this case, " "if this function fails, it will not restore the previously active device but rather leave the sound system in an " @@ -1276,10 +1520,6 @@ DefineEngineFunction( sfxCreateDevice, bool, ( const char* provider, const char* "Sounds that are already playing while the new device is created will be temporarily transitioned to virtualized " "playback and then resume normal playback once the device has been created.\n\n" "In the core scripts, sound is automatically set up during startup in the sfxStartup() function.\n\n" - "@param provider The name of the device provider as returned by sfxGetAvailableDevices().\n" - "@param device The name of the device as returned by sfxGetAvailableDevices().\n" - "@param useHardware Whether to enabled hardware mixing on the device or not. Only relevant if supported by the given device.\n" - "@param maxBuffers The maximum number of concurrent voices for this device to use or -1 for the device to pick its own reasonable default." "@return True if the initialization was successful, false if not.\n" "@note This function must be called before any of the sound playback functions can be used.\n" "@see sfxGetAvailableDevices\n" @@ -1288,7 +1528,34 @@ DefineEngineFunction( sfxCreateDevice, bool, ( const char* provider, const char* "@ref SFX_devices\n" "@ingroup SFX" ) { - return SFX->createDevice( provider, device, useHardware, maxBuffers, true ); + // return SFX->createDevice( provider, device, useHardware, maxBuffers, true ); + SFXProvider* p = SFXSystem::getBestProviderChoice(); + if (p) + { + SFX->createDevice(p); + return true; + } + return false; +} + +//----------------------------------------------------------------------------- + +DefineEngineFunction(sfxCreateDeviceFromName, bool, (const char* providerName, const char* deviceName), ("", ""), + "Create a sound device. Optionally specify provider and device name directly.\n" + "@param providerName Optional provider type name (e.g. \"OpenAL\", \"NullProvider\").\n" + "@param deviceName Optional device name to match against.\n" + "@ingroup SFX") +{ + // If explicit names were provided, use them directly + if (providerName[0] != '\0' && deviceName[0] != '\0') + return SFX->createDeviceByName(providerName, deviceName); + + // Otherwise fall back to autodetect via prefs + SFXProvider* p = SFXSystem::getBestProviderChoice(); + if (p) + return SFX->createDevice(p); + + return false; } //----------------------------------------------------------------------------- @@ -1621,13 +1888,13 @@ DefineEngineFunction( sfxPlayOnce, S32, (StringTableEntry assetId, const char* a if (String::isEmpty(arg0) || !tempSoundAsset->is3D()) { - source = SFX->playOnce(tempSoundAsset->getSfxProfile()); + source = SFX->playOnce(tempSoundAsset->getSFXTrack()); } else { MatrixF transform; transform.set(EulerF(0, 0, 0), Point3F(dAtof(arg0), dAtof(arg1), dAtof(arg2))); - source = SFX->playOnce(tempSoundAsset->getSfxProfile(), &transform, NULL, dAtof(arg3)); + source = SFX->playOnce(tempSoundAsset->getSFXTrack(), &transform, NULL, dAtof(arg3)); } } else diff --git a/Engine/source/sfx/sfxSystem.h b/Engine/source/sfx/sfxSystem.h index 7ac0b6f24..a54f4be20 100644 --- a/Engine/source/sfx/sfxSystem.h +++ b/Engine/source/sfx/sfxSystem.h @@ -23,9 +23,10 @@ #ifndef _SFXSYSTEM_H_ #define _SFXSYSTEM_H_ -#ifndef _SFXCOMMON_H_ - #include "sfx/sfxCommon.h" -#endif +#ifndef _SFXPROVIDER_H_ +#include "sfx/sfxProvider.h" +#endif // !_SFXPROVIDER_H_ + #ifndef _TSIGNAL_H_ #include "core/util/tSignal.h" #endif @@ -98,343 +99,362 @@ class SFXSystemPlugin /// class SFXSystem { - friend class SFXSound; // _assignVoices - friend class SFXSource; // _onAddSource, _onRemoveSource. - friend class SFXProfile; // _createBuffer. + friend class SFXSound; // _assignVoices + friend class SFXSource; // _onAddSource, _onRemoveSource. + friend class SFXProfile; // _createBuffer. + +public: + /// Allows device to register themselves as available + typedef Signal&)> RegisterProviderSignal; + static RegisterProviderSignal& getRegisterProviderSignal(); + /// Get the number of available providers. + static S32 getProviderCount(); + /// Enumerate all the sound providers on the system + static void enumerateProviders(); + static void getProviders(Vector* providers); + static const char* getProviderNameFromType(SFXProviderType type); + static SFXProvider* getBestProviderChoice(); + static SFXProvider* getProvider(U32 index); + static SFXProviderType getProviderTypeFromName(const char* name); + static SFXProvider* getProviderByTypeAndName(SFXProviderType type, const char* deviceName); + + typedef Signal< void( SFXSystemEventType event ) > EventSignalType; + typedef Vector< SFXSource* > SFXSourceVector; + typedef Vector< SFXSound* > SFXSoundVector; +private: + /// List of known adapters. + static Vector smProviders; + static RegisterProviderSignal* smRegisterProviderSignal; + +protected: + + /// The one and only instance of the SFXSystem. + static SFXSystem* smSingleton; + + /// The protected constructor. + /// + /// @see SFXSystem::init() + /// + SFXSystem(); + + /// The non-virtual destructor. You shouldn't + /// ever need to overload this class. + ~SFXSystem(); - public: - typedef Signal< void( SFXSystemEventType event ) > EventSignalType; - typedef Vector< SFXSource* > SFXSourceVector; - typedef Vector< SFXSound* > SFXSoundVector; + /// The current output sound device initialized + /// and ready to play back. + SFXDevice* mDevice; - protected: + /// + SFXSoundVector mSounds; - /// The one and only instance of the SFXSystem. - static SFXSystem* smSingleton; - - /// The protected constructor. - /// - /// @see SFXSystem::init() - /// - SFXSystem(); - - /// The non-virtual destructor. You shouldn't - /// ever need to overload this class. - ~SFXSystem(); - - /// The current output sound device initialized - /// and ready to play back. - SFXDevice* mDevice; - - /// - SFXSoundVector mSounds; - - /// This is used to keep track of play once sources - /// that must be released when they stop playing. - SFXSourceVector mPlayOnceSources; + /// This is used to keep track of play once sources + /// that must be released when they stop playing. + SFXSourceVector mPlayOnceSources; - /// The last time the sources got an update. - U32 mLastSourceUpdateTime; + /// The last time the sources got an update. + U32 mLastSourceUpdateTime; - /// - U32 mLastAmbientUpdateTime; + /// + U32 mLastAmbientUpdateTime; - /// - U32 mLastParameterUpdateTime; + /// + U32 mLastParameterUpdateTime; - /// The distance model used for rolloff curve computation on 3D sounds. - SFXDistanceModel mDistanceModel; + /// The distance model used for rolloff curve computation on 3D sounds. + SFXDistanceModel mDistanceModel; - /// The current doppler scale factor. - F32 mDopplerFactor; + /// The current doppler scale factor. + F32 mDopplerFactor; + + /// The current speed of sound. + F32 mSpeedOfSound; - /// The current curve rolloff factor. - F32 mRolloffFactor; + /// The current curve rolloff factor. + F32 mRolloffFactor; - /// The current position and orientation of all listeners. - Vector< SFXListenerProperties > mListeners; + /// The current position and orientation of all listeners. + Vector< SFXListenerProperties > mListeners; - /// Current global reverb properties. - SFXReverbProperties mReverb; + /// Current global reverb properties. + SFXReverbProperties mReverb; - /// SFX system event signal. - EventSignalType mEventSignal; + /// SFX system event signal. + EventSignalType mEventSignal; - /// Ambient soundscape manager. - SFXSoundscapeManager* mSoundscapeMgr; + /// Ambient soundscape manager. + SFXSoundscapeManager* mSoundscapeMgr; - /// List of plugins currently linked to the SFX system. - Vector< SFXSystemPlugin* > mPlugins; + /// List of plugins currently linked to the SFX system. + Vector< SFXSystemPlugin* > mPlugins; - /// @name Stats - /// - /// Stats reported back to the console for tracking performance. - /// - /// @{ + /// @name Stats + /// + /// Stats reported back to the console for tracking performance. + /// + /// @{ - S32 mStatNumSources; - S32 mStatNumSounds; - S32 mStatNumPlaying; - S32 mStatNumCulled; - S32 mStatNumVoices; - S32 mStatSourceUpdateTime; - S32 mStatParameterUpdateTime; - S32 mStatAmbientUpdateTime; + S32 mStatNumSources; + S32 mStatNumSounds; + S32 mStatNumPlaying; + S32 mStatNumCulled; + S32 mStatNumVoices; + S32 mStatSourceUpdateTime; + S32 mStatParameterUpdateTime; + S32 mStatAmbientUpdateTime; - /// @} + /// @} - /// Called to reprioritize and reassign buffers as - /// sources change state, volumes are adjusted, and - /// the listener moves around. - /// - /// @see SFXSource::_update() - /// - void _updateSources(); + /// Called to reprioritize and reassign buffers as + /// sources change state, volumes are adjusted, and + /// the listener moves around. + /// + /// @see SFXSource::_update() + /// + void _updateSources(); - /// This called to reprioritize and reassign - /// voices to sources. - void _assignVoices(); + /// This called to reprioritize and reassign + /// voices to sources. + void _assignVoices(); - /// - void _assignVoice( SFXSound* sound ); + /// + void _assignVoice( SFXSound* sound ); - /// - void _sortSounds( const SFXListenerProperties& listener ); + /// + void _sortSounds( const SFXListenerProperties& listener ); - /// Called from SFXSource::onAdd to register the source. - void _onAddSource( SFXSource* source ); + /// Called from SFXSource::onAdd to register the source. + void _onAddSource( SFXSource* source ); - /// Called from SFXSource::onRemove to unregister the source. - void _onRemoveSource( SFXSource* source ); + /// Called from SFXSource::onRemove to unregister the source. + void _onRemoveSource( SFXSource* source ); - /// Called from SFXProfile to create a device specific - /// sound buffer used in conjunction with a voice in playback. - SFXBuffer* _createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description ); + /// Called from SFXProfile to create a device specific + /// sound buffer used in conjunction with a voice in playback. + SFXBuffer* _createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description ); - /// Load file directly through SFXDevice. Depends on - /// availability with selected SFXDevice. - /// - /// @return Return new buffer or NULL. - SFXBuffer* _createBuffer( const String& filename, SFXDescription* description ); + /// Load file directly through SFXDevice. Depends on + /// availability with selected SFXDevice. + /// + /// @return Return new buffer or NULL. + SFXBuffer* _createBuffer( const String& filename, SFXDescription* description ); - /// - SFXDevice* _getDevice() const { return mDevice; } + /// + SFXDevice* _getDevice() const { return mDevice; } - public: +public: - /// Returns the one an only instance of the SFXSystem - /// unless it hasn't been initialized or its been disabled - /// in your build. - /// - /// For convienence you can use the SFX-> macro as well. - /// - /// @see SFXSystem::init() - /// @see SFX - static SFXSystem* getSingleton() { return smSingleton; } + /// Returns the one an only instance of the SFXSystem + /// unless it hasn't been initialized or its been disabled + /// in your build. + /// + /// For convienence you can use the SFX-> macro as well. + /// + /// @see SFXSystem::init() + /// @see SFX + static SFXSystem* getSingleton() { return smSingleton; } - /// This is called from initialization to prepare the - /// sound system singleton. This also includes registering - /// common resource types and initializing available sound - /// providers. - static void init(); + /// This is called from initialization to prepare the + /// sound system singleton. This also includes registering + /// common resource types and initializing available sound + /// providers. + static void init(); - /// This is called after Sim::shutdown() in shutdownLibraries() - /// to free the sound system singlton. After this the SFX - /// singleton is null and any call to it will crash. - static void destroy(); + /// This is called after Sim::shutdown() in shutdownLibraries() + /// to free the sound system singlton. After this the SFX + /// singleton is null and any call to it will crash. + static void destroy(); - /// This is only public so that it can be called by - /// the game update loop. It updates the current - /// device and all sources. - void _update(); + /// This is only public so that it can be called by + /// the game update loop. It updates the current + /// device and all sources. + void _update(); - /// Register the given plugin with the system. - void addPlugin( SFXSystemPlugin* plugin ); + /// Register the given plugin with the system. + void addPlugin( SFXSystemPlugin* plugin ); - /// Unregister the given plugin with the system. - void removePlugin( SFXSystemPlugin* plugin ); + /// Unregister the given plugin with the system. + void removePlugin( SFXSystemPlugin* plugin ); + + /// @name Device Management + /// @{ + + bool createDeviceByName(const char* providerName, const char* deviceName); + + /// This initializes a new device. + /// + /// @return Returns true if the device was created. + bool createDevice( SFXProvider* provider); + + /// Returns the current device information or NULL if no + /// device is present. The information string is in the + /// following format: + /// + /// Provider Name\tDevice Name\tUse Hardware\tMax Buffers + String getDeviceInfoString(); + + /// This destroys the current device. All sources loose their + /// playback buffers, but otherwise continue to function. + void deleteDevice(); + + /// Returns true if a device is allocated. + bool hasDevice() const { return mDevice != NULL; } - /// @name Device Management - /// @{ - - /// This initializes a new device. - /// - /// @param providerName The name of the provider. - /// @param deviceName The name of the provider device. - /// @param useHardware Toggles the use of hardware processing when available. - /// @param maxBuffers The maximum buffers for this device to use or -1 - /// for the device to pick its own reasonable default. - /// @param changeDevice Allows this to change the current device to a new one - /// @return Returns true if the device was created. - bool createDevice( const String& providerName, - const String& deviceName, - bool useHardware, - S32 maxBuffers, - bool changeDevice = false); - - /// Returns the current device information or NULL if no - /// device is present. The information string is in the - /// following format: - /// - /// Provider Name\tDevice Name\tUse Hardware\tMax Buffers - String getDeviceInfoString(); - - /// This destroys the current device. All sources loose their - /// playback buffers, but otherwise continue to function. - void deleteDevice(); - - /// Returns true if a device is allocated. - bool hasDevice() const { return mDevice != NULL; } + /// @} - /// @} - - /// @name Source Creation - /// @{ + /// @name Source Creation + /// @{ - /// Used to create new sound sources from a sound profile. The - /// returned source is in a stopped state and ready for playback. - /// Use the SFX_DELETE macro to free the source when your done. - /// - /// @note The track must have at least the same lifetime as the - /// source. If the description disappears while the source is still - /// there, the source will go with it. - /// - /// @param profile The sound profile for the created source. - /// @param transform The optional transform if creating a 3D source. - /// @param velocity The optional doppler velocity if creating a 3D source. - /// - /// @return The sound source or NULL if an error occured. - SFXSource* createSource( SFXTrack* track, - const MatrixF* transform = NULL, - const VectorF* velocity = NULL ); + /// Used to create new sound sources from a sound profile. The + /// returned source is in a stopped state and ready for playback. + /// Use the SFX_DELETE macro to free the source when your done. + /// + /// @note The track must have at least the same lifetime as the + /// source. If the description disappears while the source is still + /// there, the source will go with it. + /// + /// @param profile The sound profile for the created source. + /// @param transform The optional transform if creating a 3D source. + /// @param velocity The optional doppler velocity if creating a 3D source. + /// + /// @return The sound source or NULL if an error occured. + SFXSource* createSource( SFXTrack* track, + const MatrixF* transform = NULL, + const VectorF* velocity = NULL ); - /// Used to create a streaming sound source from a user supplied - /// stream object. - /// - /// It is only intended for memory based streams. For sound file - /// streaming use createSource() with a streaming SFXProfile. - /// - /// Use the SFX_DELETE macro to free the source when your done. - /// - /// @note The description must have at least the same lifetime as the - /// sound. If the description disappears while the source is still - /// there, the sound will go with it. - /// - /// @param stream The stream used to create the sound buffer. It - /// must exist for the lifetime of the source and will - /// have its reference count decremented when the source - /// is destroyed. - /// - /// @param description The sound description to apply to the source. - /// - /// @return The sound source or NULL if an error occured. - SFXSound* createSourceFromStream( const ThreadSafeRef< SFXStream >& stream, - SFXDescription* description ); + /// Used to create a streaming sound source from a user supplied + /// stream object. + /// + /// It is only intended for memory based streams. For sound file + /// streaming use createSource() with a streaming SFXProfile. + /// + /// Use the SFX_DELETE macro to free the source when your done. + /// + /// @note The description must have at least the same lifetime as the + /// sound. If the description disappears while the source is still + /// there, the sound will go with it. + /// + /// @param stream The stream used to create the sound buffer. It + /// must exist for the lifetime of the source and will + /// have its reference count decremented when the source + /// is destroyed. + /// + /// @param description The sound description to apply to the source. + /// + /// @return The sound source or NULL if an error occured. + SFXSound* createSourceFromStream( const ThreadSafeRef< SFXStream >& stream, + SFXDescription* description ); - /// Creates a source which when it finishes playing will auto delete - /// itself. Be aware that the returned SFXSource pointer should only - /// be used for error checking or immediate setting changes. It may - /// be deleted as soon as the next system tick. - /// - /// @param profile The sound profile for the created source. - /// @param transform The optional transform if creating a 3D source. - /// @param velocity The optional doppler velocity if creating a 3D source. - /// - /// @return The sound source or NULL if an error occured. - SFXSource* playOnce( SFXTrack* track, - const MatrixF* transform = NULL, - const VectorF* velocity = NULL, - F32 fadeInTime = -1.f ); - SFXSource* playOnce( SFXProfile* profile, - const MatrixF* transform = NULL, - const VectorF* velocity = NULL, - F32 fadeInTime = -1.f ) - { // Avoids having to require inclusion of sfxProfile.h - return playOnce( ( SFXTrack* ) profile, transform, velocity, fadeInTime ); - } + /// Creates a source which when it finishes playing will auto delete + /// itself. Be aware that the returned SFXSource pointer should only + /// be used for error checking or immediate setting changes. It may + /// be deleted as soon as the next system tick. + /// + /// @param profile The sound profile for the created source. + /// @param transform The optional transform if creating a 3D source. + /// @param velocity The optional doppler velocity if creating a 3D source. + /// + /// @return The sound source or NULL if an error occured. + SFXSource* playOnce( SFXTrack* track, + const MatrixF* transform = NULL, + const VectorF* velocity = NULL, + F32 fadeInTime = -1.f ); + SFXSource* playOnce( SFXProfile* profile, + const MatrixF* transform = NULL, + const VectorF* velocity = NULL, + F32 fadeInTime = -1.f ) + { // Avoids having to require inclusion of sfxProfile.h + return playOnce( ( SFXTrack* ) profile, transform, velocity, fadeInTime ); + } - /// Stop the source and delete it. This method will take care of - /// the fade-out time that the source may need before it will actually - /// stop and may be deleted. - void stopAndDeleteSource( SFXSource* source ); + /// Stop the source and delete it. This method will take care of + /// the fade-out time that the source may need before it will actually + /// stop and may be deleted. + void stopAndDeleteSource( SFXSource* source ); - /// Mark source for deletion when it is moving into stopped state. - /// This method is useful to basically make a source a play-once source - /// after the fact. - void deleteWhenStopped( SFXSource* source ); + /// Mark source for deletion when it is moving into stopped state. + /// This method is useful to basically make a source a play-once source + /// after the fact. + void deleteWhenStopped( SFXSource* source ); - /// @} + /// @} - /// @} + /// @} - /// @name Listeners - /// @{ + /// @name Listeners + /// @{ - /// Return the number of listeners currently configured. - U32 getNumListeners() const { return mListeners.size(); } + /// Return the number of listeners currently configured. + U32 getNumListeners() const { return mListeners.size(); } - /// Set the number of concurrent listeners. - /// @note It depends on the selected device if more than one listener is actually supported. - void setNumListeners( U32 num ); + /// Set the number of concurrent listeners. + /// @note It depends on the selected device if more than one listener is actually supported. + void setNumListeners( U32 num ); - /// Set the property of the given listener. - const SFXListenerProperties& getListener( U32 index = 0 ) const { return mListeners[ index ]; } + /// Set the property of the given listener. + const SFXListenerProperties& getListener( U32 index = 0 ) const { return mListeners[ index ]; } - /// Set the 3D attributes of the given listener. - void setListener( U32 index, const MatrixF& transform, const Point3F& velocity ); - void setListener( U32 index, const SFXListenerProperties& properties ) - { - setListener( index, properties.getTransform(), properties.getVelocity() ); - } + /// Set the 3D attributes of the given listener. + void setListener( U32 index, const MatrixF& transform, const Point3F& velocity ); + void setListener( U32 index, const SFXListenerProperties& properties ) + { + setListener( index, properties.getTransform(), properties.getVelocity() ); + } - /// @} + /// @} - /// @name 3D Sound Configuration - /// { + /// @name 3D Sound Configuration + /// { - /// Return the curve model currently used distance attenuation of positional sounds. - SFXDistanceModel getDistanceModel() const { return mDistanceModel; } + /// Return the curve model currently used distance attenuation of positional sounds. + SFXDistanceModel getDistanceModel() const { return mDistanceModel; } - /// - void setDistanceModel( SFXDistanceModel model ); + /// + void setDistanceModel( SFXDistanceModel model ); - /// - F32 getDopplerFactor() const { return mDopplerFactor; } + /// + F32 getDopplerFactor() const { return mDopplerFactor; } - /// - void setDopplerFactor( F32 factor ); + /// + void setDopplerFactor( F32 factor ); - /// - F32 getRolloffFactor() const { return mRolloffFactor; } + /// + F32 getRolloffFactor() const { return mRolloffFactor; } + + /// + /// Change the devices speed of sound. + /// + /// F32 for speed of sound. + void setSpeedOfSound(F32 speedOfSound); + + /// + void setRolloffFactor( F32 factor ); - /// - void setRolloffFactor( F32 factor ); + /// + const SFXReverbProperties& getReverb() const { return mReverb; } - /// - const SFXReverbProperties& getReverb() const { return mReverb; } + /// + void setReverb( const SFXReverbProperties& reverb ); - /// - void setReverb( const SFXReverbProperties& reverb ); + /// @} - /// @} + /// + SFXSoundscapeManager* getSoundscapeManager() const { return mSoundscapeMgr; } - /// - SFXSoundscapeManager* getSoundscapeManager() const { return mSoundscapeMgr; } + /// Dump information about all current SFXSources to the console or + /// to the given StringBuilder. + void dumpSources( StringBuilder* toString = NULL, bool excludeGroups = true ); - /// Dump information about all current SFXSources to the console or - /// to the given StringBuilder. - void dumpSources( StringBuilder* toString = NULL, bool excludeGroups = true ); + /// Return the SFX system event signal. + EventSignalType& getEventSignal() { return mEventSignal; } - /// Return the SFX system event signal. - EventSignalType& getEventSignal() { return mEventSignal; } + /// Notify the SFX system that the given description has changed. + /// All sources currently using the description will be updated. + void notifyDescriptionChanged( SFXDescription* description); - /// Notify the SFX system that the given description has changed. - /// All sources currently using the description will be updated. - void notifyDescriptionChanged( SFXDescription* description); - - /// - void notifyTrackChanged( SFXTrack* track ); + /// + void notifyTrackChanged( SFXTrack* track ); }; diff --git a/Engine/source/sfx/sfxVoice.h b/Engine/source/sfx/sfxVoice.h index 74e40293e..593c3a1f1 100644 --- a/Engine/source/sfx/sfxVoice.h +++ b/Engine/source/sfx/sfxVoice.h @@ -210,9 +210,9 @@ class SFXVoice : public StrongRefBase, F32 outerAngle, F32 outerVolume ) = 0; - /// Set the reverb properties for playback of this sound. + /// Allow this sound to use SFXEnvironment reverb. /// @note Has no effect on devices that do not support reverb. - virtual void setReverb( const SFXSoundReverbProperties& reverb ) {} + virtual void setReverb( bool useReverb ) {} /// Set the priority of this voice. Default 1.0. /// @note Has no effect on devices that do not support voice management. diff --git a/Engine/source/sfx/sfxWorld.h b/Engine/source/sfx/sfxWorld.h index 288644ace..5442545be 100644 --- a/Engine/source/sfx/sfxWorld.h +++ b/Engine/source/sfx/sfxWorld.h @@ -387,7 +387,7 @@ void SFXWorld< NUM_DIMENSIONS, Object >::_onScopeOut( Object object ) // Remove its soundscape. Scope& scope = mScopeStack[ index ]; - if( scope.mSoundscape ) + if( scope.mSoundscape && SFX ) SFX->getSoundscapeManager()->removeSoundscape( scope.mSoundscape ); mScopeStack.erase( index ); diff --git a/Engine/source/sfx/xaudio/sfxXAudioBuffer.cpp b/Engine/source/sfx/xaudio/sfxXAudioBuffer.cpp deleted file mode 100644 index 166815ee7..000000000 --- a/Engine/source/sfx/xaudio/sfxXAudioBuffer.cpp +++ /dev/null @@ -1,125 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "sfx/xaudio/sfxXAudioBuffer.h" -#include "sfx/xaudio/sfxXAudioVoice.h" - - -//#define DEBUG_SPEW - - -SFXXAudioBuffer* SFXXAudioBuffer::create( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description ) -{ - SFXXAudioBuffer *buffer = new SFXXAudioBuffer( stream, description ); - return buffer; -} - -SFXXAudioBuffer::SFXXAudioBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description ) - : Parent( stream, description ) -{ - VECTOR_SET_ASSOCIATION( mBufferQueue ); -} - -SFXXAudioBuffer::~SFXXAudioBuffer() -{ - _flush(); -} - -void SFXXAudioBuffer::write( SFXInternal::SFXStreamPacket* const* packets, U32 num ) -{ - AssertFatal( SFXInternal::isSFXThread(), "SFXXAudioBuffer::write() - not on SFX thread" ); - - using namespace SFXInternal; - - // Unqueue processed packets. - - if( isStreaming() ) - { - EnterCriticalSection( &_getUniqueVoice()->mLock ); - - XAUDIO2_VOICE_STATE state; - _getUniqueVoice()->mXAudioVoice->GetState( &state ); - - U32 numProcessed = mBufferQueue.size() - state.BuffersQueued; - for( U32 i = 0; i < numProcessed; ++ i ) - { - destructSingle< SFXStreamPacket* >( mBufferQueue.first().mPacket ); - mBufferQueue.pop_front(); - - #ifdef DEBUG_SPEW - Platform::outputDebugString( "[SFXXAudioBuffer] Unqueued packet" ); - #endif - } - - LeaveCriticalSection( &_getUniqueVoice()->mLock ); - } - - // Queue new packets. - - for( U32 i = 0; i < num; ++ i ) - { - SFXStreamPacket* packet = packets[ i ]; - Buffer buffer; - - if( packet->mIsLast ) - buffer.mData.Flags = XAUDIO2_END_OF_STREAM; - - buffer.mPacket = packet; - buffer.mData.AudioBytes = packet->mSizeActual; - buffer.mData.pAudioData = packet->data; - - mBufferQueue.push_back( buffer ); - - #ifdef DEBUG_SPEW - Platform::outputDebugString( "[SFXXAudioBuffer] Queued packet" ); - #endif - - // If this is a streaming buffer, submit the packet to the - // voice queue right away. - - if( isStreaming() ) - { - EnterCriticalSection( &_getUniqueVoice()->mLock ); - - IXAudio2SourceVoice* voice = _getUniqueVoice()->mXAudioVoice; - voice->SubmitSourceBuffer( &buffer.mData ); - - LeaveCriticalSection( &_getUniqueVoice()->mLock ); - } - } -} - -void SFXXAudioBuffer::_flush() -{ - #ifdef DEBUG_SPEW - Platform::outputDebugString( "[SFXXAudioBuffer] Flushing buffer" ); - #endif - - if( _getUniqueVoice() ) - _getUniqueVoice()->_stop(); - - while( !mBufferQueue.empty() ) - { - destructSingle( mBufferQueue.last().mPacket ); - mBufferQueue.pop_back(); - } -} diff --git a/Engine/source/sfx/xaudio/sfxXAudioBuffer.h b/Engine/source/sfx/xaudio/sfxXAudioBuffer.h deleted file mode 100644 index a1bcee139..000000000 --- a/Engine/source/sfx/xaudio/sfxXAudioBuffer.h +++ /dev/null @@ -1,83 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _SFXXAUDIOBUFFER_H_ -#define _SFXXAUDIOBUFFER_H_ - -#include - -#ifndef _SFXINTERNAL_H_ -#include "sfx/sfxInternal.h" -#endif - -#ifndef _TVECTOR_H_ -#include "core/util/tVector.h" -#endif - - -/// Audio data buffer for the XAudio device layer. -class SFXXAudioBuffer : public SFXBuffer -{ - public: - - typedef SFXBuffer Parent; - - friend class SFXXAudioDevice; - friend class SFXXAudioVoice; - - protected: - - struct Buffer - { - XAUDIO2_BUFFER mData; - SFXInternal::SFXStreamPacket* mPacket; - - Buffer() - : mPacket( 0 ) - { - dMemset( &mData, 0, sizeof( mData ) ); - } - }; - - typedef Vector< Buffer > QueueType; - - QueueType mBufferQueue; - - /// If this is a streaming buffer, return the unique voice associated - /// with the buffer. - SFXXAudioVoice* _getUniqueVoice() { return ( SFXXAudioVoice* ) mUniqueVoice.getPointer(); } - - /// - SFXXAudioBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description ); - virtual ~SFXXAudioBuffer(); - - // SFXBuffer. - virtual void write( SFXInternal::SFXStreamPacket* const* packets, U32 num ); - void _flush(); - - public: - - /// - static SFXXAudioBuffer* create( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description ); -}; - -#endif // _SFXXAUDIOBUFFER_H_ \ No newline at end of file diff --git a/Engine/source/sfx/xaudio/sfxXAudioDevice.cpp b/Engine/source/sfx/xaudio/sfxXAudioDevice.cpp deleted file mode 100644 index eca8e64ea..000000000 --- a/Engine/source/sfx/xaudio/sfxXAudioDevice.cpp +++ /dev/null @@ -1,245 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "sfx/xaudio/sfxXAudioDevice.h" -#include "platform/async/asyncUpdate.h" -#include "core/stringTable.h" -#include "console/console.h" -#include "core/util/safeRelease.h" -#include "core/tAlgorithm.h" -#include "platform/profiler.h" - - -SFXXAudioDevice::SFXXAudioDevice( SFXProvider* provider, - const String& name, - IXAudio2 *xaudio, - U32 deviceIndex, - U32 speakerChannelMask, - U32 maxBuffers ) - : Parent( name, provider, false, maxBuffers ), - mXAudio( xaudio ), - mMasterVoice( NULL ) -{ - dMemset( &mListener, 0, sizeof( mListener ) ); - - // If mMaxBuffers is negative then use some default value. - // to decide on a good maximum value... or set 8. - // - // TODO: We should change the terminology to voices! - if ( mMaxBuffers < 0 ) - mMaxBuffers = 64; - - // Create the mastering voice. - HRESULT hr = mXAudio->CreateMasteringVoice( &mMasterVoice, - XAUDIO2_DEFAULT_CHANNELS, - XAUDIO2_DEFAULT_SAMPLERATE, - 0, - deviceIndex, - NULL ); - if ( FAILED( hr ) || !mMasterVoice ) - { - Con::errorf( "SFXXAudioDevice - Failed creating master voice!" ); - return; - } - - mMasterVoice->GetVoiceDetails( &mMasterVoiceDetails ); - - // Init X3DAudio. - X3DAudioInitialize( speakerChannelMask, - X3DAUDIO_SPEED_OF_SOUND, - mX3DAudio ); - - // Start the update thread. - - if( !Con::getBoolVariable( "$_forceAllMainThread" ) ) - { - SFXInternal::gUpdateThread = new AsyncUpdateThread - ( "XAudio Update Thread", SFXInternal::gBufferUpdateList ); - SFXInternal::gUpdateThread->start(); - } -} - - -SFXXAudioDevice::~SFXXAudioDevice() -{ - _releaseAllResources(); - - if ( mMasterVoice ) - { - mMasterVoice->DestroyVoice(); - mMasterVoice = NULL; - } - - // Kill the engine. - SAFE_RELEASE( mXAudio ); -} - - -SFXBuffer* SFXXAudioDevice::createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description ) -{ - SFXXAudioBuffer* buffer = SFXXAudioBuffer::create( stream, description ); - if ( !buffer ) - return NULL; - - _addBuffer( buffer ); - return buffer; -} - -SFXVoice* SFXXAudioDevice::createVoice( bool is3D, SFXBuffer *buffer ) -{ - // Don't bother going any further if we've - // exceeded the maximum voices. - if ( mVoices.size() >= mMaxBuffers ) - return NULL; - - AssertFatal( buffer, "SFXXAudioDevice::createVoice() - Got null buffer!" ); - - SFXXAudioBuffer* xaBuffer = dynamic_cast( buffer ); - AssertFatal( xaBuffer, "SFXXAudioDevice::createVoice() - Got bad buffer!" ); - - SFXXAudioVoice* voice = SFXXAudioVoice::create( mXAudio, is3D, xaBuffer ); - if ( !voice ) - return NULL; - - voice->mXAudioDevice = this; - - _addVoice( voice ); - return voice; -} - -void SFXXAudioDevice::_setOutputMatrix( SFXXAudioVoice *voice ) -{ - X3DAUDIO_DSP_SETTINGS dspSettings = {0}; - FLOAT32 matrix[12] = { 0 }; - dspSettings.DstChannelCount = mMasterVoiceDetails.InputChannels; - dspSettings.pMatrixCoefficients = matrix; - - const X3DAUDIO_EMITTER &emitter = voice->getEmitter(); - dspSettings.SrcChannelCount = emitter.ChannelCount; - - // Calculate the output volumes and doppler. - X3DAudioCalculate( mX3DAudio, - &mListener, - &emitter, - X3DAUDIO_CALCULATE_MATRIX | - X3DAUDIO_CALCULATE_DOPPLER, - &dspSettings ); - - voice->mXAudioVoice->SetOutputMatrix( mMasterVoice, - dspSettings.SrcChannelCount, - dspSettings.DstChannelCount, - dspSettings.pMatrixCoefficients, - 4321 ); - - voice->mXAudioVoice->SetFrequencyRatio( dspSettings.DopplerFactor * voice->mPitch, - 4321 ); - - // Commit the changes. - mXAudio->CommitChanges( 4321 ); -} - -void SFXXAudioDevice::update() -{ - PROFILE_SCOPE( SFXXAudioDevice_Update ); - - Parent::update(); - - X3DAUDIO_DSP_SETTINGS dspSettings = {0}; - FLOAT32 matrix[12] = { 0 }; - dspSettings.DstChannelCount = mMasterVoiceDetails.InputChannels; - dspSettings.pMatrixCoefficients = matrix; - - dspSettings.DopplerFactor = mDopplerFactor; - - // Now update the volume and frequency of - // all the active 3D voices. - VoiceVector::iterator voice = mVoices.begin(); - for ( ; voice != mVoices.end(); voice++ ) - { - SFXXAudioVoice* xaVoice = ( SFXXAudioVoice* ) *voice; - - // Skip 2D or stopped voices. - if ( !xaVoice->is3D() || - xaVoice->getStatus() != SFXStatusPlaying ) - continue; - - const X3DAUDIO_EMITTER &emitter = xaVoice->getEmitter(); - dspSettings.SrcChannelCount = emitter.ChannelCount; - - // Calculate the output volumes and doppler. - X3DAudioCalculate( mX3DAudio, - &mListener, - &emitter, - X3DAUDIO_CALCULATE_MATRIX | - X3DAUDIO_CALCULATE_DOPPLER, - &dspSettings ); - - xaVoice->mXAudioVoice->SetOutputMatrix( mMasterVoice, - dspSettings.SrcChannelCount, - dspSettings.DstChannelCount, - dspSettings.pMatrixCoefficients, - 4321 ) ; - - xaVoice->mXAudioVoice->SetFrequencyRatio( dspSettings.DopplerFactor * xaVoice->mPitch, - 4321 ); - } - - // Commit the changes. - mXAudio->CommitChanges( 4321 ); -} - -void SFXXAudioDevice::setListener( U32 index, const SFXListenerProperties& listener ) -{ - // Get the transform from the listener. - const MatrixF& transform = listener.getTransform(); - transform.getColumn( 3, (Point3F*)&mListener.Position ); - transform.getColumn( 1, (Point3F*)&mListener.OrientFront ); - transform.getColumn( 2, (Point3F*)&mListener.OrientTop ); - - // And the velocity... - const VectorF& velocity = listener.getVelocity(); - mListener.Velocity.x = velocity.x; - mListener.Velocity.y = velocity.y; - mListener.Velocity.z = velocity.z; - - // XAudio and Torque use opposite handedness, so - // flip the z coord to account for that. - mListener.Position.z *= -1.0f; - mListener.OrientFront.z *= -1.0f; - mListener.OrientTop.z *= -1.0f; - mListener.Velocity.z *= -1.0f; -} - -void SFXXAudioDevice::setDistanceModel( SFXDistanceModel model ) -{ - mDistanceModel = model; -} - -void SFXXAudioDevice::setDopplerFactor( F32 factor ) -{ - mDopplerFactor = factor; -} - -void SFXXAudioDevice::setRolloffFactor( F32 factor ) -{ - mRolloffFactor = factor; -} diff --git a/Engine/source/sfx/xaudio/sfxXAudioDevice.h b/Engine/source/sfx/xaudio/sfxXAudioDevice.h deleted file mode 100644 index 7e1d8a7ee..000000000 --- a/Engine/source/sfx/xaudio/sfxXAudioDevice.h +++ /dev/null @@ -1,101 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _SFXXAUDIODEVICE_H_ -#define _SFXXAUDIODEVICE_H_ - -class SFXProvider; - -#ifndef _SFXDEVICE_H_ -#include "sfx/sfxDevice.h" -#endif - -#ifndef _SFXPROVIDER_H_ -#include "sfx/sfxProvider.h" -#endif - -#ifndef _SFXXAUDIOVOICE_H_ -#include "sfx/xaudio/sfxXAudioVoice.h" -#endif - -#ifndef _SFXXAUDIOBUFFER_H_ -#include "sfx/xaudio/sfxXAudioBuffer.h" -#endif - -#include -#include - - -class SFXXAudioDevice : public SFXDevice -{ - public: - - typedef SFXDevice Parent; - friend class SFXXAudioVoice; // mXAudio - - protected: - - /// The XAudio engine interface passed - /// on creation from the provider. - IXAudio2 *mXAudio; - - /// The X3DAudio instance. - X3DAUDIO_HANDLE mX3DAudio; - - /// The one and only mastering voice. - IXAudio2MasteringVoice* mMasterVoice; - - /// The details of the master voice. - XAUDIO2_VOICE_DETAILS mMasterVoiceDetails; - - /// The one listener. - X3DAUDIO_LISTENER mListener; - - SFXDistanceModel mDistanceModel; - F32 mRolloffFactor; - F32 mDopplerFactor; - - public: - - SFXXAudioDevice( SFXProvider* provider, - const String& name, - IXAudio2 *xaudio, - U32 deviceIndex, - U32 speakerChannelMask, - U32 maxBuffers ); - - virtual ~SFXXAudioDevice(); - - // SFXDevice - virtual SFXBuffer* createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description ); - virtual SFXVoice* createVoice( bool is3D, SFXBuffer *buffer ); - virtual void update(); - virtual void setListener( U32 index, const SFXListenerProperties& listener ); - virtual void setDistanceModel( SFXDistanceModel model ); - virtual void setRolloffFactor( F32 factor ); - virtual void setDopplerFactor( F32 factor ); - - /// Called from the voice when its about to start playback. - void _setOutputMatrix( SFXXAudioVoice *voice ); -}; - -#endif // _SFXXAUDIODEVICE_H_ \ No newline at end of file diff --git a/Engine/source/sfx/xaudio/sfxXAudioProvider.cpp b/Engine/source/sfx/xaudio/sfxXAudioProvider.cpp deleted file mode 100644 index ab060ae5e..000000000 --- a/Engine/source/sfx/xaudio/sfxXAudioProvider.cpp +++ /dev/null @@ -1,188 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -// Note: This must be defined before platform.h so that -// CoInitializeEx is properly included. -#define _WIN32_DCOM -#include - -#include "sfx/xaudio/sfxXAudioDevice.h" -#include "sfx/sfxProvider.h" -#include "core/util/safeRelease.h" -#include "core/strings/unicode.h" -#include "core/strings/stringFunctions.h" -#include "console/console.h" -#include "core/module.h" - - -class SFXXAudioProvider : public SFXProvider -{ -public: - - SFXXAudioProvider() - : SFXProvider( "XAudio" ) {} - virtual ~SFXXAudioProvider(); - -protected: - - /// Extended SFXDeviceInfo to also store some - /// extra XAudio specific data. - struct XADeviceInfo : SFXDeviceInfo - { - UINT32 deviceIndex; - - XAUDIO2_DEVICE_ROLE role; - - WAVEFORMATEXTENSIBLE format; - }; - - /// Helper for creating the XAudio engine. - static bool _createXAudio( IXAudio2 **xaudio ); - -public: - - // SFXProvider - void init(); - SFXDevice* createDevice( const String& deviceName, bool useHardware, S32 maxBuffers ); - -}; - -MODULE_BEGIN( XAudio ) - - MODULE_INIT_BEFORE( SFX ) - MODULE_SHUTDOWN_AFTER( SFX ) - - SFXXAudioProvider* mProvider; - - MODULE_INIT - { - mProvider = new SFXXAudioProvider; - } - - MODULE_SHUTDOWN - { - delete mProvider; - } - -MODULE_END; - -SFXXAudioProvider::~SFXXAudioProvider() -{ -} - -void SFXXAudioProvider::init() -{ - // Create a temp XAudio object for device enumeration. - IXAudio2 *xAudio = NULL; - if ( !_createXAudio( &xAudio ) ) - { - Con::errorf( "SFXXAudioProvider::init() - XAudio2 failed to load!" ); - return; - } - - // Add the devices to the info list. - UINT32 count = 0; - xAudio->GetDeviceCount( &count ); - for ( UINT32 i = 0; i < count; i++ ) - { - XAUDIO2_DEVICE_DETAILS details; - HRESULT hr = xAudio->GetDeviceDetails( i, &details ); - if ( FAILED( hr ) ) - continue; - - // Add a device to the info list. - XADeviceInfo* info = new XADeviceInfo; - info->deviceIndex = i; - info->driver = String( "XAudio" ); - info->name = String( details.DisplayName ); - info->hasHardware = false; - info->maxBuffers = 64; - info->role = details.Role; - info->format = details.OutputFormat; - mDeviceInfo.push_back( info ); - } - - // We're done with XAudio for now. - SAFE_RELEASE( xAudio ); - - // If we have no devices... we're done. - if ( mDeviceInfo.empty() ) - { - Con::errorf( "SFXXAudioProvider::init() - No valid XAudio2 devices found!" ); - return; - } - - // If we got this far then we should be able to - // safely create a device for XAudio. - regProvider( this ); -} - -bool SFXXAudioProvider::_createXAudio( IXAudio2 **xaudio ) -{ - // In debug builds enable the debug version - // of the XAudio engine. - #ifdef TORQUE_DEBUG - #define XAUDIO_FLAGS XAUDIO2_DEBUG_ENGINE - #else - #define XAUDIO_FLAGS 0 - #endif - - // This must be called first... it doesn't hurt to - // call it more than once. - CoInitialize( NULL ); - - // Try creating the xaudio engine. - HRESULT hr = XAudio2Create( xaudio, XAUDIO_FLAGS, XAUDIO2_DEFAULT_PROCESSOR ); - - return SUCCEEDED( hr ) && (*xaudio); -} - -SFXDevice* SFXXAudioProvider::createDevice( const String& deviceName, bool useHardware, S32 maxBuffers ) -{ - String devName; - - devName = deviceName; - - XADeviceInfo* info = dynamic_cast< XADeviceInfo* >( _findDeviceInfo( devName ) ); - - // Do we find one to create? - if ( info ) - { - // Create the XAudio object to pass to the device. - IXAudio2 *xAudio = NULL; - if ( !_createXAudio( &xAudio ) ) - { - Con::errorf( "SFXXAudioProvider::createDevice() - XAudio2 failed to load!" ); - return NULL; - } - - return new SFXXAudioDevice( this, - devName, - xAudio, - info->deviceIndex, - info->format.dwChannelMask, - maxBuffers ); - } - - // We didn't find a matching valid device. - return NULL; -} diff --git a/Engine/source/sfx/xaudio/sfxXAudioVoice.cpp b/Engine/source/sfx/xaudio/sfxXAudioVoice.cpp deleted file mode 100644 index 80ba7745c..000000000 --- a/Engine/source/sfx/xaudio/sfxXAudioVoice.cpp +++ /dev/null @@ -1,445 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "sfx/xaudio/sfxXAudioVoice.h" -#include "sfx/xaudio/sfxXAudioDevice.h" -#include "sfx/xaudio/sfxXAudioBuffer.h" -#include "core/util/safeDelete.h" -#include "math/mMathFn.h" - - -//#define DEBUG_SPEW - - -static void sfxFormatToWAVEFORMATEX( const SFXFormat& format, WAVEFORMATEX *wfx ) -{ - dMemset( wfx, 0, sizeof( WAVEFORMATEX ) ); - wfx->wFormatTag = WAVE_FORMAT_PCM; - wfx->nChannels = format.getChannels(); - wfx->nSamplesPerSec = format.getSamplesPerSecond(); - wfx->wBitsPerSample = format.getBitsPerChannel(); - wfx->nBlockAlign = wfx->nChannels * wfx->wBitsPerSample / 8; - wfx->nAvgBytesPerSec = wfx->nSamplesPerSec * wfx->nBlockAlign; -} - - -SFXXAudioVoice* SFXXAudioVoice::create( IXAudio2 *xaudio, - bool is3D, - SFXXAudioBuffer *buffer, - SFXXAudioVoice* inVoice ) -{ - AssertFatal( xaudio, "SFXXAudioVoice::create() - Got null XAudio!" ); - AssertFatal( buffer, "SFXXAudioVoice::create() - Got null buffer!" ); - - // Create the voice object first as it also the callback object. - SFXXAudioVoice* voice = inVoice; - if( !voice ) - voice = new SFXXAudioVoice( buffer ); - - // Get the buffer format. - WAVEFORMATEX wfx; - sfxFormatToWAVEFORMATEX( buffer->getFormat(), &wfx ); - - // We don't support multi-channel 3d sounds! - if ( is3D && wfx.nChannels > 1 ) - return NULL; - - // Create the voice. - IXAudio2SourceVoice *xaVoice; - HRESULT hr = xaudio->CreateSourceVoice( &xaVoice, - (WAVEFORMATEX*)&wfx, - 0, - XAUDIO2_DEFAULT_FREQ_RATIO, - voice, - NULL, - NULL ); - - if( FAILED( hr ) || !voice ) - { - if( !inVoice ) - delete voice; - return NULL; - } - - voice->mIs3D = is3D; - voice->mEmitter.ChannelCount = wfx.nChannels; - voice->mXAudioVoice = xaVoice; - - return voice; -} - -SFXXAudioVoice::SFXXAudioVoice( SFXXAudioBuffer* buffer ) - : Parent( buffer ), - mXAudioDevice( NULL ), - mXAudioVoice( NULL ), - mIs3D( false ), - mPitch( 1.0f ), - mHasStopped( false ), - mHasStarted( false ), - mIsLooping( false ), - mIsPlaying( false ), - mNonStreamSampleStartPos( 0 ), - mNonStreamBufferLoaded( false ), - mSamplesPlayedOffset( 0 ) -{ - dMemset( &mEmitter, 0, sizeof( mEmitter ) ); - mEmitter.DopplerScaler = 1.0f; - - InitializeCriticalSection( &mLock ); -} - -SFXXAudioVoice::~SFXXAudioVoice() -{ - if ( mEmitter.pVolumeCurve ) - { - SAFE_DELETE_ARRAY( mEmitter.pVolumeCurve->pPoints ); - SAFE_DELETE( mEmitter.pVolumeCurve ); - } - - SAFE_DELETE( mEmitter.pCone ); - - if ( mXAudioVoice ) - mXAudioVoice->DestroyVoice(); - - DeleteCriticalSection( &mLock ); -} - -SFXStatus SFXXAudioVoice::_status() const -{ - if( mHasStopped ) - return SFXStatusStopped; - else if( mHasStarted ) - { - if( !mIsPlaying ) - return SFXStatusPaused; - else - return SFXStatusPlaying; - } - else - return SFXStatusStopped; -} - -void SFXXAudioVoice::_flush() -{ - AssertFatal( mXAudioVoice != NULL, - "SFXXAudioVoice::_flush() - invalid voice" ); - - EnterCriticalSection( &mLock ); - - mXAudioVoice->Stop( 0 ); - mXAudioVoice->FlushSourceBuffers(); - mNonStreamBufferLoaded = false; - - #ifdef DEBUG_SPEW - Platform::outputDebugString( "[SFXXAudioVoice] Flushed state" ); - #endif - - mIsPlaying = false; - mHasStarted = false; - mHasStopped = true; - - //WORKAROUND: According to the docs, SamplesPlayed reported by the - // voice should get reset as soon as we submit a new buffer to the voice. - // Alas it won't. So, save the current value here and offset our future - // play cursors. - - XAUDIO2_VOICE_STATE state; - mXAudioVoice->GetState( &state ); - mSamplesPlayedOffset = - S32( state.SamplesPlayed ); - - LeaveCriticalSection( &mLock ); -} - -void SFXXAudioVoice::_play() -{ - AssertFatal( mXAudioVoice != NULL, - "SFXXAudioVoice::_play() - invalid voice" ); - - // For non-streaming voices queue the data if we haven't yet. - - if( !mBuffer->isStreaming() && !mNonStreamBufferLoaded ) - _loadNonStreamed(); - - // Start playback. - - mXAudioVoice->Start( 0, 0 ); - - #ifdef DEBUG_SPEW - Platform::outputDebugString( "[SFXXAudioVoice] Started playback" ); - #endif - - mIsPlaying = true; - mHasStarted = true; - mHasStopped = false; -} - -void SFXXAudioVoice::_pause() -{ - AssertFatal( mXAudioVoice != NULL, - "SFXXAudioVoice::_pause() - invalid voice" ); - - mXAudioVoice->Stop( 0 ); - mIsPlaying = false; - - #ifdef DEBUG_SPEW - Platform::outputDebugString( "[SFXXAudioVoice] Paused playback" ); - #endif -} - -void SFXXAudioVoice::_stop() -{ - AssertFatal( mXAudioVoice != NULL, - "SFXXAudioVoice::_stop() - invalid voice" ); - - _flush(); - - mIsPlaying = false; - mHasStarted = false; - mHasStopped = true; - - #ifdef DEBUG_SPEW - Platform::outputDebugString( "[SFXXAudioVoice] Stopped playback" ); - #endif -} - -void SFXXAudioVoice::_seek( U32 sample ) -{ - #ifdef DEBUG_SPEW - Platform::outputDebugString( "[SFXXAudioVoice] Seeking to %i", sample ); - #endif - - mNonStreamSampleStartPos = sample; - - bool wasPlaying = mIsPlaying; - - _stop(); - if( wasPlaying ) - _play(); -} - -void SFXXAudioVoice::_loadNonStreamed() -{ - AssertFatal( !mBuffer->isStreaming(), "SFXXAudioVoice::_loadNonStreamed - must not be called on streaming voices" ); - AssertFatal( mXAudioVoice != NULL, "SFXXAudioVoice::_loadNonStreamed - invalid voice" ); - AssertWarn( !mNonStreamBufferLoaded, "SFXXAudioVoice::_nonStreamNonstreamed - Data already loaded" ); - - #ifdef DEBUG_SPEW - Platform::outputDebugString( "[SFXXAudioVoice] Loading non-stream buffer at %i", mNonStreamSampleStartPos ); - #endif - - EnterCriticalSection( &mLock ); - - const XAUDIO2_BUFFER& orgBuffer = _getBuffer()->mBufferQueue.front().mData; - - mNonStreamBuffer = orgBuffer; - - if( mNonStreamSampleStartPos ) - { - mNonStreamBuffer.PlayBegin = mNonStreamSampleStartPos; - mNonStreamBuffer.PlayLength = _getBuffer()->getNumSamples() - mNonStreamSampleStartPos; - mSamplesPlayedOffset += mNonStreamSampleStartPos; // Add samples that we are skipping. - mNonStreamSampleStartPos = 0; - } - - if( mIsLooping ) - { - mNonStreamBuffer.LoopCount = XAUDIO2_LOOP_INFINITE; - mNonStreamBuffer.LoopLength = _getBuffer()->getNumSamples(); - } - - // Submit buffer. - - mXAudioVoice->SubmitSourceBuffer( &mNonStreamBuffer ); - mNonStreamBufferLoaded = true; - - LeaveCriticalSection( &mLock ); -} - -U32 SFXXAudioVoice::_tell() const -{ - XAUDIO2_VOICE_STATE state; - mXAudioVoice->GetState( &state ); - - // Workaround SamplesPlayed not getting reset. - return ( state.SamplesPlayed + mSamplesPlayedOffset ); -} - -void SFXXAudioVoice::setMinMaxDistance( F32 min, F32 max ) -{ - // Set the overall volume curve scale. - mEmitter.CurveDistanceScaler = max; - - // The curve uses normalized distances, so - // figure out the normalized min distance. - F32 normMin = 0.0f; - if ( min > 0.0f ) - normMin = min / max; - - // See what type of curve we are supposed to generate. - const bool linear = ( mXAudioDevice->mDistanceModel == SFXDistanceModelLinear ); - - // Have we setup the curve yet? - if( !mEmitter.pVolumeCurve - || ( linear && mEmitter.pVolumeCurve->PointCount != 2 ) - || ( !linear && mEmitter.pVolumeCurve->PointCount != 6 ) ) - { - if( !mEmitter.pVolumeCurve ) - mEmitter.pVolumeCurve = new X3DAUDIO_DISTANCE_CURVE; - else - SAFE_DELETE_ARRAY( mEmitter.pVolumeCurve->pPoints ); - - // We use 6 points for logarithmic volume curves and 2 for linear volume curves. - if( linear ) - { - mEmitter.pVolumeCurve->pPoints = new X3DAUDIO_DISTANCE_CURVE_POINT[ 2 ]; - mEmitter.pVolumeCurve->PointCount = 2; - } - else - { - mEmitter.pVolumeCurve->pPoints = new X3DAUDIO_DISTANCE_CURVE_POINT[ 6 ]; - mEmitter.pVolumeCurve->PointCount = 6; - } - - // The first and last points are known - // and will not change. - mEmitter.pVolumeCurve->pPoints[ 0 ].Distance = 0.0f; - mEmitter.pVolumeCurve->pPoints[ 0 ].DSPSetting = 1.0f; - mEmitter.pVolumeCurve->pPoints[ linear ? 1 : 5 ].Distance = 1.0f; - mEmitter.pVolumeCurve->pPoints[ linear ? 1 : 5 ].DSPSetting = 0.0f; - } - - if( !linear ) - { - // Set the second point of the curve. - mEmitter.pVolumeCurve->pPoints[1].Distance = normMin; - mEmitter.pVolumeCurve->pPoints[1].DSPSetting = 1.0f; - - // The next three points are calculated to - // give the sound a rough logarithmic falloff. - F32 distStep = ( 1.0f - normMin ) / 4.0f; - for ( U32 i=0; i < 3; i++ ) - { - U32 index = 2 + i; - F32 dist = normMin + ( distStep * (F32)( i + 1 ) ); - - mEmitter.pVolumeCurve->pPoints[index].Distance = dist; - mEmitter.pVolumeCurve->pPoints[index].DSPSetting = 1.0f - log10( dist * 10.0f ); - } - } -} - -void SFXXAudioVoice::OnBufferEnd( void* bufferContext ) -{ - if( mBuffer->isStreaming() ) - SFXInternal::TriggerUpdate(); -} - -void SFXXAudioVoice::OnStreamEnd() -{ - // Warning: This is being called within the XAudio - // thread, so be sure you're thread safe! - - mHasStopped = true; - - if( mBuffer->isStreaming() ) - SFXInternal::TriggerUpdate(); - else - _stop(); -} - -void SFXXAudioVoice::play( bool looping ) -{ - // Give the device a chance to calculate our positional - // audio settings before we start playback... this is - // important else we get glitches. - if( mIs3D ) - mXAudioDevice->_setOutputMatrix( this ); - - mIsLooping = looping; - Parent::play( looping ); -} - -void SFXXAudioVoice::setVelocity( const VectorF& velocity ) -{ - mEmitter.Velocity.x = velocity.x; - mEmitter.Velocity.y = velocity.y; - - // XAudio and Torque use opposite handedness, so - // flip the z coord to account for that. - mEmitter.Velocity.z = -velocity.z; -} - -void SFXXAudioVoice::setTransform( const MatrixF& transform ) -{ - transform.getColumn( 3, (Point3F*)&mEmitter.Position ); - transform.getColumn( 1, (Point3F*)&mEmitter.OrientFront ); - transform.getColumn( 2, (Point3F*)&mEmitter.OrientTop ); - - // XAudio and Torque use opposite handedness, so - // flip the z coord to account for that. - mEmitter.Position.z *= -1.0f; - mEmitter.OrientFront.z *= -1.0f; - mEmitter.OrientTop.z *= -1.0f; -} - -void SFXXAudioVoice::setVolume( F32 volume ) -{ - mXAudioVoice->SetVolume( volume ); -} - -void SFXXAudioVoice::setPitch( F32 pitch ) -{ - mPitch = mClampF( pitch, XAUDIO2_MIN_FREQ_RATIO, XAUDIO2_DEFAULT_FREQ_RATIO ); - mXAudioVoice->SetFrequencyRatio( mPitch ); -} - -void SFXXAudioVoice::setCone( F32 innerAngle, F32 outerAngle, F32 outerVolume ) -{ - // If the cone is set to 360 then the - // cone is null and doesn't need to be - // set on the voice. - if ( mIsEqual( innerAngle, 360 ) ) - { - SAFE_DELETE( mEmitter.pCone ); - return; - } - - if ( !mEmitter.pCone ) - { - mEmitter.pCone = new X3DAUDIO_CONE; - - // The inner volume is always 1... the overall - // volume is what scales it. - mEmitter.pCone->InnerVolume = 1.0f; - - // We don't use these yet. - mEmitter.pCone->InnerLPF = 0.0f; - mEmitter.pCone->OuterLPF = 0.0f; - mEmitter.pCone->InnerReverb = 0.0f; - mEmitter.pCone->OuterReverb = 0.0f; - } - - mEmitter.pCone->InnerAngle = mDegToRad( innerAngle ); - mEmitter.pCone->OuterAngle = mDegToRad( outerAngle ); - mEmitter.pCone->OuterVolume = outerVolume; -} diff --git a/Engine/source/sfx/xaudio/sfxXAudioVoice.h b/Engine/source/sfx/xaudio/sfxXAudioVoice.h deleted file mode 100644 index 93500fcc4..000000000 --- a/Engine/source/sfx/xaudio/sfxXAudioVoice.h +++ /dev/null @@ -1,154 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _SFXXAUDIOVOICE_H_ -#define _SFXXAUDIOVOICE_H_ - -#include -#include - -#include "sfx/sfxVoice.h" - - -class SFXXAudioBuffer; - - -class SFXXAudioVoice : public SFXVoice, - public IXAudio2VoiceCallback -{ - public: - - typedef SFXVoice Parent; - - friend class SFXXAudioDevice; - friend class SFXXAudioBuffer; - - protected: - - /// This constructor does not create a valid voice. - /// @see SFXXAudioVoice::create - SFXXAudioVoice( SFXXAudioBuffer* buffer ); - - /// The device that created us. - SFXXAudioDevice *mXAudioDevice; - - /// The XAudio voice. - IXAudio2SourceVoice *mXAudioVoice; - - /// - CRITICAL_SECTION mLock; - - /// Used to know what sounds need positional updates. - bool mIs3D; - - /// Whether the voice has stopped playing. - mutable bool mHasStopped; - - /// Whether we have started playback. - bool mHasStarted; - - /// Whether playback is currently running. - bool mIsPlaying; - - /// Whether playback is looping. - bool mIsLooping; - - /// Since 3D sounds are pitch shifted for doppler - /// effect we need to track the users base pitch. - F32 mPitch; - - /// The cached X3DAudio emitter data. - X3DAUDIO_EMITTER mEmitter; - - /// XAudio does not reset the SamplesPlayed count as is stated in the docs. To work around - /// that, we offset the values reported by XAudio through this field. - S32 mSamplesPlayedOffset; - - /// @name Data for Non-Streaming Voices - /// @{ - - /// Whether we have loaded our non-streaming data. We use an explicit - /// flag here as we really can't rely on XAUDIO2_VOICE_STATE. - bool mNonStreamBufferLoaded; - - /// Audio buffer for non-streaming voice. - XAUDIO2_BUFFER mNonStreamBuffer; - - /// Sample to start playing at when seting up #mNonStreamBuffer. - U32 mNonStreamSampleStartPos; - - /// @} - - // IXAudio2VoiceCallback - void STDMETHODCALLTYPE OnStreamEnd(); - void STDMETHODCALLTYPE OnVoiceProcessingPassStart( UINT32 BytesRequired ) {} - void STDMETHODCALLTYPE OnVoiceProcessingPassEnd() {} - void STDMETHODCALLTYPE OnBufferEnd( void *bufferContext ); - void STDMETHODCALLTYPE OnBufferStart( void *bufferContext ) {} - void STDMETHODCALLTYPE OnLoopEnd( void *bufferContext ) {} - void STDMETHODCALLTYPE OnVoiceError( void * bufferContext, HRESULT error ) {} - - /// @deprecated This is only here for compatibility with - /// the March 2008 SDK version of IXAudio2VoiceCallback. - void STDMETHODCALLTYPE OnVoiceProcessingPassStart() {} - - void _flush(); - void _loadNonStreamed(); - - // SFXVoice. - virtual SFXStatus _status() const; - virtual void _play(); - virtual void _pause(); - virtual void _stop(); - virtual void _seek( U32 sample ); - virtual U32 _tell() const; - - SFXXAudioBuffer* _getBuffer() const { return ( SFXXAudioBuffer* ) mBuffer.getPointer(); } - - public: - - /// - static SFXXAudioVoice* create( IXAudio2 *xaudio, - bool is3D, - SFXXAudioBuffer *buffer, - SFXXAudioVoice* inVoice = NULL ); - - /// - virtual ~SFXXAudioVoice(); - - // SFXVoice - void setMinMaxDistance( F32 min, F32 max ); - void play( bool looping ); - void setVelocity( const VectorF& velocity ); - void setTransform( const MatrixF& transform ); - void setVolume( F32 volume ); - void setPitch( F32 pitch ); - void setCone( F32 innerAngle, F32 outerAngle, F32 outerVolume ); - - /// Is this a 3D positional voice. - bool is3D() const { return mIs3D; } - - /// - const X3DAUDIO_EMITTER& getEmitter() const { return mEmitter; } -}; - -#endif // _SFXXAUDIOVOICE_H_ \ No newline at end of file diff --git a/Templates/BaseGame/game/core/core.tscript b/Templates/BaseGame/game/core/core.tscript index c400b9227..13880cd27 100644 --- a/Templates/BaseGame/game/core/core.tscript +++ b/Templates/BaseGame/game/core/core.tscript @@ -70,9 +70,7 @@ function CoreModule::onCreate(%this) // Init the physics plugin. physicsInit(); - - sfxStartup(); - + // Set up networking. setNetPort(0); diff --git a/Templates/BaseGame/game/core/gui/scripts/canvas.tscript b/Templates/BaseGame/game/core/gui/scripts/canvas.tscript index 8d6a0d98b..cddee4ecb 100644 --- a/Templates/BaseGame/game/core/gui/scripts/canvas.tscript +++ b/Templates/BaseGame/game/core/gui/scripts/canvas.tscript @@ -25,6 +25,7 @@ function createCanvas(%windowTitle) if ($isDedicated) { GFXInit::createNullDevice(); + sfxCreateDevice("Null","Null Device", false, 8); return true; } diff --git a/Templates/BaseGame/game/core/sfx/Core_SFX.tscript b/Templates/BaseGame/game/core/sfx/Core_SFX.tscript index 771048b32..65eb5ef39 100644 --- a/Templates/BaseGame/game/core/sfx/Core_SFX.tscript +++ b/Templates/BaseGame/game/core/sfx/Core_SFX.tscript @@ -3,13 +3,21 @@ function Core_SFX::onCreate(%this) { exec("./scripts/audio." @ $TorqueScriptFileExtension); exec("./scripts/audioData." @ $TorqueScriptFileExtension); + exec("./scripts/audioStates." @ $TorqueScriptFileExtension); + exec("./scripts/audioEnvironments." @ $TorqueScriptFileExtension); exec("./scripts/audioAmbience." @ $TorqueScriptFileExtension); exec("./scripts/audioDescriptions." @ $TorqueScriptFileExtension); - exec("./scripts/audioEnvironments." @ $TorqueScriptFileExtension); - exec("./scripts/audioStates." @ $TorqueScriptFileExtension); exec("./scripts/audioOptions." @ $TorqueScriptFileExtension); } function Core_SFX::onDestroy(%this) { +} + +function Core_SFX::initClient(%this) +{ + if($pref::SFX::autoDetect) + { + AutodetectSound(); + } } \ No newline at end of file diff --git a/Templates/BaseGame/game/core/sfx/scripts/audio.tscript b/Templates/BaseGame/game/core/sfx/scripts/audio.tscript index 2d8726afc..b3cd76ba2 100644 --- a/Templates/BaseGame/game/core/sfx/scripts/audio.tscript +++ b/Templates/BaseGame/game/core/sfx/scripts/audio.tscript @@ -24,7 +24,11 @@ // Source groups. //----------------------------------------------------------------------------- -singleton SFXDescription( AudioMaster ); +singleton SFXDescription( AudioMaster ) +{ + useCustomReverb = false; +}; + singleton SFXSource( AudioChannelMaster ) { description = AudioMaster; @@ -33,8 +37,16 @@ singleton SFXSource( AudioChannelMaster ) singleton SFXDescription( AudioChannel ) { sourceGroup = AudioChannelMaster; + useCustomReverb = false; }; +singleton SFXDescription( AudioEffectChannel ) +{ + sourceGroup = AudioChannelMaster; + useCustomReverb = true; +}; + + singleton SFXSource( AudioChannelDefault ) { description = AudioChannel; @@ -45,7 +57,7 @@ singleton SFXSource( AudioChannelGui ) }; singleton SFXSource( AudioChannelEffects ) { - description = AudioChannel; + description = AudioEffectChannel; }; singleton SFXSource( AudioChannelMessages ) { @@ -66,7 +78,7 @@ AudioChannelMusic.play(); AudioChannelMessages.play(); // Stop in-game effects channels. -AudioChannelEffects.stop(); +AudioChannelEffects.play(); //----------------------------------------------------------------------------- // Master SFXDescriptions. @@ -145,10 +157,6 @@ function sfxStartup() function sfxInit() { // If already initialized, shut down the current device first. - - if( sfxGetDeviceInfo() !$= "" ) - sfxShutdown(); - if ($isDedicated) { sfxCreateDevice("Null","Null Device", false, 8); @@ -156,12 +164,16 @@ function sfxInit() } // Start it up! - %maxBuffers = $pref::SFX::useHardware ? -1 : $pref::SFX::maxSoftwareBuffers; - if ( !sfxCreateDevice( $pref::SFX::provider, $pref::SFX::device, $pref::SFX::useHardware, %maxBuffers ) ) - return false; + %info = sfxGetDeviceInfo(); + if(%info $= "" ) + { + %maxBuffers = $pref::SFX::useHardware ? -1 : $pref::SFX::maxSoftwareBuffers; + if ( !sfxCreateDevice() ) + return false; + } // This returns a tab seperated string with - // the initialized system info. + // the initialized system info %info = sfxGetDeviceInfo(); $pref::SFX::provider = getField( %info, 0 ); $pref::SFX::device = getField( %info, 1 ); @@ -440,4 +452,4 @@ function sfxResume( %pauseSet ) // Clear our pause set... the caller is left // to clear his own if he passed one. %pauseSet.clear(); -}*/ +}*/ \ No newline at end of file diff --git a/Templates/BaseGame/game/core/sfx/scripts/audioAmbience.tscript b/Templates/BaseGame/game/core/sfx/scripts/audioAmbience.tscript index 8c2bf270c..4b45ee113 100644 --- a/Templates/BaseGame/game/core/sfx/scripts/audioAmbience.tscript +++ b/Templates/BaseGame/game/core/sfx/scripts/audioAmbience.tscript @@ -23,22 +23,27 @@ singleton SFXAmbience( AudioAmbienceDefault ) { environment = AudioEnvOff; + dopplerFactor = "1"; }; singleton SFXAmbience( AudioAmbienceOutside ) { environment = AudioEnvPlain; states[ 0 ] = AudioLocationOutside; + dopplerFactor = "1"; }; singleton SFXAmbience( AudioAmbienceInside ) { environment = AudioEnvRoom; states[ 0 ] = AudioLocationInside; + dopplerFactor = "1"; }; singleton SFXAmbience( AudioAmbienceUnderwater ) { environment = AudioEnvUnderwater; states[ 0 ] = AudioLocationUnderwater; + dopplerFactor = "0.5"; + speedOfSound = "1500.0"; }; diff --git a/Templates/BaseGame/game/core/sfx/scripts/audioEnvironments.tscript b/Templates/BaseGame/game/core/sfx/scripts/audioEnvironments.tscript index 671825b6b..e66b863c6 100644 --- a/Templates/BaseGame/game/core/sfx/scripts/audioEnvironments.tscript +++ b/Templates/BaseGame/game/core/sfx/scripts/audioEnvironments.tscript @@ -24,893 +24,678 @@ // // For customized presets, best derive from one of these presets. -singleton SFXEnvironment( AudioEnvOff ) +singleton SFXEnvironment(AudioEnvOff) { - envSize = "7.5"; - envDiffusion = "1.0"; - room = "-10000"; - roomHF = "-10000"; - roomLF = "0"; - decayTime = "1.0"; - decayHFRatio = "1.0"; - decayLFRatio = "1.0"; - reflections = "-2602"; - reflectionsDelay = "0.007"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "200"; - reverbDelay = "0.011"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; + reverbDensity = "0.0"; + reverbDiffusion = "0.0"; + reverbGain = "0.0"; + reverbGainHF = "0.0"; + reverbGainLF = "0.0"; + reverbDecayTime = "0.1"; + reverbDecayHFRatio = "1.0"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.0"; + reflectionDelay = "0.0"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "0.0"; + lateReverbDelay = "0.0"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.075"; + reverbEchoDepth = "0.0"; + reverbModTime = "0.04"; + reverbModDepth = "0.0"; + airAbsorbtionGainHF = "1.0"; + reverbHFRef = "1000"; + reverbLFRef = "20"; + roomRolloffFactor = "0.0"; + decayHFLimit = "0"; +}; + +singleton SFXEnvironment(AudioEnvGeneric) +{ + reverbDensity = "0.5"; + reverbDiffusion = "0.5"; + reverbGain = "0.15"; + reverbGainHF = "0.15"; + reverbGainLF = "0.1"; + reverbDecayTime = "1.0"; + reverbDecayHFRatio = "1.0"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.2"; + reflectionDelay = "0.02"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "0.25"; + lateReverbDelay = "0.03"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.08"; + reverbEchoDepth = "0.05"; + reverbModTime = "0.1"; + reverbModDepth = "0.05"; + airAbsorbtionGainHF = "0.95"; + reverbHFRef = "5000"; + reverbLFRef = "100"; + roomRolloffFactor = "0.2"; + decayHFLimit = "1"; +}; + +singleton SFXEnvironment(AudioEnvPlain) +{ + reverbDensity = "0.05"; + reverbDiffusion = "0.15"; + reverbGain = "0.18"; + reverbGainHF = "0.12"; + reverbGainLF = "0.30"; + reverbDecayTime = "5.0"; + reverbDecayHFRatio = "0.5"; + reverbDecayLFRatio = "1.4"; + reflectionsGain = "0.005"; + reflectionDelay = "0.02"; + reflectionsPan = "0 0 0"; + lateReverbGain = "0.35"; + lateReverbDelay = "0.15"; + lateReverbPan = "0 0 0"; + reverbEchoTime = "0.17"; + reverbEchoDepth = "0.08"; + reverbModTime = "2.8"; + reverbModDepth = "0.25"; + airAbsorbtionGainHF = "0.90"; + reverbHFRef = "6500"; + reverbLFRef = "90"; + roomRolloffFactor = "0.05"; + decayHFLimit = "0"; +}; + +singleton SFXEnvironment(AudioEnvRoom) +{ + reverbDensity = "0.8"; + reverbDiffusion = "0.85"; + reverbGain = "0.35"; + reverbGainHF = "0.4"; + reverbGainLF = "0.25"; + reverbDecayTime = "1.8"; + reverbDecayHFRatio = "0.9"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.8"; + reflectionDelay = "0.03"; + reflectionsPan = "0.2 0.0 -0.2"; + lateReverbGain = "0.9"; + lateReverbDelay = "0.05"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.09"; + reverbEchoDepth = "0.15"; + reverbModTime = "0.2"; + reverbModDepth = "0.1"; + airAbsorbtionGainHF = "0.9"; + reverbHFRef = "7000"; + reverbLFRef = "60"; + roomRolloffFactor = "0.5"; + decayHFLimit = "1"; +}; + +singleton SFXEnvironment(AudioEnvPaddedCell) +{ + reverbDensity = "0.7"; + reverbDiffusion = "0.9"; + reverbGain = "0.5"; + reverbGainHF = "0.25"; + reverbGainLF = "0.15"; + reverbDecayTime = "2.0"; + reverbDecayHFRatio = "0.7"; + reverbDecayLFRatio = "0.9"; + reflectionsGain = "1.0"; + reflectionDelay = "0.015"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "1.2"; + lateReverbDelay = "0.02"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.1"; + reverbEchoDepth = "0.2"; + reverbModTime = "0.15"; + reverbModDepth = "0.1"; + airAbsorbtionGainHF = "0.85"; + reverbHFRef = "5000"; + reverbLFRef = "100"; + roomRolloffFactor = "0.8"; + decayHFLimit = "1"; +}; + +singleton SFXEnvironment(AudioEnvBathroom) +{ + reverbDensity = "0.9"; + reverbDiffusion = "0.95"; + reverbGain = "0.45"; + reverbGainHF = "0.8"; + reverbGainLF = "0.25"; + reverbDecayTime = "1.2"; + reverbDecayHFRatio = "1.5"; + reverbDecayLFRatio = "0.9"; + reflectionsGain = "2.5"; + reflectionDelay = "0.025"; + reflectionsPan = "0.5 -0.5 0.0"; + lateReverbGain = "0.9"; + lateReverbDelay = "0.04"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.08"; + reverbEchoDepth = "0.1"; + reverbModTime = "0.15"; + reverbModDepth = "0.05"; + airAbsorbtionGainHF = "0.95"; + reverbHFRef = "12000"; + reverbLFRef = "80"; + roomRolloffFactor = "0.8"; + decayHFLimit = "1"; +}; + + +singleton SFXEnvironment(AudioEnvLivingRoom) +{ + reverbDensity = "0.45"; + reverbDiffusion = "0.65"; + reverbGain = "0.30"; + reverbGainHF = "0.35"; + reverbGainLF = "0.20"; + reverbDecayTime = "0.7"; + reverbDecayHFRatio = "0.9"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.45"; + reflectionDelay = "0.010"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "0.45"; + lateReverbDelay = "0.025"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.09"; + reverbEchoDepth = "0.02"; + reverbModTime = "0.20"; + reverbModDepth = "0.02"; + airAbsorbtionGainHF = "0.95"; + reverbHFRef = "5000"; + reverbLFRef = "120"; + roomRolloffFactor = "0.2"; + decayHFLimit = "1"; +}; + +singleton SFXEnvironment(AudioEnvStoneRoom) +{ + reverbDensity = "0.70"; + reverbDiffusion = "0.85"; + reverbGain = "0.55"; + reverbGainHF = "0.45"; + reverbGainLF = "0.35"; + reverbDecayTime = "2.2"; + reverbDecayHFRatio = "0.8"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "1.1"; + reflectionDelay = "0.015"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "1.1"; + lateReverbDelay = "0.035"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.12"; + reverbEchoDepth = "0.05"; + reverbModTime = "0.30"; + reverbModDepth = "0.05"; + airAbsorbtionGainHF = "0.92"; + reverbHFRef = "4500"; + reverbLFRef = "80"; + roomRolloffFactor = "0.1"; + decayHFLimit = "1"; +}; + +singleton SFXEnvironment(AudioEnvAuditorium) +{ + reverbDensity = "0.65"; + reverbDiffusion = "0.85"; + reverbGain = "0.40"; + reverbGainHF = "0.42"; + reverbGainLF = "0.30"; + reverbDecayTime = "3.6"; + reverbDecayHFRatio = "0.7"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.20"; + reflectionDelay = "0.025"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "0.9"; + lateReverbDelay = "0.06"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.14"; + reverbEchoDepth = "0.02"; + reverbModTime = "0.25"; + reverbModDepth = "0.03"; + airAbsorbtionGainHF = "0.93"; + reverbHFRef = "5000"; + reverbLFRef = "100"; + roomRolloffFactor = "0.05"; + decayHFLimit = "1"; +}; + +singleton SFXEnvironment(AudioEnvConcertHall) +{ + reverbDensity = "0.66"; + reverbDiffusion = "0.88"; + reverbGain = "0.42"; + reverbGainHF = "0.40"; + reverbGainLF = "0.30"; + reverbDecayTime = "3.8"; + reverbDecayHFRatio = "0.75"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.18"; + reflectionDelay = "0.022"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "0.95"; + lateReverbDelay = "0.05"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.13"; + reverbEchoDepth = "0.02"; + reverbModTime = "0.22"; + reverbModDepth = "0.03"; + airAbsorbtionGainHF = "0.93"; + reverbHFRef = "4800"; + reverbLFRef = "100"; + roomRolloffFactor = "0.05"; + decayHFLimit = "1"; +}; + +singleton SFXEnvironment(AudioEnvCave) +{ + reverbDensity = "0.55"; + reverbDiffusion = "0.70"; + reverbGain = "0.60"; + reverbGainHF = "0.30"; + reverbGainLF = "0.40"; + reverbDecayTime = "3.0"; + reverbDecayHFRatio = "1.1"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "1.6"; + reflectionDelay = "0.020"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "1.6"; + lateReverbDelay = "0.04"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.16"; + reverbEchoDepth = "0.06"; + reverbModTime = "0.30"; + reverbModDepth = "0.06"; + airAbsorbtionGainHF = "0.90"; + reverbHFRef = "4500"; + reverbLFRef = "70"; + roomRolloffFactor = "0.1"; + decayHFLimit = "0"; +}; + +singleton SFXEnvironment(AudioEnvArena) +{ + reverbDensity = "0.60"; + reverbDiffusion = "0.85"; + reverbGain = "0.48"; + reverbGainHF = "0.38"; + reverbGainLF = "0.32"; + reverbDecayTime = "5.5"; + reverbDecayHFRatio = "0.6"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.6"; + reflectionDelay = "0.025"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "1.2"; + lateReverbDelay = "0.06"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.18"; + reverbEchoDepth = "0.04"; + reverbModTime = "0.30"; + reverbModDepth = "0.04"; + airAbsorbtionGainHF = "0.90"; + reverbHFRef = "4500"; + reverbLFRef = "90"; + roomRolloffFactor = "0.05"; + decayHFLimit = "0"; +}; + +singleton SFXEnvironment(AudioEnvHangar) +{ + reverbDensity = "0.50"; + reverbDiffusion = "0.60"; + reverbGain = "0.55"; + reverbGainHF = "0.30"; + reverbGainLF = "0.45"; + reverbDecayTime = "7.5"; + reverbDecayHFRatio = "0.5"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.8"; + reflectionDelay = "0.03"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "1.6"; + lateReverbDelay = "0.07"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.18"; + reverbEchoDepth = "0.03"; + reverbModTime = "0.35"; + reverbModDepth = "0.04"; + airAbsorbtionGainHF = "0.88"; + reverbHFRef = "4000"; + reverbLFRef = "80"; + roomRolloffFactor = "0.05"; + decayHFLimit = "0"; +}; + +singleton SFXEnvironment(AudioEnvCarpettedHallway) +{ + reverbDensity = "0.35"; + reverbDiffusion = "0.50"; + reverbGain = "0.18"; + reverbGainHF = "0.08"; + reverbGainLF = "0.18"; + reverbDecayTime = "0.35"; + reverbDecayHFRatio = "0.5"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.25"; + reflectionDelay = "0.004"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "0.22"; + lateReverbDelay = "0.02"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.09"; + reverbEchoDepth = "0.01"; + reverbModTime = "0.18"; + reverbModDepth = "0.02"; + airAbsorbtionGainHF = "0.88"; + reverbHFRef = "5000"; + reverbLFRef = "120"; + roomRolloffFactor = "0.25"; + decayHFLimit = "1"; +}; + +singleton SFXEnvironment(AudioEnvHallway) +{ + reverbDensity = "0.45"; + reverbDiffusion = "0.60"; + reverbGain = "0.30"; + reverbGainHF = "0.28"; + reverbGainLF = "0.22"; + reverbDecayTime = "1.2"; + reverbDecayHFRatio = "0.7"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.9"; + reflectionDelay = "0.007"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "0.8"; + lateReverbDelay = "0.03"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.10"; + reverbEchoDepth = "0.02"; + reverbModTime = "0.20"; + reverbModDepth = "0.03"; + airAbsorbtionGainHF = "0.90"; + reverbHFRef = "4500"; + reverbLFRef = "80"; + roomRolloffFactor = "0.12"; + decayHFLimit = "1"; +}; + +singleton SFXEnvironment(AudioEnvStoneCorridor) +{ + reverbDensity = "0.60"; + reverbDiffusion = "0.75"; + reverbGain = "0.50"; + reverbGainHF = "0.30"; + reverbGainLF = "0.32"; + reverbDecayTime = "2.6"; + reverbDecayHFRatio = "0.8"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "1.0"; + reflectionDelay = "0.013"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "1.0"; + lateReverbDelay = "0.04"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.14"; + reverbEchoDepth = "0.04"; + reverbModTime = "0.25"; + reverbModDepth = "0.05"; + airAbsorbtionGainHF = "0.90"; + reverbHFRef = "4200"; + reverbLFRef = "80"; + roomRolloffFactor = "0.1"; + decayHFLimit = "0"; +}; + +singleton SFXEnvironment(AudioEnvAlley) +{ + reverbDensity = "0.22"; + reverbDiffusion = "0.30"; + reverbGain = "0.15"; + reverbGainHF = "0.12"; + reverbGainLF = "0.22"; + reverbDecayTime = "1.1"; + reverbDecayHFRatio = "0.6"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.3"; + reflectionDelay = "0.007"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "0.25"; + lateReverbDelay = "0.02"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.12"; + reverbEchoDepth = "0.18"; + reverbModTime = "0.25"; + reverbModDepth = "0.02"; + airAbsorbtionGainHF = "0.90"; + reverbHFRef = "5000"; + reverbLFRef = "100"; + roomRolloffFactor = "0.08"; + decayHFLimit = "0"; +}; + +singleton SFXEnvironment(AudioEnvForest) +{ + reverbDensity = "0.10"; + reverbDiffusion = "0.20"; + reverbGain = "0.10"; + reverbGainHF = "0.08"; + reverbGainLF = "0.18"; + reverbDecayTime = "1.1"; + reverbDecayHFRatio = "0.5"; + reverbDecayLFRatio = "1.2"; + reflectionsGain = "0.02"; + reflectionDelay = "0.12"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "0.20"; + lateReverbDelay = "0.10"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.14"; + reverbEchoDepth = "0.60"; + reverbModTime = "0.40"; + reverbModDepth = "0.06"; + airAbsorbtionGainHF = "0.88"; + reverbHFRef = "4000"; + reverbLFRef = "90"; + roomRolloffFactor = "0.02"; + decayHFLimit = "0"; +}; + +singleton SFXEnvironment(AudioEnvCity) +{ + reverbDensity = "0.18"; + reverbDiffusion = "0.35"; + reverbGain = "0.18"; + reverbGainHF = "0.16"; + reverbGainLF = "0.22"; + reverbDecayTime = "1.4"; + reverbDecayHFRatio = "0.6"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.25"; + reflectionDelay = "0.010"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "0.22"; + lateReverbDelay = "0.06"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.16"; + reverbEchoDepth = "0.12"; + reverbModTime = "0.30"; + reverbModDepth = "0.04"; + airAbsorbtionGainHF = "0.90"; + reverbHFRef = "5000"; + reverbLFRef = "100"; + roomRolloffFactor = "0.05"; + decayHFLimit = "0"; +}; + +singleton SFXEnvironment(AudioEnvMountains) +{ + reverbDensity = "0.06"; + reverbDiffusion = "0.18"; + reverbGain = "0.12"; + reverbGainHF = "0.10"; + reverbGainLF = "0.20"; + reverbDecayTime = "3.2"; + reverbDecayHFRatio = "0.45"; + reverbDecayLFRatio = "1.3"; + reflectionsGain = "0.01"; + reflectionDelay = "0.30"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "0.25"; + lateReverbDelay = "0.10"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.20"; + reverbEchoDepth = "0.40"; + reverbModTime = "1.2"; + reverbModDepth = "0.10"; + airAbsorbtionGainHF = "0.88"; + reverbHFRef = "4500"; + reverbLFRef = "80"; + roomRolloffFactor = "0.02"; + decayHFLimit = "0"; +}; + +singleton SFXEnvironment(AudioEnvQuary) +{ + reverbDensity = "0.25"; + reverbDiffusion = "0.45"; + reverbGain = "0.28"; + reverbGainHF = "0.20"; + reverbGainLF = "0.30"; + reverbDecayTime = "2.1"; + reverbDecayHFRatio = "0.7"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.9"; + reflectionDelay = "0.060"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "0.9"; + lateReverbDelay = "0.04"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.14"; + reverbEchoDepth = "0.45"; + reverbModTime = "0.30"; + reverbModDepth = "0.06"; + airAbsorbtionGainHF = "0.90"; + reverbHFRef = "4200"; + reverbLFRef = "80"; + roomRolloffFactor = "0.05"; + decayHFLimit = "0"; +}; + +singleton SFXEnvironment(AudioEnvParkingLot) +{ + reverbDensity = "0.20"; + reverbDiffusion = "0.40"; + reverbGain = "0.16"; + reverbGainHF = "0.12"; + reverbGainLF = "0.22"; + reverbDecayTime = "1.3"; + reverbDecayHFRatio = "1.1"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.20"; + reflectionDelay = "0.010"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "0.22"; + lateReverbDelay = "0.03"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.12"; + reverbEchoDepth = "0.05"; + reverbModTime = "0.25"; + reverbModDepth = "0.04"; + airAbsorbtionGainHF = "0.90"; + reverbHFRef = "4800"; + reverbLFRef = "100"; + roomRolloffFactor = "0.04"; + decayHFLimit = "0"; +}; + +singleton SFXEnvironment(AudioEnvSewerPipe) +{ + reverbDensity = "0.42"; + reverbDiffusion = "0.60"; + reverbGain = "0.65"; + reverbGainHF = "0.18"; + reverbGainLF = "0.40"; + reverbDecayTime = "2.6"; + reverbDecayHFRatio = "0.35"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "1.8"; + reflectionDelay = "0.014"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "1.8"; + lateReverbDelay = "0.09"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.14"; + reverbEchoDepth = "0.02"; + reverbModTime = "0.20"; + reverbModDepth = "0.03"; + airAbsorbtionGainHF = "0.86"; + reverbHFRef = "3500"; + reverbLFRef = "60"; + roomRolloffFactor = "0.08"; + decayHFLimit = "0"; +}; + +singleton SFXEnvironment(AudioEnvUnderwater) +{ + reverbDensity = "0.85"; + reverbDiffusion = "0.95"; + reverbGain = "0.70"; + reverbGainHF = "0.20"; + reverbGainLF = "0.60"; + reverbDecayTime = "2.0"; + reverbDecayHFRatio = "0.3"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.6"; + reflectionDelay = "0.012"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "0.9"; + lateReverbDelay = "0.06"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.10"; + reverbEchoDepth = "0.12"; + reverbModTime = "1.2"; + reverbModDepth = "0.25"; + airAbsorbtionGainHF = "0.80"; + reverbHFRef = "1200"; + reverbLFRef = "50"; roomRolloffFactor = "0.0"; - diffusion = "0.0"; - density = "0.0"; - flags = 0x33; + decayHFLimit = "0"; }; -singleton SFXEnvironment( AudioEnvGeneric ) +singleton SFXEnvironment(AudioEnvDrugged) { - envSize = "7.5"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "-100"; - roomLF = "0"; - decayTime = "1.49"; - decayHFRatio = "0.83"; - decayLFRatio = "1.0"; - reflections = "-2602"; - reflectionsDelay = "0.007"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "200"; - reverbDelay = "0.011"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvRoom ) -{ - envSize = "1.9"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "-454"; - roomLF = "0"; - decayTime = "0.4"; - decayHFRatio = "0.83"; - decayLFRatio = "1.0"; - reflections = "-1646"; - reflectionsDelay = "0.002"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "53"; - reverbDelay = "0.003"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvPaddedCell ) -{ - envSize = "1.4"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "-6000"; - roomLF = "0"; - decayTime = "0.17"; - decayHFRatio = "0.1"; - decayLFRatio = "1.0"; - reflections = "-1204"; - reflectionsDelay = "0.001"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "207"; - reverbDelay = "0.002"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvBathroom ) -{ - envSize = "1.4"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "-1200"; - roomLF = "0"; - decayTime = "1.49"; - decayHFRatio = "0.54"; - decayLFRatio = "1.0"; - reflections = "-370"; - reflectionsDelay = "0.007"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "1030"; - reverbDelay = "0.011"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "60.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvLivingRoom ) -{ - envSize = "2.5"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "-6000"; - roomLF = "0"; - decayTime = "0.5"; - decayHFRatio = "0.1"; - decayLFRatio = "1.0"; - reflections = "-1376"; - reflectionsDelay = "0.003"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "-1104"; - reverbDelay = "0.004"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvStoneRoom ) -{ - envSize = "11.6"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "300"; - roomLF = "0"; - decayTime = "2.31"; - decayHFRatio = "0.64"; - decayLFRatio = "1.0"; - reflections = "-711"; - reflectionsDelay = "0.012"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "83"; - reverbDelay = "0.017"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "-5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvAuditorium ) -{ - envSize = "21.6"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "-476"; - roomLF = "0"; - decayTime = "4.32"; - decayHFRatio = "0.59"; - decayLFRatio = "1.0"; - reflections = "1"; - reflectionsDelay = "0.02"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "-289"; - reverbDelay = "0.03"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvConcertHall ) -{ - envSize = "19.6"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "-500"; - roomLF = "0"; - decayTime = "3.92"; - decayHFRatio = "0.7"; - decayLFRatio = "1.0"; - reflections = "-1230"; - reflectionsDelay = "0.02"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "-2"; - reverbDelay = "0.029"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvCave ) -{ - envSize = "14.6"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "0"; - roomLF = "0"; - decayTime = "2.91"; - decayHFRatio = "1.3"; - decayLFRatio = "1.0"; - reflections = "-602"; - reflectionsDelay = "0.015"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "-302"; - reverbDelay = "0.022"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x1f; -}; - -singleton SFXEnvironment( AudioEnvArena ) -{ - envSize = "36.2f"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "-698"; - roomLF = "0"; - decayTime = "7.24"; - decayHFRatio = "0.33"; - decayLFRatio = "1.0"; - reflections = "-1166"; - reflectionsDelay = "0.02"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "16"; - reverbDelay = "0.03"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvHangar ) -{ - envSize = "50.3"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "-1000"; - roomLF = "0"; - decayTime = "10.05"; - decayHFRatio = "0.23"; - decayLFRatio = "1.0"; - reflections = "-602"; - reflectionsDelay = "0.02"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "198"; - reverbDelay = "0.03"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvCarpettedHallway ) -{ - envSize = "1.9"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "-4000"; - roomLF = "0"; - decayTime = "0.3"; - decayHFRatio = "0.1"; - decayLFRatio = "1.0"; - reflections = "-1831"; - reflectionsDelay = "0.002"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "-1630"; - reverbDelay = "0.03"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvHallway ) -{ - envSize = "1.8"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "-300"; - roomLF = "0"; - decayTime = "1.49"; - decayHFRatio = "0.59"; - decayLFRatio = "1.0"; - reflections = "-1219"; - reflectionsDelay = "0.007"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "441"; - reverbDelay = "0.011"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvStoneCorridor ) -{ - envSize = "13.5"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "-237"; - roomLF = "0"; - decayTime = "2.7"; - decayHFRatio = "0.79"; - decayLFRatio = "1.0"; - reflections = "-1214"; - reflectionsDelay = "0.013"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "395"; - reverbDelay = "0.02"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvAlley ) -{ - envSize = "7.5"; - envDiffusion = "0.3"; - room = "-1000"; - roomHF = "-270"; - roomLF = "0"; - decayTime = "1.49"; - decayHFRatio = "0.86"; - decayLFRatio = "1.0"; - reflections = "-1204"; - reflectionsDelay = "0.007"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "-4"; - reverbDelay = "0.011"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.125"; - echoDepth = "0.95"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvForest ) -{ - envSize = "38.0"; - envDiffusion = "0.3"; - room = "-1000"; - roomHF = "-3300"; - roomLF = "0"; - decayTime = "1.49"; - decayHFRatio = "0.54"; - decayLFRatio = "1.0"; - reflections = "-2560"; - reflectionsDelay = "0.162"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "-229"; - reverbDelay = "0.088"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.125"; - echoDepth = "1.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "79.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvCity ) -{ - envSize = "7.5"; - envDiffusion = "0.5"; - room = "-1000"; - roomHF = "-800"; - roomLF = "0"; - decayTime = "1.49"; - decayHFRatio = "0.67"; - decayLFRatio = "1.0"; - reflections = "-2273"; - reflectionsDelay = "0.007"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "-1691"; - reverbDelay = "0.011"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "50.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvMountains ) -{ - envSize = "100.0"; - envDiffusion = "0.27"; - room = "-1000"; - roomHF = "-2500"; - roomLF = "0"; - decayTime = "1.49"; - decayHFRatio = "0.21"; - decayLFRatio = "1.0"; - reflections = "-2780"; - reflectionsDelay = "0.3"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "-1434"; - reverbDelay = "0.1"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "1.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "27.0"; - density = "100.0"; - flags = 0x1f; -}; - -singleton SFXEnvironment( AudioEnvQuary ) -{ - envSize = "17.5"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "-1000"; - roomLF = "0"; - decayTime = "1.49"; - decayHFRatio = "0.83"; - decayLFRatio = "1.0"; - reflections = "-10000"; - reflectionsDelay = "0.061"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "500"; - reverbDelay = "0.025"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.125"; - echoDepth = "0.7"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvPlain ) -{ - envSize = "42.5"; - envDiffusion = "0.21"; - room = "-1000"; - roomHF = "-2000"; - roomLF = "0"; - decayTime = "1.49"; - decayHFRatio = "0.5"; - decayLFRatio = "1.0"; - reflections = "-2466"; - reflectionsDelay = "0.179"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "-1926"; - reverbDelay = "0.1"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "1.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "21.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvParkingLot ) -{ - envSize = "8.3"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "0"; - roomLF = "0"; - decayTime = "1.65"; - decayHFRatio = "1.5"; - decayLFRatio = "1.0"; - reflections = "-1363"; - reflectionsDelay = "0.008"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "-1153"; - reverbDelay = "0.012"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x1f; -}; - -singleton SFXEnvironment( AudioEnvSewerPipe ) -{ - envSize = "1.7"; - envDiffusion = "0.8"; - room = "-1000"; - roomHF = "-1000"; - roomLF = "0"; - decayTime = "2.81"; - decayHFRatio = "0.14"; - decayLFRatio = "1.0"; - reflections = "429"; - reflectionsDelay = "0.014"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "1023"; - reverbDelay = "0.21"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "0.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "80.0"; - density = "60.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvUnderwater ) -{ - envSize = "1.8"; - envDiffusion = "1.0"; - room = "-1000"; - roomHF = "-4000"; - roomLF = "0"; - decayTime = "1.49"; - decayHFRatio = "0.1"; - decayLFRatio = "1.0"; - reflections = "-449"; - reflectionsDelay = "0.007"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "1700"; - reverbDelay = "0.011"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "1.18"; - modulationDepth = "0.348"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x3f; -}; - -singleton SFXEnvironment( AudioEnvDrugged ) -{ - envSize = "1.9"; - envDiffusion = "0.5"; - room = "-1000"; - roomHF = "0"; - roomLF = "0"; - decayTime = "8.39"; - decayHFRatio = "1.39"; - decayLFRatio = "1.0"; - reflections = "-115"; - reflectionsDelay = "0.002"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "985"; - reverbDelay = "0.03"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "0.25"; - modulationDepth = "1.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x1f; -}; - -singleton SFXEnvironment( AudioEnvDizzy ) -{ - envSize = "1.8"; - envDiffusion = "0.6"; - room = "-1000.0"; - roomHF = "-400"; - roomLF = "0"; - decayTime = "17.23"; - decayHFRatio = "0.56"; - decayLFRatio = "1.0"; - reflections = "-1713"; - reflectionsDelay = "0.02"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "-613"; - reverbDelay = "0.03"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "1.0"; - modulationTime = "0.81"; - modulationDepth = "0.31"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x1f; -}; - -singleton SFXEnvironment( AudioEnvPsychotic ) -{ - envSize = "1.0"; - envDiffusion = "0.5"; - room = "-1000"; - roomHF = "-151"; - roomLF = "0"; - decayTime = "7.56"; - decayHFRatio = "0.91"; - decayLFRatio = "1.0"; - reflections = "-626"; - reflectionsDelay = "0.02"; - reflectionsPan[ 0 ] = "0.0"; - reflectionsPan[ 1 ] = "0.0"; - reflectionsPan[ 2 ] = "0.0"; - reverb = "774"; - reverbDelay = "0.03"; - reverbPan[ 0 ] = "0.0"; - reverbPan[ 1 ] = "0.0"; - reverbPan[ 2 ] = "0.0"; - echoTime = "0.25"; - echoDepth = "0.0"; - modulationTime = "4.0"; - modulationDepth = "1.0"; - airAbsorptionHF = "-5.0"; - HFReference = "5000.0"; - LFReference = "250.0"; - roomRolloffFactor = "0.0"; - diffusion = "100.0"; - density = "100.0"; - flags = 0x1f; -}; + reverbDensity = "0.40"; + reverbDiffusion = "0.55"; + reverbGain = "0.50"; + reverbGainHF = "0.30"; + reverbGainLF = "0.35"; + reverbDecayTime = "4.0"; + reverbDecayHFRatio = "1.1"; + reverbDecayLFRatio = "1.0"; + reflectionsGain = "0.8"; + reflectionDelay = "0.010"; + reflectionsPan = "0.0 0.0 0.0"; + lateReverbGain = "1.1"; + lateReverbDelay = "0.04"; + lateReverbPan = "0.0 0.0 0.0"; + reverbEchoTime = "0.20"; + reverbEchoDepth = "0.20"; + reverbModTime = "0.75"; + reverbModDepth = "0.40"; + airAbsorbtionGainHF = "0.88"; + reverbHFRef = "4200"; + reverbLFRef = "90"; + roomRolloffFactor = "0.05"; + decayHFLimit = "0"; +}; \ No newline at end of file diff --git a/Templates/BaseGame/game/core/sfx/scripts/audioOptions.tscript b/Templates/BaseGame/game/core/sfx/scripts/audioOptions.tscript index eb72c3f86..94aed17fa 100644 --- a/Templates/BaseGame/game/core/sfx/scripts/audioOptions.tscript +++ b/Templates/BaseGame/game/core/sfx/scripts/audioOptions.tscript @@ -6,8 +6,8 @@ new SimGroup(AudioSettingsGroup) new SimGroup() { class = "SubOptionsGroup"; - displayName = "Audio Devices"; - + displayName = "Audio Settings"; + new SimGroup(AudioSettingsProviderGroup) { class = "AudioOptionsSettings"; @@ -15,7 +15,7 @@ new SimGroup(AudioSettingsGroup) OptionName = "Audio Provider"; Description = ""; }; - + new SimGroup(AudioSettingsDeviceGroup) { class = "AudioOptionsSettings"; @@ -26,58 +26,92 @@ new SimGroup(AudioSettingsGroup) }; }; +function getDeviceDisplayName(%fullName) +{ + %openPos = strstr(%fullName, "("); + %closePos = strstr(%fullName, ")"); + + if (%openPos == -1 || %closePos == -1) + return %fullName; + + // +1 to skip past the "(" itself + return trim(getSubStr(%fullName, %openPos + 1, %closePos - %openPos - 1)); +} + function AudioSettingsGroup::populateSettings(%this) { AudioSettingsProviderGroup.clear(); AudioSettingsDeviceGroup.clear(); - %buffer = sfxGetAvailableDevices(); - %count = getRecordCount( %buffer ); + %pCount = sfxGetProviderCount(); - for(%i = 0; %i < %count; %i++) + // --- First pass: build deduplicated provider list --- + for (%i = 0; %i < %pCount; %i++) { - %record = getRecord(%buffer, %i); - %provider = getField(%record, 0); - %device = getField(%record, 1); + %providerType = sfxGetProviderType(%i); - //When the client is actually running, we don't care about null audo devices - if(%provider $= "null") + if (%providerType $= "NullProvider") continue; - - //We can't have duplicate providers, so double check for uniqueness - %foundProvider = false; - foreach(%registeredProviders in AudioSettingsProviderGroup) + + %alreadyAdded = false; + foreach (%entry in AudioSettingsProviderGroup) { - if(%registeredProviders.displayName $= %provider) + if (%entry.displayName $= %providerType) { - %foundProvider = true; + %alreadyAdded = true; break; } } - if(!%foundProvider) + if (!%alreadyAdded) { - //Provider entry %providerEntry = new ArrayObject() { - class = "OptionsQualityLevel"; - displayName = %provider; - key["$pref::SFX::provider"] = %provider; + class = "OptionsQualityLevel"; + displayName = %providerType; + key["$pref::SFX::provider"] = %providerType; }; - AudioSettingsProviderGroup.add(%providerEntry); } - - //Device Entry - %deviceEntry = new ArrayObject() - { - class = "OptionsQualityLevel"; - displayName = %device; - provider = %provider; //this is for filtering later, if we need to - key["$pref::SFX::device"] = %device; - }; + } + + // --- Second pass: for each provider, collect its devices --- + foreach (%providerEntry in AudioSettingsProviderGroup) + { + %providerType = %providerEntry.displayName; - AudioSettingsDeviceGroup.add(%deviceEntry); + for (%i = 0; %i < %pCount; %i++) + { + if (sfxGetProviderType(%i) !$= %providerType) + continue; + + %deviceName = sfxGetProviderDevice(%i); + + %deviceEntry = new ArrayObject() + { + class = "OptionsQualityLevel"; + displayName = getDeviceDisplayName(%deviceName); + providerType = %providerType; + key["$pref::SFX::device"] = %deviceName; + }; + AudioSettingsDeviceGroup.add(%deviceEntry); + } + } + + // Highlight the currently active entries + %activeProvider = $pref::SFX::provider; + %activeDevice = $pref::SFX::device; + + foreach (%entry in AudioSettingsProviderGroup) + { + if (%entry.displayName $= %activeProvider) + AudioSettingsProviderGroup.currentValue = %activeProvider; + } + + foreach (%entry in AudioSettingsDeviceGroup) + { + if (%entry.displayName $= %activeDevice && %entry.providerType $= %activeProvider) + AudioSettingsDeviceGroup.currentValue = %activeDevice; } } @@ -93,11 +127,15 @@ function AudioSettingsDeviceGroup::onApply(%this) function updateAudioOptionsSettings() { - if ( !sfxCreateDevice( $pref::SFX::provider, - $pref::SFX::device, - $pref::SFX::useHardware, - -1 ) ) + if ( !sfxCreateDeviceFromName($pref::SFX::provider, $pref::SFX::device) ) error( "Unable to create SFX device: " @ $pref::SFX::provider SPC $pref::SFX::device SPC $pref::SFX::useHardware ); +} + +function AutodetectSound() +{ + // Nothing to actually do in here? + // function here for convenience. + $pref::SFX::autoDetect = false; } \ No newline at end of file diff --git a/Templates/BaseGame/game/data/UI/guis/optionsMenu.tscript b/Templates/BaseGame/game/data/UI/guis/optionsMenu.tscript index f502982ad..d3ab3dca8 100644 --- a/Templates/BaseGame/game/data/UI/guis/optionsMenu.tscript +++ b/Templates/BaseGame/game/data/UI/guis/optionsMenu.tscript @@ -223,7 +223,6 @@ function OptionsMenu::openOptionsCategory(%this, %categoryName) else if(%categoryName $= "Audio") { $MenuList = AudioSettingsList; - %this.currentCatgeoryIdx = 1; } else if(%categoryName $= "KBM") @@ -856,6 +855,8 @@ function OptionsMenu::resetSettings(%this) function OptionsMenu::populateAudioSettings(%this) { AudioSettingsList.clear(); + OptionsMenu.optsListCount = -1; + AudioSettingsGroup.populateSettings(); //Process the lists diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/sound.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/sound.tscript index 5a90c3d6b..db71754f9 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/sound.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/sound.tscript @@ -12,6 +12,53 @@ function SoundAsset::onChanged(%this) if (isObject($PreviewSoundSource)) sfxStop($PreviewSoundSource); } +function SoundAsset::onShowActionMenu(%this) +{ + GenericAsset::onShowActionMenu(%this); + + %assetId = %this.getAssetId(); + + EditAssetPopup.objectData = %assetId; + EditAssetPopup.objectType = AssetDatabase.getAssetType(%assetId); + + EditAssetPopup.reloadItems(); + + EditAssetPopup.showPopup(Canvas); +} + + +function SoundAsset::onEditProperties(%this) +{ + Canvas.pushDialog(AssetBrowser_editAsset); + + AssetBrowser_editAssetWindow.text = "Asset Properties - " @ %this.getAssetId(); + + AssetEditInspector.tempAsset = %this.deepClone(); + + AssetEditInspector.inspect(%this); + AssetBrowser_editAsset.editedObjectData = %this.getAssetId(); + AssetBrowser_editAsset.editedObject = %this; + AssetBrowser_editAsset.editedObjectType = AssetDatabase.getAssetType(%this.getAssetId()); + + //remove some of the groups we don't need: + for(%i=0; %i < AssetEditInspector.getCount(); %i++) + { + %caption = AssetEditInspector.getObject(%i).caption; + + if(%caption $= "Ungrouped" || %caption $= "Object" || %caption $= "Editing" + || %caption $= "Persistence" || %caption $= "Dynamic Fields") + { + AssetEditInspector.remove(AssetEditInspector.getObject(%i)); + %i--; + } + } +} + +//Called when the AssetType has it's properties saved from the onEditProperties process +function SoundAsset::onSaveProperties(%this) +{ + %this.refreshAsset(); +} function SoundAsset::buildBrowserElement(%this, %previewData) { diff --git a/Tools/CMake/modules/dsound.cmake b/Tools/CMake/modules/dsound.cmake deleted file mode 100644 index f91225d39..000000000 --- a/Tools/CMake/modules/dsound.cmake +++ /dev/null @@ -1,8 +0,0 @@ -# OpenAL module -option(TORQUE_SFX_DIRECTX "Use DirectSound SFX" OFF) - -if(TORQUE_SFX_DIRECTX AND WIN32) - message("Enabling DirectSound Module") - - torqueAddSourceDirectories("${CMAKE_SOURCE_DIR}/Engine/source/sfx/dsound" "${CMAKE_SOURCE_DIR}/Engine/source/sfx/xaudio") -endif(TORQUE_SFX_DIRECTX AND WIN32)