Skip to content

Commit b2c6d57

Browse files
committed
[LINUX][ZH] Add OpenAL AudioManager implementation
1 parent b2e0e24 commit b2c6d57

File tree

6 files changed

+3795
-12
lines changed

6 files changed

+3795
-12
lines changed

GeneralsMD/Code/GameEngineDevice/CMakeLists.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -253,14 +253,14 @@ if(RTS_BUILD_OPTION_OPENAL)
253253
find_package(OpenAL CONFIG REQUIRED)
254254

255255
if(OpenAL_FOUND)
256-
#target_sources(z_gameenginedevice PRIVATE
257-
# Include/OpenALDevice/OpenALAudioManager.h
256+
target_sources(z_gameenginedevice PRIVATE
257+
Include/OpenALDevice/OpenALAudioManager.h
258258
# Include/OpenALDevice/OpenALAudioStream.h
259-
# Source/OpenALDevice/OpenALAudioCache.h
260-
# Source/OpenALDevice/OpenALAudioCache.cpp
261-
# Source/OpenALDevice/OpenALAudioManager.cpp
259+
Source/OpenALDevice/OpenALAudioFileCache.h
260+
Source/OpenALDevice/OpenALAudioFileCache.cpp
261+
Source/OpenALDevice/OpenALAudioManager.cpp
262262
# Source/OpenALDevice/OpenALAudioStream.cpp
263-
#)
263+
)
264264

