1 // BlinkenSisters - Hunt for the Lost Pixels
2 //     Bringing back the fun of the 80s
3 //
4 // (C) 2005-07 Rene Schickbauer, Wolfgang Dautermann
5 //
6 // See License.txt for licensing information
7 //
8 
9 
10 #include <stdlib.h>
11 #include "globals.h"
12 #include "sound.h"
13 #include "errorhandler.h"
14 
15 
16 int audio_rate = 44100;
17 Uint16 audio_format = AUDIO_S16; /* 16-bit stereo */
18 int audio_channels = 2;
19 Uint32 audio_buffers = AUDIOBUFFERSIZE;
20 extern bool soundOK ;
21 bool soundInitOK = false;
22 char bgMusicFile[1000];
23 
24 #ifndef DISABLE_SOUND
25 Mix_Music *levelMusic = NULL;
26 Mix_Chunk *sound_fx[FX_MAX_PREDEF + MAX_FX_SAMPLES];
27 Mix_Chunk *sound_fx_video = 0;
28 Uint32 sndfxcnt = 0;
29 #endif
30 bool playOnceFinished = false;
31 bool onlyPlayOnce = true;
32 Uint32 soundSimTick = 0; // Simulated sound length if we have no sound
33 
initSound()34 void initSound()
35 {
36 	if (soundOK==false) { return ; } // Sound support not compiled or disabled by command line switch -s
37 #ifndef DISABLE_SOUND
38 	/* This is where we open up our audio device.  Mix_OpenAudio takes
39 	as its parameters the audio format we'd /like/ to have. */
40 	if(Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers)) {
41 		printf("Unable to open audio!\n");
42 		soundInitOK = false;
43 		return;
44 	} else {
45 		soundInitOK = true;
46 		Mix_HookMusicFinished(soundMusicFinished);
47 	}
48 
49 	/* If we actually care about what we got, we can ask here.  In this
50 	program we don't... yet */
51 	Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels);
52 	sound_fx[FX_COLLECT_PIXEL] = Mix_LoadWAV(configGetPath("fx_collect_pixel.ogg"));
53 	sound_fx[FX_KILL_MONSTER] = Mix_LoadWAV(configGetPath("fx_kill_monster.ogg"));
54 	sound_fx[FX_KILL_PLAYER] = Mix_LoadWAV(configGetPath("fx_killed.ogg"));
55 	sound_fx[FX_LEVEL_FINISHED] = Mix_LoadWAV(configGetPath("fx_level_finished.ogg"));
56 	sound_fx[FX_MENU] = Mix_LoadWAV(configGetPath("fx_menu.ogg"));
57 	sound_fx[FX_RESPAWNPOINT] = Mix_LoadWAV(configGetPath("fx_respawnpoint.ogg"));
58 #endif // DISABLE_SOUND
59 }
60 
deInitSound()61 void deInitSound()
62 {
63 	printf("De-init sound\n");
64 	if(!soundOK || !soundInitOK) {
65 		return;
66 	}
67 #ifndef DISABLE_SOUND
68 	soundStopMusic();
69 	levelMusic = NULL;
70 
71 	Mix_FreeChunk(sound_fx[FX_COLLECT_PIXEL]);
72 	Mix_FreeChunk(sound_fx[FX_KILL_MONSTER]);
73 	Mix_FreeChunk(sound_fx[FX_KILL_PLAYER]);
74 	Mix_FreeChunk(sound_fx[FX_LEVEL_FINISHED]);
75 	Mix_FreeChunk(sound_fx[FX_MENU]);
76 
77 	deInitSoundFXLua();
78 
79 	Mix_CloseAudio();
80 	soundInitOK = false;
81 #endif // DISABLE_SOUND
82 }
83 
84 
soundPlayFX(Uint32 fx)85 void soundPlayFX(Uint32 fx) {
86 	if(!soundOK || !soundInitOK) {
87 		return;
88 	}
89 #ifndef DISABLE_SOUND
90 	Mix_PlayChannel(-1, sound_fx[fx], 0);
91 #endif // DISABLE_SOUND
92 }
93 
94 
soundStartMusic(const char * fname,bool playOnce)95 void soundStartMusic(const char* fname, bool playOnce)
96 {
97 	// There are some things that ALWAYS needs to be done, no matter if sound actually works
98 	soundStopMusic(); // Has his own checks and simulated to-do list
99 	playOnceFinished = false;
100 	onlyPlayOnce = playOnce;
101 
102 	if(!soundOK || !soundInitOK) {
103 		soundSimTick = SDL_GetTicks() + 45000; // Simulated sound plays 45 seconds
104 		return;
105 	}
106 #ifndef DISABLE_SOUND
107 
108 
109 	sprintf(bgMusicFile, "%s", fname); // Remember original Filename
110 
111 	char fullfname[MAX_FNAME_LENGTH];
112 	sprintf(fullfname, "%s", configGetPath(fname));
113 	levelMusic = Mix_LoadMUS(fullfname);
114 	if(!levelMusic) {
115 		DIE(ERROR_SOUND_READ, fullfname);
116 	}
117 	/*
118 	if(!playOnce) {
119 		Mix_PlayMusic(levelMusic, -1);
120 	} else {
121 		Mix_PlayMusic(levelMusic, 1);
122 	}
123 	 We do NOT use automated repeat - we do it ourself to try and fix a bug
124 	 */
125 	Mix_PlayMusic(levelMusic, 1);
126 
127 
128 	Mix_VolumeMusic(MIX_MAX_VOLUME / 2);
129 #endif // DISABLE_SOUND
130 }
131 
soundStopMusic()132 void soundStopMusic()
133 {
134 	// There are some things that ALWAYS needs to be done, no matter if sound actually works
135 	playOnceFinished = false;
136 	onlyPlayOnce = false;
137 
138 	if(!soundOK || !soundInitOK) {
139 		soundSimTick = 0;
140 		return;
141 	}
142 #ifndef DISABLE_SOUND
143 	Mix_HaltMusic();
144 	if(levelMusic) {
145 		Mix_FreeMusic(levelMusic);
146 		levelMusic = 0;
147 	}
148 
149 #endif // DISABLE_SOUND
150 }
151 
addSoundFXLua(char * fname)152 Uint32 addSoundFXLua(char* fname) {
153 	if(!soundOK || !soundInitOK) {
154 		return 0;
155 	}
156 #ifndef DISABLE_SOUND
157 	char fullfname[MAX_FNAME_LENGTH];
158 	sprintf(fullfname, "%s", configGetPath(fname));
159 
160 	if(sndfxcnt >= MAX_FX_SAMPLES) {
161 		DIE(ERROR_BOUNDARY, "too many FX samples");
162 	}
163 	sound_fx[sndfxcnt + FX_MAX_PREDEF] = Mix_LoadWAV(fullfname);
164 	if(!sound_fx[sndfxcnt + FX_MAX_PREDEF]) {
165 		DIE(ERROR_SOUND_READ, fname);
166 	}
167 	sndfxcnt++;
168 	return (sndfxcnt-1);
169 #else // DISABLE_SOUND
170 	return 0 ;
171 #endif // DISABLE_SOUND
172 }
173 
soundPlayFXLua(Uint32 fx)174 void soundPlayFXLua(Uint32 fx) {
175 	if(!soundOK || !soundInitOK) {
176 		return;
177 	}
178 #ifndef DISABLE_SOUND
179 	if(fx >= sndfxcnt) {
180 		DIE(ERROR_INDEX_INVALID, "Unknown sample");
181 	}
182 	soundPlayFX(fx + FX_MAX_PREDEF);
183 #endif // DISABLE_SOUND
184 }
185 
initSoundFXLua()186 void initSoundFXLua() {
187 	if(!soundOK || !soundInitOK) {
188 		return;
189 	}
190 #ifndef DISABLE_SOUND
191 	sndfxcnt = 0;
192 #endif // DISABLE_SOUND
193 }
194 
deInitSoundFXLua()195 void deInitSoundFXLua() {
196 	if(!soundOK || !soundInitOK) {
197 		return;
198 	}
199 #ifndef DISABLE_SOUND
200 	for(Uint32 i = 0; i < sndfxcnt; i++) {
201 		Mix_FreeChunk(sound_fx[i + FX_MAX_PREDEF]);
202 	}
203 	sndfxcnt = 0;
204 #endif // DISABLE_SOUND
205 }
206 
soundStartVideoFX(SDL_RWops * src)207 void soundStartVideoFX(SDL_RWops* src) {
208 	if(!soundOK || !soundInitOK) {
209 		return;
210 	}
211 #ifndef DISABLE_SOUND
212 	sound_fx_video=Mix_LoadWAV_RW(src, 0);
213 	if(!sound_fx_video) {
214 		printf("Couldn't start video sound\n");
215 		return;
216 	}
217 	Mix_PlayChannel(-1, sound_fx_video, 0);
218 #endif // DISABLE_SOUND
219 }
220 
soundStopVideoFX()221 void soundStopVideoFX() {
222 	if(!soundOK || !soundInitOK) {
223 		return;
224 	}
225 #ifndef DISABLE_SOUND
226 	if(!sound_fx_video) {
227 		return;
228 	}
229 	Mix_FreeChunk(sound_fx_video);
230 	sound_fx_video = 0;
231 #endif // DISABLE_SOUND
232 }
233 
soundMusicFinished()234 void soundMusicFinished() {
235 	if(onlyPlayOnce) {
236 		soundStopMusic();
237 		playOnceFinished = true;
238 	} else {
239 		// soundStartMusic auto-unloads current file, so we don't have to call
240 		// it explicitely
241 		soundStartMusic(bgMusicFile, false);
242 	}
243 }
244 
soundPlayOnceFinished()245 bool soundPlayOnceFinished() {
246 	if(!soundOK || !soundInitOK) {
247 		// Simulate playonce
248 		if(soundSimTick != 0 && SDL_GetTicks() > soundSimTick) {
249 			if(onlyPlayOnce) {
250 				playOnceFinished = true;
251 			}
252 		}
253 	}
254 	return playOnceFinished;
255 }
256 
257