Import from neverball-1.3.1.tar.gz
[neverball-archive.git] / ball / audio.c
blob625aec4752c1b5e946217f939c25da563a90d2b1
1 /*
2 * Copyright (C) 2003 Robert Kooima
4 * NEVERBALL is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
15 #include <SDL.h>
16 #include <SDL_mixer.h>
17 #include <string.h>
19 #include "config.h"
20 #include "audio.h"
22 /*---------------------------------------------------------------------------*/
24 static int audio_state = 0;
26 static Mix_Music *song;
27 static Mix_Chunk *buff[AUD_COUNT];
28 static int chan[AUD_COUNT];
30 #define CH_STATE 0
31 #define CH_MENU 1
32 #define CH_GRAB 2
33 #define CH_TICK 3
34 #define CH_BUMP 4
35 #define CH_VOICE 5
36 #define CH_COUNT 6
38 /*---------------------------------------------------------------------------*/
40 static void chunk_load(int i, const char *filename, int channel)
42 buff[i] = Mix_LoadWAV(config_data(filename));
43 chan[i] = channel;
46 static void chunk_free(int i)
48 if (buff[i])
50 Mix_FreeChunk(buff[i]);
51 buff[i] = NULL;
55 /*---------------------------------------------------------------------------*/
57 void audio_init(void)
59 int r = config_get_d(CONFIG_AUDIO_RATE);
60 int b = config_get_d(CONFIG_AUDIO_BUFF);
62 if (audio_state == 0)
64 if (Mix_OpenAudio(r, MIX_DEFAULT_FORMAT, 1, b) == 0)
66 chunk_load(AUD_MENU, "snd/menu.wav", CH_MENU);
67 chunk_load(AUD_START, "snd/select.ogg", CH_VOICE);
68 chunk_load(AUD_READY, "snd/ready.ogg", CH_VOICE);
69 chunk_load(AUD_SET, "snd/set.ogg", CH_VOICE);
70 chunk_load(AUD_GO, "snd/go.ogg", CH_VOICE);
71 chunk_load(AUD_BALL, "snd/ball.ogg", CH_GRAB);
72 chunk_load(AUD_BUMP, "snd/bump.ogg", CH_BUMP);
73 chunk_load(AUD_COIN, "snd/coin.wav", CH_GRAB);
74 chunk_load(AUD_TICK, "snd/tick.ogg", CH_TICK);
75 chunk_load(AUD_TOCK, "snd/tock.ogg", CH_TICK);
76 chunk_load(AUD_SWITCH, "snd/switch.wav", CH_STATE);
77 chunk_load(AUD_JUMP, "snd/jump.ogg", CH_STATE);
78 chunk_load(AUD_GOAL, "snd/goal.wav", CH_STATE);
79 chunk_load(AUD_SCORE, "snd/record.ogg", CH_VOICE);
80 chunk_load(AUD_FALL, "snd/fall.ogg", CH_VOICE);
81 chunk_load(AUD_TIME, "snd/time.ogg", CH_VOICE);
82 chunk_load(AUD_OVER, "snd/over.ogg", CH_VOICE);
84 audio_state = 1;
86 audio_volume(config_get_d(CONFIG_SOUND_VOLUME),
87 config_get_d(CONFIG_MUSIC_VOLUME));
89 else
91 fprintf(stderr, "Sound disabled\n");
92 audio_state = 0;
97 void audio_play(int i, float v)
99 if (audio_state == 1 && buff[i])
101 Mix_VolumeChunk(buff[i], (int) (v * MIX_MAX_VOLUME));
102 Mix_PlayChannel(chan[i], buff[i], 0);
106 void audio_free(void)
108 if (audio_state == 1)
110 Mix_CloseAudio();
112 chunk_free(AUD_OVER);
113 chunk_free(AUD_TIME);
114 chunk_free(AUD_FALL);
115 chunk_free(AUD_SCORE);
116 chunk_free(AUD_GOAL);
117 chunk_free(AUD_JUMP);
118 chunk_free(AUD_SWITCH);
119 chunk_free(AUD_TOCK);
120 chunk_free(AUD_TICK);
121 chunk_free(AUD_COIN);
122 chunk_free(AUD_BUMP);
123 chunk_free(AUD_BALL);
124 chunk_free(AUD_GO);
125 chunk_free(AUD_SET);
126 chunk_free(AUD_READY);
127 chunk_free(AUD_START);
128 chunk_free(AUD_MENU);
130 audio_state = 0;
134 /*---------------------------------------------------------------------------*/
136 static const char *current = NULL;
137 static const char *next = NULL;
139 static float fade_volume = 1.0f;
140 static float fade_rate = 0.0f;
142 void audio_music_play(const char *filename)
144 if (audio_state)
146 audio_music_stop();
148 if ((config_get_d(CONFIG_MUSIC_VOLUME) > 0) &&
149 (song = Mix_LoadMUS(config_data(filename))))
151 Mix_PlayMusic(song, -1);
152 current = filename;
157 void audio_music_queue(const char *filename)
159 if (audio_state)
161 if (!current || strcmp(filename, current) != 0)
163 Mix_VolumeMusic(0);
164 fade_volume = 0.0f;
166 audio_music_play(filename);
167 current = filename;
169 Mix_PauseMusic();
174 void audio_music_stop(void)
176 if (audio_state)
178 if (Mix_PlayingMusic())
179 Mix_HaltMusic();
181 if (song)
182 Mix_FreeMusic(song);
184 song = NULL;
188 /*---------------------------------------------------------------------------*/
190 * SDL_mixer already provides music fading. Unfortunately, it halts playback
191 * at the end of a fade. We need to be able to fade music back in from the
192 * point where it stopped. So, we reinvent this wheel.
195 void audio_timer(float dt)
197 if (audio_state)
199 if (fade_rate > 0.0f || fade_rate < 0.0f)
200 fade_volume += dt / fade_rate;
202 if (fade_volume < 0.0f)
204 fade_volume = 0.0f;
206 if (next == NULL)
208 fade_rate = 0.0f;
209 if (Mix_PlayingMusic())
210 Mix_PauseMusic();
212 else
214 fade_rate = -fade_rate;
215 audio_music_queue(next);
220 if (fade_volume > 1.0f)
222 fade_rate = 0.0f;
223 fade_volume = 1.0f;
226 if (Mix_PausedMusic() && fade_rate > 0.0f)
227 Mix_ResumeMusic();
229 if (Mix_PlayingMusic())
230 Mix_VolumeMusic(config_get_d(CONFIG_MUSIC_VOLUME) *
231 (int) (fade_volume * MIX_MAX_VOLUME) / 10);
235 void audio_music_fade_out(float t)
237 fade_rate = -t;
238 next = NULL;
241 void audio_music_fade_in(float t)
243 fade_rate = +t;
244 next = NULL;
247 void audio_music_fade_to(float t, const char *filename)
249 if (fade_volume > 0)
251 if (!current || strcmp(filename, current) != 0)
253 next = filename;
254 fade_rate = -t;
256 else fade_rate = t;
258 else
260 audio_music_queue(filename);
261 audio_music_fade_in(t);
265 void audio_volume(int s, int m)
267 if (audio_state)
269 Mix_Volume(-1, s * MIX_MAX_VOLUME / 10);
270 Mix_VolumeMusic(m * MIX_MAX_VOLUME / 10);
274 /*---------------------------------------------------------------------------*/