| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- /*
- ** Command & Conquer Generals(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- //----------------------------------------------------------------------------
- //
- // Westwood Studios Pacific.
- //
- // Confidential Information
- // Copyright (C) 2001 - All Rights Reserved
- //
- //----------------------------------------------------------------------------
- //
- // Project: RTS 3
- //
- // File name: Common/GameAudio.h
- //
- // Created: 5/01/01
- //
- //----------------------------------------------------------------------------
- #pragma once
- #ifndef __COMMON_GAMEAUDIO_H_
- #define __COMMON_GAMEAUDIO_H_
- // Includes
- #include "Lib/BaseType.h"
- #include "Common/STLTypedefs.h"
- #include "Common/SubsystemInterface.h"
- // Forward Declarations
- class AsciiString;
- class AudioEventRTS;
- class DebugDisplayInterface;
- class Drawable;
- class MusicManager;
- class Object;
- class SoundManager;
- enum AudioAffect;
- enum AudioType;
- struct AudioEventInfo;
- struct AudioRequest;
- struct AudioSettings;
- struct MiscAudio;
- typedef std::hash_map<AsciiString, AudioEventInfo*, rts::hash<AsciiString>, rts::equal_to<AsciiString> > AudioEventInfoHash;
- typedef AudioEventInfoHash::iterator AudioEventInfoHashIt;
- typedef UnsignedInt AudioHandle;
- // Defines
- enum
- {
- PROVIDER_ERROR = 0xFFFFFFFF
- };
- // Class AudioManager
- /**
- The life of audio.
- When audio is requested to play, it is done so in the following manner:
- 1) An AudioEventRTS is created on the stack.
- 2) Its guts are copied from elsewhere (for instance, a ThingTemplate, or MiscAudio).
- 3) It is added to TheAudio via TheAudio->addAudioEvent(...)
- The return value from addAudioEvent can be saved in case the sound needs to loop and/or be
- terminated at some point.
-
- To reomve a playing sound, the call TheAudio->removeAudioEvent(...) is used. This will search
- the list of currently playing audio for the specified handle, and kill the attached sound. It
- will play a decay sound, if one is specified.
- The important functions of TheAudio, are therefore
- GameAudio::addAudioEvent()
- GameAudio::removeAudioEvent()
- All other functions exist to support these two basic requirements.
- In addition to the fundamental requirements, the audio has a fairly complicated sound management
- scheme. If all units were always allowed to sound off, the sound engine would be overwhelmed and
- would sound awful. Therefore, when an audio event is requested, it goes through a series of
- checks to determine if it is near enough to the camera, if it should be heard based on shroud,
- local player affiliation, etc. (The entire list of checks is contained in shouldPlayLocally()).
-
- In addition, the world and unit audio are never allowed to exceed their footprint, as specified
- in the audio settings INI file. In order to accomodate this, the audio uses an audio cache. The
- audio cache will attempt to load a sample, assuming there is enough room. If there is not enough
- room, then it goes through and finds any samples that are lower priority, and kills them until
- enough room is present for the sample. If it cannot free enough room, nothing happens to the
- cache.
- Although the audio is multithreaded, most of the operations are performed such that the worst
- case scenario for thread miscommunication is that the main thread misses an event for one frame.
- One specific case of this is the status of playing audio. Because audio is playing
- asynchronously, it can complete at any time. When most audio completes, it sets a flag on the
- event noting that it has completed. During the next update (from the main thread), anything with
- that flag set is moved to the stopped list, and then is cleaned up. (Basically, the audio uses
- a push model for its multithreadedness, which doesn't require thread safety such as mutexes or
- semaphores).
- All in all, the best way to learn how the audio works is to track the lifetime of an event
- through the system. This will give a better understanding than all the documentation I could
- write.
- -jkmcd
- -December 2002
- */
- class AudioManager : public SubsystemInterface
- {
- public:
- AudioManager();
- virtual ~AudioManager();
- #if defined(_DEBUG) || defined(_INTERNAL)
- virtual void audioDebugDisplay(DebugDisplayInterface *dd, void *userData, FILE *fp = NULL ) = 0;
- #endif
- // From SubsystemInterface
- virtual void init();
- virtual void postProcessLoad();
- virtual void reset();
- virtual void update();
- // device dependent stop, pause and resume
- virtual void stopAudio( AudioAffect which ) = 0;
- virtual void pauseAudio( AudioAffect which ) = 0;
- virtual void resumeAudio( AudioAffect which ) = 0;
- virtual void pauseAmbient( Bool shouldPause ) = 0;
- // device dependent stops.
- virtual void stopAllAmbientsBy( Object* obj ) = 0;
- virtual void stopAllAmbientsBy( Drawable* draw ) = 0;
- // for focus issues
- virtual void loseFocus( void );
- virtual void regainFocus( void );
- // control for AudioEventsRTS
- virtual AudioHandle addAudioEvent( const AudioEventRTS *eventToAdd ); ///< Add an audio event (event must be declared in an INI file)
- virtual void removeAudioEvent( AudioHandle audioEvent ); ///< Remove an audio event, stop for instance.
- virtual void killAudioEventImmediately( AudioHandle audioEvent ) = 0;
- virtual Bool isValidAudioEvent( const AudioEventRTS *eventToCheck ) const; ///< validate that this piece of audio exists
- virtual Bool isValidAudioEvent( AudioEventRTS *eventToCheck ) const; ///< validate that this piece of audio exists
- // add tracks during INIification
- void addTrackName( const AsciiString& trackName );
- AsciiString nextTrackName(const AsciiString& currentTrack );
- AsciiString prevTrackName(const AsciiString& currentTrack );
-
- // changing music tracks
- virtual void nextMusicTrack( void ) = 0;
- virtual void prevMusicTrack( void ) = 0;
- virtual Bool isMusicPlaying( void ) const = 0;
- virtual Bool hasMusicTrackCompleted( const AsciiString& trackName, Int numberOfTimes ) const = 0;
- virtual AsciiString getMusicTrackName( void ) const = 0;
- virtual void setAudioEventEnabled( AsciiString eventToAffect, Bool enable );
- virtual void setAudioEventVolumeOverride( AsciiString eventToAffect, Real newVolume );
- virtual void removeAudioEvent( AsciiString eventToRemove );
- virtual void removeDisabledEvents();
- // Really meant for internal purposes only, but cannot be protected.
- virtual void getInfoForAudioEvent( const AudioEventRTS *eventToFindAndFill ) const; // Note: m_eventInfo is Mutable, and so this function will overwrite it if found
- ///< Return whether the current audio is playing or not.
- ///< NOTE NOTE NOTE !!DO NOT USE THIS IN FOR GAMELOGIC PURPOSES!! NOTE NOTE NOTE
- virtual Bool isCurrentlyPlaying( AudioHandle handle );
- // Device Dependent open and close functions
- virtual void openDevice( void ) = 0;
- virtual void closeDevice( void ) = 0;
- virtual void *getDevice( void ) = 0;
- // Debice Dependent notification functions
- virtual void notifyOfAudioCompletion( UnsignedInt audioCompleted, UnsignedInt flags ) = 0;
- // Device Dependent enumerate providers functions. It is okay for there to be only 1 provider (Miles provides a maximum of 64.
- virtual UnsignedInt getProviderCount( void ) const = 0;
- virtual AsciiString getProviderName( UnsignedInt providerNum ) const = 0;
- virtual UnsignedInt getProviderIndex( AsciiString providerName ) const = 0;
- virtual void selectProvider( UnsignedInt providerNdx ) = 0;
- virtual void unselectProvider( void ) = 0;
- virtual UnsignedInt getSelectedProvider( void ) const = 0;
- virtual void setSpeakerType( UnsignedInt speakerType ) = 0;
- virtual UnsignedInt getSpeakerType( void ) = 0;
- virtual UnsignedInt translateSpeakerTypeToUnsignedInt( const AsciiString& speakerType );
- virtual AsciiString translateUnsignedIntToSpeakerType( UnsignedInt speakerType );
- // Device Dependent calls to get the number of channels for each type of audio (2-D, 3-D, Streams)
- virtual UnsignedInt getNum2DSamples( void ) const = 0;
- virtual UnsignedInt getNum3DSamples( void ) const = 0;
- virtual UnsignedInt getNumStreams( void ) const = 0;
- // Device Dependent calls to determine sound prioritization info
- virtual Bool doesViolateLimit( AudioEventRTS *event ) const = 0;
- virtual Bool isPlayingLowerPriority( AudioEventRTS *event ) const = 0;
- virtual Bool isPlayingAlready( AudioEventRTS *event ) const = 0;
- virtual Bool isObjectPlayingVoice( UnsignedInt objID ) const = 0;
- virtual void adjustVolumeOfPlayingAudio(AsciiString eventName, Real newVolume) = 0;
- virtual void removePlayingAudio( AsciiString eventName ) = 0;
- virtual void removeAllDisabledAudio() = 0;
-
- // Is the audio device on? We can skip a lot of audio processing if not.
- virtual Bool isOn( AudioAffect whichToGet ) const;
- virtual void setOn( Bool turnOn, AudioAffect whichToAffect );
- // Set and get the device Volume
- virtual void setVolume( Real volume, AudioAffect whichToAffect );
- virtual Real getVolume( AudioAffect whichToGet );
-
- // To get a more 3-D feeling from the universe, we adjust the volume of the 3-D samples based
- // on zoom.
- virtual void set3DVolumeAdjustment( Real volumeAdjustment );
- virtual void *getHandleForBink( void ) = 0;
- virtual void releaseHandleForBink( void ) = 0;
- // this function will play an audio event rts by loading it into memory. It should not be used
- // by anything except for the load screens.
- virtual void friend_forcePlayAudioEventRTS(const AudioEventRTS* eventToPlay) = 0;
- // Update Listener position information
- virtual void setListenerPosition( const Coord3D *newListenerPos, const Coord3D *newListenerOrientation );
- virtual const Coord3D *getListenerPosition( void ) const;
- virtual AudioRequest *allocateAudioRequest( Bool useAudioEvent );
- virtual void releaseAudioRequest( AudioRequest *requestToRelease );
- virtual void appendAudioRequest( AudioRequest *m_request );
- virtual void processRequestList( void );
-
- virtual AudioEventInfo *newAudioEventInfo( AsciiString newEventName );
- virtual AudioEventInfo *findAudioEventInfo( AsciiString eventName ) const;
- const AudioSettings *getAudioSettings( void ) const;
- const MiscAudio *getMiscAudio( void ) const;
- // This function should only be called by AudioManager, MusicManager and SoundManager
- virtual void releaseAudioEventRTS( AudioEventRTS *eventToRelease );
- // For INI
- AudioSettings *friend_getAudioSettings( void );
- MiscAudio *friend_getMiscAudio( void );
- const FieldParse *getFieldParseTable( void ) const;
- const AudioEventRTS *getValidSilentAudioEvent() const { return m_silentAudioEvent; }
- virtual void setHardwareAccelerated(Bool accel) { m_hardwareAccel = accel; }
- virtual Bool getHardwareAccelerated() { return m_hardwareAccel; }
- virtual void setSpeakerSurround(Bool surround) { m_surroundSpeakers = surround; }
- virtual Bool getSpeakerSurround() { return m_surroundSpeakers; }
- virtual void refreshCachedVariables();
- virtual void setPreferredProvider(AsciiString providerNdx) = 0;
- virtual void setPreferredSpeaker(AsciiString speakerType) = 0;
- // For Scripting
- virtual Real getAudioLengthMS( const AudioEventRTS *event );
- virtual Real getFileLengthMS( AsciiString strToLoad ) const = 0;
- // For the file cache to know when to remove files.
- virtual void closeAnySamplesUsingFile( const void *fileToClose ) = 0;
-
- virtual Bool isMusicAlreadyLoaded(void) const;
- virtual Bool isMusicPlayingFromCD(void) const { return m_musicPlayingFromCD; }
- Bool getDisallowSpeech( void ) const { return m_disallowSpeech; }
- void setDisallowSpeech( Bool disallowSpeech ) { m_disallowSpeech = disallowSpeech; }
- // For Worldbuilder, to build lists from which to select
- virtual void findAllAudioEventsOfType( AudioType audioType, std::vector<AudioEventInfo*>& allEvents );
- Real getZoomVolume() const { return m_zoomVolume; }
- protected:
- // Is the currently selected provider actually HW accelerated?
- virtual Bool isCurrentProviderHardwareAccelerated();
-
- // Is the currently selected speaker type Surround sound?
- virtual Bool isCurrentSpeakerTypeSurroundSound();
- // Should this piece of audio play on the local machine?
- virtual Bool shouldPlayLocally(const AudioEventRTS *audioEvent);
- // Set the Listening position for the device
- virtual void setDeviceListenerPosition( void ) = 0;
- // For tracking purposes
- virtual AudioHandle allocateNewHandle( void );
- protected:
- AudioSettings *m_audioSettings;
- MiscAudio *m_miscAudio;
- MusicManager *m_music;
- SoundManager *m_sound;
- Coord3D m_listenerPosition;
- Coord3D m_listenerOrientation;
- std::list<AudioRequest*> m_audioRequests;
- std::vector<AsciiString> m_musicTracks;
- AudioEventInfoHash m_allAudioEventInfo;
- AudioHandle theAudioHandlePool;
- std::list<std::pair<AsciiString, Real> > m_adjustedVolumes;
- Real m_musicVolume;
- Real m_soundVolume;
- Real m_sound3DVolume;
- Real m_speechVolume;
- Real m_scriptMusicVolume;
- Real m_scriptSoundVolume;
- Real m_scriptSound3DVolume;
- Real m_scriptSpeechVolume;
-
- Real m_systemMusicVolume;
- Real m_systemSoundVolume;
- Real m_systemSound3DVolume;
- Real m_systemSpeechVolume;
- Real m_zoomVolume;
-
- AudioEventRTS *m_silentAudioEvent;
-
- enum { NUM_VOLUME_TYPES = 4 };
- Real *m_savedValues;
- // Group of 8
- Bool m_speechOn : 1;
- Bool m_soundOn : 1;
- Bool m_sound3DOn : 1;
- Bool m_musicOn : 1;
- Bool m_volumeHasChanged : 1;
- Bool m_hardwareAccel : 1;
- Bool m_surroundSpeakers : 1;
- Bool m_musicPlayingFromCD : 1;
- // Next 8
- Bool m_disallowSpeech : 1;
- };
- extern AudioManager *TheAudio;
- #endif // __COMMON_GAMEAUDIO_H_
|