Removed all bonus ball texture-related code.
[neverball] / share / audio.c
1 /*
2  * Copyright (C) 2003 Robert Kooima
3  *
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.
8  *
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.
13  */
14
15 #include <SDL.h>
16 #include <SDL_mixer.h>
17 #include <string.h>
18
19 #include "config.h"
20 #include "audio.h"
21
22 /*---------------------------------------------------------------------------*/
23
24 static int audio_state = 0;
25
26 static char       name[MAXSND][MAXSTR];
27 static int        chan[MAXSND];
28 static Mix_Chunk *buff[MAXSND];
29 static Mix_Music *song;
30
31 static char  curr_bgm[MAXSTR];
32 static char  next_bgm[MAXSTR];
33
34 static float fade_volume = 1.0f;
35 static float fade_rate   = 0.0f;
36
37 /*---------------------------------------------------------------------------*/
38
39 void audio_init(void)
40 {
41     int r = config_get_d(CONFIG_AUDIO_RATE);
42     int b = config_get_d(CONFIG_AUDIO_BUFF);
43     int i;
44
45     memset(curr_bgm, 0, MAXSTR);
46     memset(next_bgm, 0, MAXSTR);
47
48     if (audio_state == 0)
49     {
50         if (Mix_OpenAudio(r, MIX_DEFAULT_FORMAT, 2, b) == 0)
51         {
52             for (i = 0; i < MAXSND; i++)
53                 if (chan[i])
54                     buff[i] = Mix_LoadWAV(config_data(name[i]));
55
56             audio_state = 1;
57
58             audio_volume(config_get_d(CONFIG_SOUND_VOLUME),
59                          config_get_d(CONFIG_MUSIC_VOLUME));
60         }
61         else
62         {
63             fprintf(stderr, _("Sound disabled\n"));
64             audio_state = 0;
65         }
66     }
67 }
68
69 void audio_free(void)
70 {
71     int i;
72
73     if (audio_state == 1)
74     {
75         for (i = 0; i < MAXSND; i++)
76             if (buff[i])
77             {
78                 Mix_FreeChunk(buff[i]);
79
80                 buff[i] = NULL;
81             }
82
83         Mix_CloseAudio();
84         audio_state = 0;
85     }
86 }
87
88 void audio_bind(int i, int c, const char *filename)
89 {
90     strncpy(name[i], filename, MAXSTR);
91     chan[i] = c;
92 }
93
94 void audio_play(int i, float v)
95 {
96     if (audio_state == 1 && buff[i])
97     {
98         Mix_VolumeChunk(buff[i], (int) (v * MIX_MAX_VOLUME));
99         Mix_PlayChannel(chan[i], buff[i], 0);
100     }
101 }
102
103 /*---------------------------------------------------------------------------*/
104
105 void audio_music_play(const char *filename)
106 {
107     if (audio_state)
108     {
109         audio_music_stop();
110
111         if ((config_get_d(CONFIG_MUSIC_VOLUME) > 0) &&
112             (song = Mix_LoadMUS(config_data(filename))))
113         {
114             Mix_PlayMusic(song, -1);
115             strcpy(curr_bgm, filename);
116         }
117     }
118 }
119
120 void audio_music_queue(const char *filename)
121 {
122     if (audio_state)
123     {
124         if (strlen(curr_bgm) == 0 || strcmp(filename, curr_bgm) != 0)
125         {
126             Mix_VolumeMusic(0);
127             fade_volume = 0.0f;
128
129             audio_music_play(filename);
130             strcpy(curr_bgm, filename);
131
132             Mix_PauseMusic();
133         }
134     }
135 }
136
137 void audio_music_stop(void)
138 {
139     if (audio_state)
140     {
141         if (Mix_PlayingMusic())
142             Mix_HaltMusic();
143
144         if (song)
145             Mix_FreeMusic(song);
146
147         song = NULL;
148     }
149 }
150
151 /*---------------------------------------------------------------------------*/
152 /*
153  * SDL_mixer already provides music fading.  Unfortunately, it halts playback
154  * at the end of a fade.  We need to be able to fade music back in from the
155  * point where it stopped.  So, we reinvent this wheel.
156  */
157
158 void audio_timer(float dt)
159 {
160     if (audio_state)
161     {
162         if (fade_rate > 0.0f || fade_rate < 0.0f)
163             fade_volume += dt / fade_rate;
164
165         if (fade_volume < 0.0f)
166         {
167             fade_volume = 0.0f;
168
169             if (strlen(next_bgm) == 0)
170             {
171                 fade_rate = 0.0f;
172                 if (Mix_PlayingMusic())
173                     Mix_PauseMusic();
174             }
175             else
176             {
177                 fade_rate = -fade_rate;
178                 audio_music_queue(next_bgm);
179             }
180         }
181
182         if (fade_volume > 1.0f)
183         {
184             fade_rate   = 0.0f;
185             fade_volume = 1.0f;
186         }
187
188         if (Mix_PausedMusic() && fade_rate > 0.0f)
189             Mix_ResumeMusic();
190
191         if (Mix_PlayingMusic())
192             Mix_VolumeMusic(config_get_d(CONFIG_MUSIC_VOLUME) *
193                             (int) (fade_volume * MIX_MAX_VOLUME) / 10);
194     }
195 }
196
197 void audio_music_fade_out(float t)
198 {
199     fade_rate = -t;
200     strcpy(next_bgm, "");
201 }
202
203 void audio_music_fade_in(float t)
204 {
205     fade_rate = +t;
206     strcpy(next_bgm, "");
207 }
208
209 void audio_music_fade_to(float t, const char *filename)
210 {
211     if (fade_volume > 0)
212     {
213         if (strlen(curr_bgm) == 0 || strcmp(filename, curr_bgm) != 0)
214         {
215             strcpy(next_bgm, filename);
216             fade_rate = -t;
217         }
218         else fade_rate = t;
219     }
220     else
221     {
222         audio_music_queue(filename);
223         audio_music_fade_in(t);
224     }
225 }
226
227 void audio_volume(int s, int m)
228 {
229     if (audio_state)
230     {
231         Mix_Volume(-1, s * MIX_MAX_VOLUME / 10);
232         Mix_VolumeMusic(m * MIX_MAX_VOLUME / 10);
233     }
234 }
235
236 /*---------------------------------------------------------------------------*/