Torque3D/Engine/source/sfx/sfxSystem.h
marauder2k7 974f217b96 SFX API Changes
DSound has since been deprecated and xaudio2 would require us to write our own 3d spatialization and mixer
Load devices the same way we load in the gfx end
setup sfx provider
run sfx devices on startup
various fixes around sfx null device
added the bitrate and samplerate globals
added the hrtf global code is in to use this but not setup yet
Adds speed of sound to the sound system
SFXAmbience now has a property for speed of sound for different mediums, can also be set directly
2026-04-13 14:55:43 +01:00

466 lines
15 KiB
C++

//-----------------------------------------------------------------------------
// 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 _SFXSYSTEM_H_
#define _SFXSYSTEM_H_
#ifndef _SFXPROVIDER_H_
#include "sfx/sfxProvider.h"
#endif // !_SFXPROVIDER_H_
#ifndef _TSIGNAL_H_
#include "core/util/tSignal.h"
#endif
#ifndef _TVECTOR_H_
#include "core/util/tVector.h"
#endif
#ifndef _THREADSAFEREFCOUNT_H_
#include "platform/threads/threadSafeRefCount.h"
#endif
class SFXTrack;
class SFXDevice;
class SFXProfile;
class SFXStream;
class SFXAmbience;
class SFXSoundscapeManager;
class SFXSource;
class SFXSound;
class SFXBuffer;
class SFXDescription;
/// SFX system events that can be received notifications on.
enum SFXSystemEventType
{
/// SFX is being updated.
SFXSystemEvent_Update,
/// New SFXDevice has been created.
SFXSystemEvent_CreateDevice,
/// SFXDevice is about to be destroyed.
SFXSystemEvent_DestroyDevice,
};
/// SFXSystemPlugins are used to allow other subsystems hook into core functionality
/// of the sound system.
class SFXSystemPlugin
{
public:
///
virtual void update() {}
///
virtual SFXSource* createSource( SFXTrack* track ) { return NULL; }
/// Filter the given reverb setup before it is set up on the device. This
/// allows to, for example, modify the current reverb depending on listener
/// location.
virtual void filterReverb( SFXReverbProperties& reverb ) {}
};
/// This class provides access to the sound system.
///
/// There are a few script preferences that are used by
/// the sound providers.
///
/// $pref::SFX::frequency - This is the playback frequency
/// for the primary sound buffer used for mixing. Although
/// most providers will reformat on the fly, for best quality
/// and performance match your sound files to this setting.
///
/// $pref::SFX::bitrate - This is the playback bitrate for
/// the primary sound buffer used for mixing. Although most
/// providers will reformat on the fly, for best quality
/// and performance match your sound files to this setting.
///
class SFXSystem
{
friend class SFXSound; // _assignVoices
friend class SFXSource; // _onAddSource, _onRemoveSource.
friend class SFXProfile; // _createBuffer.
public:
/// Allows device to register themselves as available
typedef Signal<void(Vector<SFXProvider*>&)> 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<SFXProvider*>* providers);
static const char* getProviderNameFromType(SFXProviderType type);
static SFXProvider* getBestProviderChoice();
static SFXProvider* getProvider(U32 index);
typedef Signal< void( SFXSystemEventType event ) > EventSignalType;
typedef Vector< SFXSource* > SFXSourceVector;
typedef Vector< SFXSound* > SFXSoundVector;
private:
/// List of known adapters.
static Vector<SFXProvider*> 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();
/// 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;
/// The last time the sources got an update.
U32 mLastSourceUpdateTime;
///
U32 mLastAmbientUpdateTime;
///
U32 mLastParameterUpdateTime;
/// The distance model used for rolloff curve computation on 3D sounds.
SFXDistanceModel mDistanceModel;
/// The current doppler scale factor.
F32 mDopplerFactor;
/// The current speed of sound.
F32 mSpeedOfSound;
/// The current curve rolloff factor.
F32 mRolloffFactor;
/// The current position and orientation of all listeners.
Vector< SFXListenerProperties > mListeners;
/// Current global reverb properties.
SFXReverbProperties mReverb;
/// SFX system event signal.
EventSignalType mEventSignal;
/// Ambient soundscape manager.
SFXSoundscapeManager* mSoundscapeMgr;
/// List of plugins currently linked to the SFX system.
Vector< SFXSystemPlugin* > mPlugins;
/// @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;
/// @}
/// 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();
///
void _assignVoice( SFXSound* sound );
///
void _sortSounds( const SFXListenerProperties& listener );
/// 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 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 );
///
SFXDevice* _getDevice() const { return mDevice; }
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; }
/// 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 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 );
/// Unregister the given plugin with the system.
void removePlugin( SFXSystemPlugin* plugin );
/// @name Device Management
/// @{
/// 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 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 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 );
}
/// 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 );
/// @}
/// @}
/// @name Listeners
/// @{
/// 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 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() );
}
/// @}
/// @name 3D Sound Configuration
/// {
/// Return the curve model currently used distance attenuation of positional sounds.
SFXDistanceModel getDistanceModel() const { return mDistanceModel; }
///
void setDistanceModel( SFXDistanceModel model );
///
F32 getDopplerFactor() const { return mDopplerFactor; }
///
void setDopplerFactor( F32 factor );
///
F32 getRolloffFactor() const { return mRolloffFactor; }
/// <summary>
/// Change the devices speed of sound.
/// </summary>
/// <param name="speedOfSound">F32 for speed of sound.</param>
void setSpeedOfSound(F32 speedOfSound);
///
void setRolloffFactor( F32 factor );
///
const SFXReverbProperties& getReverb() const { return mReverb; }
///
void setReverb( const SFXReverbProperties& reverb );
/// @}
///
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 );
/// 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);
///
void notifyTrackChanged( SFXTrack* track );
};
/// Less verbose macro for accessing the SFX singleton. This
/// should be the prefered method for accessing the system.
///
/// @see SFXSystem
/// @see SFXSystem::getSingleton()
///
#define SFX SFXSystem::getSingleton()
#endif // _SFXSYSTEM_H_