1 /*
2 Copyright (C) 2003 Parallel Realities
3 Copyright (C) 2011, 2012 Guus Sliepen
4 Copyright (C) 2015-2020 The Diligent Circle <diligentcircle@riseup.net>
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 3
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <math.h>
21
22 #ifndef NOSOUND
23 #include "SDL_mixer.h"
24 #endif
25
26 #include "defs.h"
27 #include "structs.h"
28
29 #include "game.h"
30 #include "engine.h"
31 #include "screen.h"
32
33 #ifndef NOSOUND
34 static Mix_Chunk *sound[SFX_MAX];
35 static Mix_Music *music = NULL;
36 #endif
37
audio_loadSounds()38 void audio_loadSounds()
39 {
40 #ifndef NOSOUND
41 sound[SFX_EXPLOSION] = Mix_LoadWAV("sound/explode.ogg");
42 sound[SFX_HIT] = Mix_LoadWAV("sound/explode2.ogg");
43 sound[SFX_DEATH] = Mix_LoadWAV("sound/maledeath.ogg");
44 sound[SFX_MISSILE] = Mix_LoadWAV("sound/missile.ogg");
45 sound[SFX_PLASMA] = Mix_LoadWAV("sound/plasma.ogg");
46 sound[SFX_CLOCK] = Mix_LoadWAV("sound/clock.ogg");
47 sound[SFX_FLY] = Mix_LoadWAV("sound/flyby.ogg");
48 sound[SFX_ENERGYRAY] = Mix_LoadWAV("sound/beamLaser.ogg");
49 sound[SFX_PICKUP] = Mix_LoadWAV("sound/item.ogg");
50 sound[SFX_SHIELDUP] = Mix_LoadWAV("sound/shield.ogg");
51 sound[SFX_CLOAK] = Mix_LoadWAV("sound/cloak.ogg");
52 sound[SFX_DEBRIS] = Mix_LoadWAV("sound/explode3.ogg");
53 sound[SFX_DEBRIS2] = Mix_LoadWAV("sound/explode4.ogg");
54 sound[SFX_LASER] = Mix_LoadWAV("sound/laser.ogg");
55 sound[SFX_PLASMA2] = Mix_LoadWAV("sound/plasma2.ogg");
56 sound[SFX_PLASMA3] = Mix_LoadWAV("sound/plasma3.ogg");
57 #endif
58 }
59
audio_playSound(int sid,float x,float y)60 void audio_playSound(int sid, float x, float y)
61 {
62 #ifndef NOSOUND
63 int channel = -1;
64 static int freechannel = 4;
65 static int channelVolume[4] = {0, 0, 0, 0};
66 int angle = atanf((x - (screen->w / 2)) / (screen->w / 2)) * 180 / M_PI;
67 int attenuation = fabsf(x - (screen->w / 2)) / (screen->w / 20);
68 float distance = sqrtf(powf(fabsf(x - (screen->w / 2)), 2) + powf(fabsf(y - (screen->h / 2)), 2));
69 int volume = MIX_MAX_VOLUME - (MIX_MAX_VOLUME * distance / (3 * screen->w));
70
71 if ((!engine.useSound) || (!engine.useAudio) || (volume <= 0))
72 return;
73
74 switch(sid)
75 {
76 case SFX_DEATH:
77 case SFX_CLOCK:
78 case SFX_FLY:
79 case SFX_SHIELDUP:
80 case SFX_PICKUP:
81 case SFX_CLOAK:
82 case SFX_PLASMA2:
83 case SFX_PLASMA3:
84 channel = -1;
85 break;
86 case SFX_PLASMA:
87 case SFX_LASER:
88 channel = 0;
89 break;
90 case SFX_ENERGYRAY:
91 case SFX_MISSILE:
92 channel = 1;
93 break;
94 case SFX_HIT:
95 channel = 2;
96 break;
97 case SFX_EXPLOSION:
98 case SFX_DEBRIS:
99 case SFX_DEBRIS2:
100 channel = 3;
101 break;
102 }
103
104 if (channel == -1)
105 {
106 channel = freechannel++;
107 if (freechannel >= 8)
108 freechannel = 4;
109 }
110 else
111 {
112 if (Mix_Playing(channel) && (volume <= MIX_MAX_VOLUME / 4)
113 && (channelVolume[channel] >= MIX_MAX_VOLUME * 3 / 4))
114 return;
115 else
116 channelVolume[channel] = volume;
117 }
118
119 angle %= 360;
120 if (angle < 0)
121 angle += 360;
122
123 if (attenuation > 255)
124 attenuation = 255;
125
126 Mix_SetPosition(channel, angle, attenuation);
127 Mix_Volume(channel, volume);
128 Mix_PlayChannel(channel, sound[sid], 0);
129 #endif
130 }
131
audio_haltMusic()132 void audio_haltMusic()
133 {
134 #ifndef NOSOUND
135 if (Mix_PlayingMusic())
136 {
137 Mix_ResumeMusic();
138 Mix_HaltMusic();
139 }
140
141 if (music != NULL)
142 {
143 Mix_FreeMusic(music);
144 music = NULL;
145 }
146 #endif
147 }
148
audio_pauseMusic()149 void audio_pauseMusic()
150 {
151 #ifndef NOSOUND
152 if (Mix_PlayingMusic() && !Mix_PausedMusic())
153 Mix_PauseMusic();
154 #endif
155 }
156
audio_resumeMusic()157 void audio_resumeMusic()
158 {
159 #ifndef NOSOUND
160 Mix_ResumeMusic();
161 #endif
162 }
163
audio_setMusicVolume(int volume)164 void audio_setMusicVolume(int volume)
165 {
166 #ifndef NOSOUND
167 if (engine.useMusic && engine.useAudio)
168 Mix_VolumeMusic(volume);
169 #endif
170 }
171
audio_playMusic(const char * filename,int loops)172 void audio_playMusic(const char *filename, int loops)
173 {
174 #ifndef NOSOUND
175 if (engine.useMusic && engine.useAudio)
176 {
177 audio_haltMusic();
178 music = Mix_LoadMUS(filename);
179 audio_setMusicVolume(100);
180 Mix_PlayMusic(music, loops);
181 }
182 #endif
183 }
184
audio_playRandomTrack()185 void audio_playRandomTrack()
186 {
187 #ifndef NOSOUND
188 if ((!engine.useMusic) || (!engine.useAudio))
189 return;
190
191 #ifdef OLD_MUSIC
192 int tracks = 0;
193 char track[][PATH_MAX] = {
194 "music/Frantic.mod", "music/Artificial.mod", "music/Lunatic.mod",
195 "music/ToxicFriend.mod", "music/DigitalInferno.mod",
196 "music/TempoTrance.mod", "music/IntoTheMachine.mod"
197 };
198
199 switch (game.system)
200 {
201 case SYSTEM_SPIRIT:
202 tracks = 3;
203 break;
204 case SYSTEM_EYANANTH:
205 tracks = 5;
206 break;
207 case SYSTEM_MORDOR:
208 case SYSTEM_SOL:
209 tracks = 7;
210 break;
211 default:
212 tracks = 3;
213 }
214 #else
215 int tracks = 4;
216 char track[][PATH_MAX] = {
217 "music/railjet_short.ogg", "music/space_dimensions.ogg",
218 "music/frozen_jam.ogg", "music/sound_and_silence.ogg"
219 };
220 #endif
221
222 switch (game.area)
223 {
224 #ifndef OLD_MUSIC
225 case MISN_START:
226 audio_playMusic("music/railjet_short.ogg", -1);
227 break;
228 #endif
229 case MISN_MOEBO:
230 case MISN_ELAMALE:
231 case MISN_ELLESH:
232 case MISN_EARTH:
233 #ifdef OLD_MUSIC
234 audio_playMusic("music/HardTranceDub.mod", -1);
235 #else
236 audio_playMusic("music/orbital_colossus.ogg", -1);
237 #endif
238 break;
239 case MISN_VENUS:
240 #ifdef OLD_MUSIC
241 audio_playMusic("music/LoopsAndTings.mod", -1);
242 #else
243 audio_playMusic("music/RE.ogg", -1);
244 #endif
245 break;
246 default:
247 audio_playMusic(track[rand() % tracks], -1);
248 }
249 #endif
250 }
251
audio_free()252 void audio_free()
253 {
254 #ifndef NOSOUND
255 for (int i = 0 ; i < SFX_MAX ; i++)
256 {
257 if (sound[i] != NULL)
258 {
259 Mix_FreeChunk(sound[i]);
260 sound[i] = NULL;
261 }
262 }
263
264 if (music != NULL)
265 {
266 Mix_FreeMusic(music);
267 music = NULL;
268 }
269 #endif
270 }
271