Line data Source code
1 : /* Copyright (C) 2022 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "precompiled.h"
19 :
20 : #include "CSoundBase.h"
21 :
22 : #if CONFIG2_AUDIO
23 :
24 : #include "lib/timer.h"
25 : #include "soundmanager/SoundManager.h"
26 : #include "soundmanager/data/SoundData.h"
27 : #include "ps/CLogger.h"
28 :
29 0 : CSoundBase::CSoundBase()
30 : {
31 0 : ResetVars();
32 0 : }
33 :
34 0 : CSoundBase::~CSoundBase()
35 : {
36 0 : Stop();
37 0 : ReleaseOpenAL();
38 0 : }
39 :
40 0 : void CSoundBase::ReleaseOpenAL()
41 : {
42 0 : if (m_ALSource != 0)
43 : {
44 0 : AL_CHECK;
45 0 : alSourcei(m_ALSource, AL_BUFFER, 0L);
46 0 : AL_CHECK;
47 0 : ((CSoundManager*)g_SoundManager)->ReleaseALSource(m_ALSource);
48 0 : AL_CHECK;
49 0 : m_ALSource = 0;
50 : }
51 0 : if (m_SoundData != 0)
52 : {
53 0 : AL_CHECK;
54 0 : CSoundData::ReleaseSoundData(m_SoundData);
55 0 : AL_CHECK;
56 0 : m_SoundData = 0;
57 : }
58 0 : }
59 :
60 0 : void CSoundBase::Attach(CSoundData* itemData)
61 : {
62 : UNUSED2(itemData);
63 0 : }
64 :
65 0 : void CSoundBase::ResetVars()
66 : {
67 0 : m_ALSource = 0;
68 0 : m_SoundData = 0;
69 0 : m_LastPlay = false;
70 0 : m_Looping = false;
71 0 : m_StartFadeTime = 0;
72 0 : m_EndFadeTime = 0;
73 0 : m_StartVolume = 0;
74 0 : m_EndVolume = 0;
75 0 : m_ShouldBePlaying = false;
76 0 : m_IsPaused = false;
77 0 : ResetFade();
78 0 : }
79 :
80 0 : void CSoundBase::ResetFade()
81 : {
82 0 : m_StartFadeTime = 0;
83 0 : m_EndFadeTime = 0;
84 0 : m_StartVolume = 0;
85 0 : m_EndVolume = 0;
86 0 : m_PauseAfterFade = false;
87 0 : }
88 :
89 0 : bool CSoundBase::Finished()
90 : {
91 0 : return !m_ShouldBePlaying && !IsPlaying();
92 : }
93 :
94 0 : bool CSoundBase::InitOpenAL()
95 : {
96 0 : alGetError(); /* clear error */
97 0 : m_ALSource = ((CSoundManager*)g_SoundManager)->GetALSource( this );
98 :
99 0 : AL_CHECK;
100 :
101 0 : if ( m_ALSource )
102 : {
103 0 : alSourcef(m_ALSource,AL_PITCH,1.0f);
104 0 : AL_CHECK;
105 0 : alSourcef(m_ALSource,AL_GAIN,1.0f);
106 0 : AL_CHECK;
107 0 : alSourcei(m_ALSource,AL_LOOPING,AL_FALSE);
108 0 : AL_CHECK;
109 0 : return true;
110 : }
111 : else
112 : {
113 : // LOGERROR("Source not allocated by SoundManager\n", 0);
114 : }
115 0 : return false;
116 : }
117 :
118 0 : void CSoundBase::SetGain(ALfloat gain)
119 : {
120 0 : AL_CHECK;
121 :
122 0 : if ( m_ALSource )
123 : {
124 0 : std::lock_guard<std::mutex> lock(m_ItemMutex);
125 0 : alSourcef(m_ALSource, AL_GAIN, gain);
126 0 : AL_CHECK;
127 : }
128 0 : }
129 :
130 0 : void CSoundBase::SetRollOff(float rolls, float minDist, float maxDist)
131 : {
132 0 : if ( m_ALSource )
133 : {
134 0 : std::lock_guard<std::mutex> lock(m_ItemMutex);
135 0 : alSourcef(m_ALSource, AL_REFERENCE_DISTANCE, minDist);
136 0 : AL_CHECK;
137 0 : alSourcef(m_ALSource, AL_MAX_DISTANCE, maxDist);
138 0 : AL_CHECK;
139 0 : alSourcef(m_ALSource, AL_ROLLOFF_FACTOR, rolls);
140 0 : AL_CHECK;
141 : }
142 0 : }
143 :
144 0 : void CSoundBase::EnsurePlay()
145 : {
146 0 : if (m_ShouldBePlaying && !m_IsPaused && !IsPlaying())
147 0 : Play();
148 0 : }
149 :
150 0 : void CSoundBase::SetCone(ALfloat innerCone, ALfloat outerCone, ALfloat coneGain)
151 : {
152 0 : if ( m_ALSource )
153 : {
154 0 : std::lock_guard<std::mutex> lock(m_ItemMutex);
155 0 : AL_CHECK;
156 0 : alSourcef(m_ALSource, AL_CONE_INNER_ANGLE, innerCone);
157 0 : AL_CHECK;
158 0 : alSourcef(m_ALSource, AL_CONE_OUTER_ANGLE, outerCone);
159 0 : AL_CHECK;
160 0 : alSourcef(m_ALSource, AL_CONE_OUTER_GAIN, coneGain);
161 0 : AL_CHECK;
162 : }
163 0 : }
164 :
165 0 : void CSoundBase::SetPitch(ALfloat pitch)
166 : {
167 0 : if ( m_ALSource )
168 : {
169 0 : std::lock_guard<std::mutex> lock(m_ItemMutex);
170 0 : alSourcef(m_ALSource, AL_PITCH, pitch);
171 0 : AL_CHECK;
172 : }
173 0 : }
174 :
175 0 : void CSoundBase::SetDirection(const CVector3D& direction)
176 : {
177 0 : if ( m_ALSource )
178 : {
179 0 : std::lock_guard<std::mutex> lock(m_ItemMutex);
180 0 : alSourcefv(m_ALSource, AL_DIRECTION, direction.AsFloatArray().data());
181 0 : AL_CHECK;
182 : }
183 0 : }
184 :
185 :
186 0 : bool CSoundBase::IsPlaying()
187 : {
188 0 : if ( m_ALSource )
189 : {
190 0 : std::lock_guard<std::mutex> lock(m_ItemMutex);
191 : int proc_state;
192 0 : alGetSourcei(m_ALSource, AL_SOURCE_STATE, &proc_state);
193 0 : AL_CHECK;
194 :
195 0 : return (proc_state == AL_PLAYING);
196 : }
197 0 : return false;
198 : }
199 :
200 0 : void CSoundBase::SetLastPlay(bool last)
201 : {
202 0 : m_LastPlay = last;
203 0 : }
204 :
205 0 : bool CSoundBase::IdleTask()
206 : {
207 0 : return true;
208 : }
209 :
210 0 : void CSoundBase::SetLocation (const CVector3D& position)
211 : {
212 0 : if ( m_ALSource != 0 )
213 : {
214 0 : std::lock_guard<std::mutex> lock(m_ItemMutex);
215 0 : alSourcefv(m_ALSource,AL_POSITION, position.AsFloatArray().data());
216 0 : AL_CHECK;
217 : }
218 0 : }
219 :
220 0 : bool CSoundBase::HandleFade()
221 : {
222 0 : AL_CHECK;
223 0 : if (m_ALSource == 0)
224 0 : return true;
225 :
226 0 : if (m_StartFadeTime != 0)
227 : {
228 0 : double currTime = timer_Time();
229 0 : double pctDone = std::min(1.0, (currTime - m_StartFadeTime) / (m_EndFadeTime - m_StartFadeTime));
230 0 : pctDone = std::max(0.0, pctDone);
231 0 : ALfloat curGain = ((m_EndVolume - m_StartVolume) * pctDone) + m_StartVolume;
232 :
233 0 : if (curGain == 0)
234 : {
235 0 : if ( m_PauseAfterFade )
236 0 : Pause();
237 : else
238 0 : Stop();
239 : }
240 0 : else if (curGain == m_EndVolume)
241 : {
242 0 : if (m_ALSource != 0)
243 0 : alSourcef(m_ALSource, AL_GAIN, curGain);
244 0 : ResetFade();
245 : }
246 0 : else if (m_ALSource != 0)
247 0 : alSourcef(m_ALSource, AL_GAIN, curGain);
248 :
249 0 : AL_CHECK;
250 : }
251 0 : return true;
252 : }
253 :
254 0 : bool CSoundBase::IsFading()
255 : {
256 0 : return ((m_ALSource != 0) && (m_StartFadeTime != 0));
257 : }
258 :
259 :
260 0 : bool CSoundBase::GetLooping()
261 : {
262 0 : return m_Looping;
263 : }
264 :
265 0 : void CSoundBase::SetLooping(bool loops)
266 : {
267 0 : m_Looping = loops;
268 0 : if (m_ALSource != 0)
269 : {
270 0 : alSourcei(m_ALSource, AL_LOOPING, loops ? AL_TRUE : AL_FALSE);
271 0 : AL_CHECK;
272 : }
273 0 : }
274 :
275 0 : void CSoundBase::Play()
276 : {
277 0 : std::lock_guard<std::mutex> lock(m_ItemMutex);
278 :
279 0 : m_ShouldBePlaying = true;
280 0 : m_IsPaused = false;
281 0 : AL_CHECK;
282 0 : if (m_ALSource != 0)
283 : {
284 0 : alSourcePlay(m_ALSource);
285 0 : ALenum err = alGetError();
286 0 : if (err != AL_NO_ERROR)
287 : {
288 0 : if (err == AL_INVALID)
289 0 : ((CSoundManager*)g_SoundManager)->SetDistressThroughError();
290 : else
291 0 : ((CSoundManager*)g_SoundManager)->al_ReportError(err, __func__, __LINE__);
292 : }
293 : }
294 0 : }
295 :
296 0 : void CSoundBase::PlayAndDelete()
297 : {
298 0 : SetLastPlay(true);
299 0 : Play();
300 0 : }
301 :
302 0 : void CSoundBase::FadeAndPause(double fadeTime)
303 : {
304 0 : m_PauseAfterFade = true;
305 0 : FadeToIn(0, fadeTime);
306 0 : }
307 :
308 0 : void CSoundBase::FadeAndDelete(double fadeTime)
309 : {
310 0 : SetLastPlay(true);
311 0 : FadeToIn(0, fadeTime);
312 0 : }
313 :
314 0 : void CSoundBase::StopAndDelete()
315 : {
316 0 : SetLastPlay(true);
317 0 : Stop();
318 0 : }
319 :
320 0 : void CSoundBase::PlayLoop()
321 : {
322 0 : if (m_ALSource != 0)
323 : {
324 0 : SetLooping(true);
325 0 : Play();
326 0 : AL_CHECK;
327 : }
328 0 : }
329 :
330 0 : void CSoundBase::FadeToIn(ALfloat newVolume, double fadeDuration)
331 : {
332 0 : if (m_ALSource != 0)
333 : {
334 : ALenum proc_state;
335 0 : alGetSourcei(m_ALSource, AL_SOURCE_STATE, &proc_state);
336 0 : if (proc_state == AL_PLAYING)
337 : {
338 0 : m_StartFadeTime = timer_Time();
339 0 : m_EndFadeTime = m_StartFadeTime + fadeDuration;
340 0 : alGetSourcef(m_ALSource, AL_GAIN, &m_StartVolume);
341 0 : m_EndVolume = newVolume;
342 : }
343 0 : AL_CHECK;
344 : }
345 0 : }
346 :
347 0 : void CSoundBase::Stop()
348 : {
349 0 : m_ShouldBePlaying = false;
350 0 : if (m_ALSource != 0)
351 : {
352 0 : std::lock_guard<std::mutex> lock(m_ItemMutex);
353 :
354 0 : AL_CHECK;
355 0 : alSourcei(m_ALSource, AL_LOOPING, AL_FALSE);
356 0 : AL_CHECK;
357 0 : alSourceStop(m_ALSource);
358 0 : AL_CHECK;
359 : }
360 0 : }
361 :
362 0 : const Path CSoundBase::GetName()
363 : {
364 0 : if (m_SoundData)
365 0 : return m_SoundData->GetFileName();
366 :
367 0 : return Path();
368 : }
369 :
370 0 : void CSoundBase::Pause()
371 : {
372 0 : if (m_ALSource != 0)
373 : {
374 0 : m_IsPaused = true;
375 0 : alSourcePause(m_ALSource);
376 0 : AL_CHECK;
377 : }
378 0 : }
379 :
380 0 : void CSoundBase::Resume()
381 : {
382 0 : if (m_ALSource != 0)
383 : {
384 0 : alSourcePlay(m_ALSource);
385 0 : AL_CHECK;
386 : }
387 3 : }
388 :
389 : #endif // CONFIG2_AUDIO
390 :
|