265265
target_link_libraries(z_gameenginedevice PRIVATE OpenAL::OpenAL)
266266
target_compile_definitions(z_gameenginedevice PUBLIC RTS_HAS_OPENAL)
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
/*
2+
** Command & Conquer Generals Zero Hour(tm)
3+
** Copyright 2025 TheSuperHackers
4+
**
5+
** This program is free software: you can redistribute it and/or modify
6+
** it under the terms of the GNU General Public License as published by
7+
** the Free Software Foundation, either version 3 of the License, or
8+
** (at your option) any later version.
9+
**
10+
** This program is distributed in the hope that it will be useful,
11+
** but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
** GNU General Public License for more details.
14+
**
15+
** You should have received a copy of the GNU General Public License
16+
** along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
// FILE: OpenALAudioManager.h //////////////////////////////////////////////////////////////////////////
20+
// OpenALAudioManager implementation
21+
// Author: Stephan Vedder, April 2025
22+
#pragma once
23+
#include "Common/AsciiString.h"
24+
#include "Common/GameAudio.h"
25+
#include <AL/al.h>
26+
#include <AL/alc.h>
27+
28+
class AudioEventRTS;
29+
30+
enum { MAXPROVIDERS = 64 };
31+
32+
#define AL_MAX_PLAYBACK_DEVICES 64
33+
34+
enum PlayingAudioType CPP_11(: Int)
35+
{
36+
PAT_Sample,
37+
PAT_3DSample,
38+
PAT_Stream,
39+
PAT_INVALID
40+
};
41+
42+
enum PlayingStatus CPP_11(: Int)
43+
{
44+
PS_Playing,
45+
PS_Stopped,
46+
PS_Paused
47+
};
48+
49+
enum PlayingWhich CPP_11(: Int)
50+
{
51+
PW_Attack,
52+
PW_Sound,
53+
PW_Decay,
54+
PW_INVALID
55+
};
56+
57+
struct ProviderInfo
58+
{
59+
AsciiString name;
60+
Bool m_isValid;
61+
};
62+
63+
class PlayingAudio;
64+
class OpenALAudioFileCache;
65+
class OpenALAudioStream;
66+
class OpenALAudioManager : public AudioManager
67+
{
68+
friend class OpenALAudioStream;
69+
friend class FFmpegVideoStream;
70+
friend class OpenALAudioFileCache;
71+
public:
72+
#if defined(_DEBUG) || defined(_INTERNAL)
73+
virtual void audioDebugDisplay(DebugDisplayInterface *dd, void *, FILE *fp = NULL );
74+
virtual AudioHandle addAudioEvent( const AudioEventRTS *eventToAdd ); ///< Add an audio event (event must be declared in an INI file)
75+
#endif
76+
77+
// from AudioDevice
78+
virtual void init();
79+
virtual void postProcessLoad();
80+
virtual void reset();
81+
virtual void update();
82+
83+
OpenALAudioManager();
84+
virtual ~OpenALAudioManager();
85+
86+
87+
virtual void nextMusicTrack( void );
88+
virtual void prevMusicTrack( void );
89+
virtual Bool isMusicPlaying( void ) const;
90+
virtual Bool hasMusicTrackCompleted( const AsciiString& trackName, Int numberOfTimes ) const;
91+
virtual AsciiString getMusicTrackName( void ) const;
92+
93+
virtual void openDevice( void );
94+
virtual void closeDevice( void );
95+
virtual void *getDevice( void ) { return m_alcDevice; }
96+
97+
virtual void stopAudio( AudioAffect which );
98+
virtual void pauseAudio( AudioAffect which );
99+
virtual void resumeAudio( AudioAffect which );
100+
virtual void pauseAmbient( Bool shouldPause );
101+
102+
virtual void killAudioEventImmediately( AudioHandle audioEvent );
103+
104+
///< Return whether the current audio is playing or not.
105+
///< NOTE NOTE NOTE !!DO NOT USE THIS IN FOR GAMELOGIC PURPOSES!! NOTE NOTE NOTE
106+
virtual Bool isCurrentlyPlaying( AudioHandle handle );
107+
108+
virtual void notifyOfAudioCompletion( ALuint source, UnsignedInt flags );
109+
virtual PlayingAudio *findPlayingAudioFrom( ALuint source, UnsignedInt flags );
110+
111+
virtual UnsignedInt getProviderCount( void ) const;
112+
virtual AsciiString getProviderName( UnsignedInt providerNum ) const;
113+
virtual UnsignedInt getProviderIndex( AsciiString providerName ) const;
114+
virtual void selectProvider( UnsignedInt providerNdx );
115+
virtual void unselectProvider( void );
116+
virtual UnsignedInt getSelectedProvider( void ) const;
117+
virtual void setSpeakerType( UnsignedInt speakerType );
118+
virtual UnsignedInt getSpeakerType( void );
119+
120+
virtual void *getHandleForBink( void );
121+
virtual void releaseHandleForBink( void );
122+
123+
virtual void friend_forcePlayAudioEventRTS(const AudioEventRTS* eventToPlay);
124+
125+
virtual UnsignedInt getNum2DSamples( void ) const;
126+
virtual UnsignedInt getNum3DSamples( void ) const;
127+
virtual UnsignedInt getNumStreams( void ) const;
128+
129+
virtual Bool doesViolateLimit( AudioEventRTS *event ) const;
130+
virtual Bool isPlayingLowerPriority( AudioEventRTS *event ) const;
131+
virtual Bool isPlayingAlready( AudioEventRTS *event ) const;
132+
virtual Bool isObjectPlayingVoice( UnsignedInt objID ) const;
133+
Bool killLowestPrioritySoundImmediately( AudioEventRTS *event );
134+
AudioEventRTS* findLowestPrioritySound( AudioEventRTS *event );
135+
136+
virtual void adjustVolumeOfPlayingAudio(AsciiString eventName, Real newVolume);
137+
138+
virtual void removePlayingAudio( AsciiString eventName );
139+
virtual void removeAllDisabledAudio();
140+
141+
virtual void processRequestList( void );
142+
virtual void processPlayingList( void );
143+
virtual void processFadingList( void );
144+
virtual void processStoppedList( void );
145+
146+
Bool shouldProcessRequestThisFrame( AudioRequest *req ) const;
147+
void adjustRequest( AudioRequest *req );
148+
Bool checkForSample( AudioRequest *req );
149+
150+
virtual void setHardwareAccelerated(Bool accel);
151+
virtual void setSpeakerSurround(Bool surround);
152+
153+
virtual void setPreferredProvider(AsciiString provider) { m_pref3DProvider = provider; }
154+
virtual void setPreferredSpeaker(AsciiString speakerType) { m_prefSpeaker = speakerType; }
155+
156+
virtual Real getFileLengthMS( AsciiString strToLoad ) const;
157+
158+
virtual void closeAnySamplesUsingFile( const void *fileToClose );
159+
160+
161+
virtual Bool has3DSensitiveStreamsPlaying( void ) const;
162+
163+
164+
protected:
165+
// 3-D functions
166+
virtual void setDeviceListenerPosition( void );
167+
const Coord3D *getCurrentPositionFromEvent( AudioEventRTS *event );
168+
Bool isOnScreen( const Coord3D *pos ) const;
169+
Real getEffectiveVolume(AudioEventRTS *event) const;
170+
171+
// Looping functions
172+
Bool startNextLoop( PlayingAudio *looping );
173+
174+
void playStream( AudioEventRTS *event, OpenALAudioStream* stream );
175+
// Returns the buffer handle representing audio data for attachment to the PlayingAudio structure
176+
ALuint playSample( AudioEventRTS *event, PlayingAudio *audio );
177+
ALuint playSample3D( AudioEventRTS *event, PlayingAudio * audio );
178+
179+
protected:
180+
void enumerateDevices( void );
181+
void createListener( void );
182+
void initDelayFilter( void );
183+
Bool isValidProvider( void );
184+
void initSamplePools( void );
185+
void processRequest( AudioRequest *req );
186+
187+
void playAudioEvent( AudioEventRTS *event );
188+
void stopAudioEvent( AudioHandle handle );
189+
void pauseAudioEvent( AudioHandle handle );
190+
191+
ALuint loadBufferForRead( AudioEventRTS *eventToLoadFrom );
192+
void closeBuffer( ALuint bufferToClose );
193+
194+
PlayingAudio *allocatePlayingAudio( void );
195+
void releaseOpenALHandles( PlayingAudio *release );
196+
void releasePlayingAudio( PlayingAudio *release );
197+
198+
void stopAllAudioImmediately( void );
199+
void freeAllOpenALHandles( void );
200+
201+
PlayingAudio *getFirst2DSample( AudioEventRTS *event );
202+
PlayingAudio *getFirst3DSample( AudioEventRTS *event );
203+
204+
void adjustPlayingVolume( PlayingAudio *audio );
205+
206+
void stopAllSpeech( void );
207+
static ALenum getALFormat( uint8_t channels, uint8_t bitsPerSample );
208+
protected:
209+
ProviderInfo m_provider3D[MAXPROVIDERS];
210+
UnsignedInt m_providerCount;
211+
UnsignedInt m_selectedProvider;
212+
UnsignedInt m_lastProvider;
213+
UnsignedInt m_selectedSpeakerType;
214+
215+
AsciiString m_pref3DProvider;
216+
AsciiString m_prefSpeaker;
217+
218+
// Currently Playing stuff. Useful if we have to preempt it.
219+
// This should rarely if ever happen, as we mirror this in Sounds, and attempt to
220+
// keep preemption from taking place here.
221+
std::list<PlayingAudio *> m_playingSounds;
222+
std::list<PlayingAudio *> m_playing3DSounds;
223+
std::list<PlayingAudio *> m_playingStreams;
224+
225+
// Currently fading stuff. At this point, we just want to let it finish fading, when it is
226+
// done it should be added to the completed list, then "freed" and the counts should be updated
227+
// on the next update
228+
std::list<PlayingAudio *> m_fadingAudio;
229+
230+
// Stuff that is done playing (either because it has finished or because it was killed)
231+
// This stuff should be cleaned up during the next update cycle. This includes updating counts
232+
// in the sound engine
233+
std::list<PlayingAudio *> m_stoppedAudio;
234+
235+
OpenALAudioFileCache *m_audioCache;
236+
UnsignedInt m_num2DSamples;
237+
UnsignedInt m_num3DSamples;
238+
UnsignedInt m_numStreams;
239+
240+
#if defined(_DEBUG) || defined(_INTERNAL)
241+
typedef std::set<AsciiString> SetAsciiString;
242+
typedef SetAsciiString::iterator SetAsciiStringIt;
243+
SetAsciiString m_allEventsLoaded;
244+
void dumpAllAssetsUsed();
245+
#endif
246+
247+
AsciiString m_alDevicesList[AL_MAX_PLAYBACK_DEVICES];
248+
int m_alMaxDevicesIndex;
249+
ALCdevice *m_alcDevice = nullptr;
250+
ALCcontext *m_alcContext = nullptr;
251+
OpenALAudioStream* m_binkAudio = nullptr;
252+
};
253+

0 commit comments

Comments
 (0)