3 * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/
5 * Copyright (C) 2001 Chuck Mason <cemason@users.sourceforge.net>
7 * Copyright (C) 2002 Florian Schulze <crow@icculus.org>
9 * Portions of this code are from the MPEG software simulation group
10 * idct implementation. This code will be replaced with a new
11 * implementation soon.
13 * This file is part of Jump'n'Bump.
15 * Jump'n'Bump is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * Jump'n'Bump is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 #include "SDL_mixer.h"
40 static Mix_Music *current_music = (Mix_Music *) NULL;
43 sfx_data sounds[NUM_SFX];
45 static int SAMPLECOUNT = 512;
47 #define MAX_CHANNELS 32
52 /* The channel step amount... */
54 /* ... and a 0.16 bit remainder of last step. */
55 unsigned int stepremainder;
56 unsigned int samplerate;
57 /* The channel data pointers, start and end. */
59 signed short* startdata;
60 signed short* enddata;
61 /* Hardware left and right channel volume lookup. */
66 channel_info_t channelinfo[MAX_CHANNELS];
68 /* Sample rate in samples/second */
69 int audio_rate = 44100;
70 int global_sfx_volume = 0;
72 // This function loops all active (internal) sound
73 // channels, retrieves a given number of samples
74 // from the raw sound data, modifies it according
75 // to the current (internal) channel parameters,
76 // mixes the per channel samples into the given
77 // mixing buffer, and clamping it to the allowed
80 // This function currently supports only 16bit.
83 static void stopchan(int i)
85 if (channelinfo[i].data) {
86 memset(&channelinfo[i], 0, sizeof(channel_info_t));
92 // This function adds a sound to the
93 // list of currently active sounds,
94 // which is maintained as a given number
95 // (eight, usually) of internal channels.
98 int addsfx(signed short *data, int len, int loop, int samplerate, int channel)
102 /* We will handle the new SFX. */
103 /* Set pointer to raw data. */
104 channelinfo[channel].data = data;
105 channelinfo[channel].startdata = data;
107 /* Set pointer to end of raw data. */
108 channelinfo[channel].enddata = channelinfo[channel].data + len - 1;
109 channelinfo[channel].samplerate = samplerate;
111 channelinfo[channel].loop = loop;
112 channelinfo[channel].stepremainder = 0;
118 static void updateSoundParams(int slot, int volume)
125 // MWM 2000-12-24: Calculates proportion of channel samplerate
126 // to global samplerate for mixing purposes.
127 // Patched to shift left *then* divide, to minimize roundoff errors
128 // as well as to use SAMPLERATE as defined above, not to assume 11025 Hz
130 channelinfo[slot].step = ((channelinfo[slot].samplerate<<16)/audio_rate);
135 /* Sanity check, clamp volume. */
146 channelinfo[slot].leftvol = leftvol;
147 channelinfo[slot].rightvol = rightvol;
151 void mix_sound(void *unused, Uint8 *stream, int len)
153 /* Mix current sound data. */
154 /* Data, from raw sound, for right and left. */
159 /* Pointers in audio stream, left, right, end. */
160 signed short* leftout;
161 signed short* rightout;
162 signed short* leftend;
163 /* Step in stream, left and right, thus two. */
166 /* Mixing channel index. */
169 /* Left and right channel */
170 /* are in audio stream, alternating. */
171 leftout = (signed short *)stream;
172 rightout = ((signed short *)stream)+1;
175 /* Determine end, for left channel only */
176 /* (right channel is implicit). */
177 leftend = leftout + (len/4)*step;
179 /* Mix sounds into the mixing buffer. */
180 /* Loop over step*SAMPLECOUNT, */
181 /* that is 512 values for two channels. */
182 while (leftout != leftend) {
183 /* Reset left/right value. */
185 dr = *rightout * 256;
187 /* Love thy L2 chache - made this a loop. */
188 /* Now more channels could be set at compile time */
189 /* as well. Thus loop those channels. */
190 for ( chan = 0; chan < MAX_CHANNELS; chan++ ) {
191 /* Check channel, if active. */
192 if (channelinfo[chan].data) {
193 /* Get the raw data from the channel. */
195 /* sample = *channelinfo[chan].data; */
196 /* linear filtering */
197 sample = (int)(((int)channelinfo[chan].data[0] * (int)(0x10000 - channelinfo[chan].stepremainder))
198 + ((int)channelinfo[chan].data[1] * (int)(channelinfo[chan].stepremainder))) >> 16;
200 /* Add left and right part */
201 /* for this channel (sound) */
202 /* to the current data. */
203 /* Adjust volume accordingly. */
204 dl += sample * (channelinfo[chan].leftvol * global_sfx_volume) / 128;
205 dr += sample * (channelinfo[chan].rightvol * global_sfx_volume) / 128;
206 /* Increment index ??? */
207 channelinfo[chan].stepremainder += channelinfo[chan].step;
208 /* MSB is next sample??? */
209 channelinfo[chan].data += channelinfo[chan].stepremainder >> 16;
210 /* Limit to LSB??? */
211 channelinfo[chan].stepremainder &= 0xffff;
213 /* Check whether we are done. */
214 if (channelinfo[chan].data >= channelinfo[chan].enddata) {
215 if (channelinfo[chan].loop) {
216 channelinfo[chan].data = channelinfo[chan].startdata;
224 /* Clamp to range. Left hardware channel. */
225 /* Has been char instead of short. */
226 /* if (dl > 127) *leftout = 127; */
227 /* else if (dl < -128) *leftout = -128; */
228 /* else *leftout = dl; */
235 else if (dl < SHRT_MIN)
238 *leftout = (signed short)dl;
240 /* Same for right hardware channel. */
242 *rightout = SHRT_MAX;
243 else if (dr < SHRT_MIN)
244 *rightout = SHRT_MIN;
246 *rightout = (signed short)dr;
248 /* Increment current pointers in stream */
258 Uint16 audio_format = AUDIO_S16;
259 int audio_channels = 2;
260 int audio_buffers = 4096;
264 if (main_info.no_sound)
267 audio_buffers = SAMPLECOUNT*audio_rate/11025;
269 memset(channelinfo, 0, sizeof(channelinfo));
270 memset(sounds, 0, sizeof(sounds));
273 if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers) < 0) {
274 fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
275 main_info.no_sound = 1;
279 Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels);
280 printf("Opened audio at %dHz %dbit %s, %d bytes audio buffer\n", audio_rate, (audio_format & 0xFF), (audio_channels > 1) ? "stereo" : "mono", audio_buffers);
282 Mix_SetMusicCMD(getenv("MUSIC_CMD"));
284 Mix_SetPostMix(mix_sound, NULL);
286 main_info.no_sound = 1;
295 if (main_info.no_sound)
301 Mix_FreeMusic(current_music);
302 current_music = NULL;
318 char dj_autodetect_sd(void)
323 char dj_set_stereo(char flag)
328 void dj_set_auto_mix(char flag)
332 unsigned short dj_set_mixing_freq(unsigned short freq)
337 void dj_set_dma_time(unsigned short time)
341 void dj_set_nosound(char flag)
353 char dj_set_num_sfx_channels(char num_channels)
358 void dj_set_sfx_volume(char volume)
360 if (main_info.no_sound)
364 global_sfx_volume = volume*2;
368 void dj_play_sfx(unsigned char sfx_num, unsigned short freq, char volume, char panning, unsigned short delay, char channel)
372 if (main_info.music_no_sound || main_info.no_sound)
376 for (slot=0; slot<MAX_CHANNELS; slot++)
377 if (channelinfo[slot].data==NULL)
379 if (slot>=MAX_CHANNELS)
385 addsfx((short *)sounds[sfx_num].buf, sounds[sfx_num].length, sounds[sfx_num].loop, freq, slot);
386 updateSoundParams(slot, volume*2);
390 char dj_get_sfx_settings(unsigned char sfx_num, sfx_data *data)
392 if (main_info.no_sound)
395 memcpy(data, &sounds[sfx_num], sizeof(sfx_data));
399 char dj_set_sfx_settings(unsigned char sfx_num, sfx_data *data)
401 if (main_info.no_sound)
404 memcpy(&sounds[sfx_num], data, sizeof(sfx_data));
408 void dj_set_sfx_channel_volume(char channel_num, char volume)
410 if (main_info.no_sound)
414 updateSoundParams(channel_num, volume*2);
418 void dj_stop_sfx_channel(char channel_num)
420 if (main_info.no_sound)
424 stopchan(channel_num);
428 char dj_load_sfx(unsigned char * file_handle, char *filename, int file_length, char sfx_type, unsigned char sfx_num)
432 unsigned short *dest;
434 if (main_info.no_sound)
437 sounds[sfx_num].buf = malloc(file_length);
439 memcpy(sounds[sfx_num].buf, file_handle, file_length);
441 sounds[sfx_num].length = file_length / 2;
442 src = sounds[sfx_num].buf;
443 dest = (unsigned short *)sounds[sfx_num].buf;
444 for (i=0; i<sounds[sfx_num].length; i++)
447 temp = src[0] + (src[1] << 8);
455 void dj_free_sfx(unsigned char sfx_num)
457 if (main_info.no_sound)
460 free(sounds[sfx_num].buf);
461 memset(&sounds[sfx_num], 0, sizeof(sfx_data));
466 char dj_ready_mod(char mod_num)
470 # if ((defined _MSC_VER) || (defined __MINGW32__))
471 char filename[] = "jnb.tmpmusic.mod";
473 char filename[] = "/tmp/jnb.tmpmusic.mod";
478 if (main_info.no_sound)
483 fp = dat_open("jump.mod", datfile_name, "rb");
484 len = dat_filelen("jump.mod", datfile_name);
487 fp = dat_open("bump.mod", datfile_name, "rb");
488 len = dat_filelen("bump.mod", datfile_name);
491 fp = dat_open("scores.mod", datfile_name, "rb");
492 len = dat_filelen("scores.mod", datfile_name);
498 if (Mix_PlayingMusic())
499 Mix_FadeOutMusic(1500);
502 Mix_FreeMusic(current_music);
503 current_music = NULL;
510 tmp = fopen(filename, "wb");
512 fwrite(fp, len, 1, tmp);
517 current_music = Mix_LoadMUS(filename);
519 if (current_music == NULL) {
520 fprintf(stderr, "Couldn't load music: %s\n", SDL_GetError());
529 char dj_start_mod(void)
532 if (main_info.no_sound)
536 Mix_PlayMusic(current_music, -1);
542 void dj_stop_mod(void)
545 if (main_info.no_sound)
552 void dj_set_mod_volume(char volume)
555 if (main_info.no_sound)
558 Mix_VolumeMusic(volume);
562 char dj_load_mod(unsigned char * file_handle, char *filename, char mod_num)
567 void dj_free_mod(char mod_num)