Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * sound.c
  3.  * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/
  4.  *
  5.  * Copyright (C) 2001 Chuck Mason <cemason@users.sourceforge.net>
  6.  *
  7.  * Copyright (C) 2002 Florian Schulze <crow@icculus.org>
  8.  *
  9.  * This file is part of Jump'n'Bump.
  10.  *
  11.  * Jump'n'Bump is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * Jump'n'Bump is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  24.  */
  25.  
  26. #include "globals.h"
  27. #include <limits.h>
  28. #ifndef _MSC_VER
  29. #include <unistd.h>
  30. #endif
  31. #include "SDL.h"
  32.  
  33. #ifndef NO_SDL_MIXER
  34. #include "SDL_mixer.h"
  35.  
  36. static Mix_Music *current_music = (Mix_Music *) NULL;
  37. #endif
  38.  
  39. sfx_data sounds[NUM_SFX];
  40.  
  41. static int SAMPLECOUNT = 512;
  42.  
  43. #define MAX_CHANNELS    32
  44.  
  45. typedef struct {
  46.         /* loop flag */
  47.         int loop;
  48.         /* The channel step amount... */
  49.         unsigned int step;
  50.         /* ... and a 0.16 bit remainder of last step. */
  51.         unsigned int stepremainder;
  52.         unsigned int samplerate;
  53.         /* The channel data pointers, start and end. */
  54.         signed short* data;
  55.         signed short* startdata;
  56.         signed short* enddata;
  57.         /* Hardware left and right channel volume lookup. */
  58.         int leftvol;
  59.         int rightvol;
  60. } channel_info_t;
  61.  
  62. channel_info_t channelinfo[MAX_CHANNELS];
  63.  
  64. /* Sample rate in samples/second */
  65. int audio_rate = 44100;
  66. int global_sfx_volume = 0;
  67. /*
  68. // This function loops all active (internal) sound
  69. //  channels, retrieves a given number of samples
  70. //  from the raw sound data, modifies it according
  71. //  to the current (internal) channel parameters,
  72. //  mixes the per channel samples into the given
  73. //  mixing buffer, and clamping it to the allowed
  74. //  range.
  75. //
  76. // This function currently supports only 16bit.
  77. */
  78.  
  79. static void stopchan(int i)
  80. {
  81.         if (channelinfo[i].data) {
  82.                 memset(&channelinfo[i], 0, sizeof(channel_info_t));
  83.         }
  84. }
  85.  
  86.  
  87. /*
  88. // This function adds a sound to the
  89. //  list of currently active sounds,
  90. //  which is maintained as a given number
  91. //  (eight, usually) of internal channels.
  92. // Returns a handle.
  93. */
  94. int addsfx(signed short *data, int len, int loop, int samplerate, int channel)
  95. {
  96.         stopchan(channel);
  97.  
  98.         /* We will handle the new SFX. */
  99.         /* Set pointer to raw data. */
  100.         channelinfo[channel].data = data;
  101.         channelinfo[channel].startdata = data;
  102.      
  103.         /* Set pointer to end of raw data. */
  104.         channelinfo[channel].enddata = channelinfo[channel].data + len - 1;
  105.         channelinfo[channel].samplerate = samplerate;
  106.  
  107.         channelinfo[channel].loop = loop;
  108.         channelinfo[channel].stepremainder = 0;
  109.  
  110.         return channel;
  111. }
  112.  
  113.  
  114. static void updateSoundParams(int slot, int volume)
  115. {
  116.         int rightvol;
  117.         int leftvol;
  118.  
  119.         /*
  120.         // Set stepping
  121.         // MWM 2000-12-24: Calculates proportion of channel samplerate
  122.         // to global samplerate for mixing purposes.
  123.         // Patched to shift left *then* divide, to minimize roundoff errors
  124.         // as well as to use SAMPLERATE as defined above, not to assume 11025 Hz
  125.         */
  126.         channelinfo[slot].step = ((channelinfo[slot].samplerate<<16)/audio_rate);
  127.  
  128.         leftvol = volume;
  129.         rightvol= volume;  
  130.  
  131.         /* Sanity check, clamp volume. */
  132.         if (rightvol < 0)
  133.                 rightvol = 0;
  134.         if (rightvol > 127)
  135.                 rightvol = 127;
  136.    
  137.         if (leftvol < 0)
  138.                 leftvol = 0;
  139.         if (leftvol > 127)
  140.                 leftvol = 127;
  141.    
  142.         channelinfo[slot].leftvol = leftvol;
  143.         channelinfo[slot].rightvol = rightvol;
  144. }
  145.  
  146.  
  147. void mix_sound(void *unused, Uint8 *stream, int len)
  148. {
  149.         /* Mix current sound data. */
  150.         /* Data, from raw sound, for right and left. */
  151.         register int sample;
  152.         register int    dl;
  153.         register int    dr;
  154.  
  155.         /* Pointers in audio stream, left, right, end. */
  156.         signed short*   leftout;
  157.         signed short*   rightout;
  158.         signed short*   leftend;
  159.         /* Step in stream, left and right, thus two. */
  160.         int       step;
  161.  
  162.         /* Mixing channel index. */
  163.         int       chan;
  164.  
  165.         /* Left and right channel */
  166.         /*  are in audio stream, alternating. */
  167.         leftout = (signed short *)stream;
  168.         rightout = ((signed short *)stream)+1;
  169.         step = 2;
  170.  
  171.         /* Determine end, for left channel only */
  172.         /*  (right channel is implicit). */
  173.         leftend = leftout + (len/4)*step;
  174.  
  175.         /* Mix sounds into the mixing buffer. */
  176.         /* Loop over step*SAMPLECOUNT, */
  177.         /*  that is 512 values for two channels. */
  178.         while (leftout != leftend) {
  179.                 /* Reset left/right value. */
  180.                 dl = *leftout * 256;
  181.                 dr = *rightout * 256;
  182.  
  183.                 /* Love thy L2 chache - made this a loop. */
  184.                 /* Now more channels could be set at compile time */
  185.                 /*  as well. Thus loop those  channels. */
  186.                 for ( chan = 0; chan < MAX_CHANNELS; chan++ ) {
  187.                         /* Check channel, if active. */
  188.                         if (channelinfo[chan].data) {
  189.                                 /* Get the raw data from the channel. */
  190.                                 /* no filtering */
  191.                                 /* sample = *channelinfo[chan].data; */
  192.                                 /* linear filtering */
  193.                                 sample = (int)(((int)channelinfo[chan].data[0] * (int)(0x10000 - channelinfo[chan].stepremainder))
  194.                                         + ((int)channelinfo[chan].data[1] * (int)(channelinfo[chan].stepremainder))) >> 16;
  195.  
  196.                                 /* Add left and right part */
  197.                                 /*  for this channel (sound) */
  198.                                 /*  to the current data. */
  199.                                 /* Adjust volume accordingly. */
  200.                                 dl += sample * (channelinfo[chan].leftvol * global_sfx_volume) / 128;
  201.                                 dr += sample * (channelinfo[chan].rightvol * global_sfx_volume) / 128;
  202.                                 /* Increment index ??? */
  203.                                 channelinfo[chan].stepremainder += channelinfo[chan].step;
  204.                                 /* MSB is next sample??? */
  205.                                 channelinfo[chan].data += channelinfo[chan].stepremainder >> 16;
  206.                                 /* Limit to LSB??? */
  207.                                 channelinfo[chan].stepremainder &= 0xffff;
  208.  
  209.                                 /* Check whether we are done. */
  210.                                 if (channelinfo[chan].data >= channelinfo[chan].enddata) {
  211.                                         if (channelinfo[chan].loop) {
  212.                                                 channelinfo[chan].data = channelinfo[chan].startdata;
  213.                                         } else {
  214.                                                 stopchan(chan);
  215.                                         }
  216.                                 }
  217.                         }
  218.                 }
  219.  
  220.                 /* Clamp to range. Left hardware channel. */
  221.                 /* Has been char instead of short. */
  222.                 /* if (dl > 127) *leftout = 127; */
  223.                 /* else if (dl < -128) *leftout = -128; */
  224.                 /* else *leftout = dl; */
  225.  
  226.                 dl = dl / 256;
  227.                 dr = dr / 256;
  228.  
  229.                 if (dl > SHRT_MAX)
  230.                         *leftout = SHRT_MAX;
  231.                 else if (dl < SHRT_MIN)
  232.                         *leftout = SHRT_MIN;
  233.                 else
  234.                         *leftout = (signed short)dl;
  235.  
  236.                 /* Same for right hardware channel. */
  237.                 if (dr > SHRT_MAX)
  238.                         *rightout = SHRT_MAX;
  239.                 else if (dr < SHRT_MIN)
  240.                         *rightout = SHRT_MIN;
  241.                 else
  242.                         *rightout = (signed short)dr;
  243.  
  244.                 /* Increment current pointers in stream */
  245.                 leftout += step;
  246.                 rightout += step;
  247.         }
  248. }
  249.  
  250. /* misc handling */
  251.  
  252. char dj_init(void)
  253. {
  254.         Uint16 audio_format = MIX_DEFAULT_FORMAT;
  255.         int audio_channels = 2;
  256.         int audio_buffers = 4096;
  257.  
  258.         open_screen();
  259.  
  260.         if (main_info.no_sound)
  261.                 return 0;
  262.  
  263.         audio_buffers = SAMPLECOUNT*audio_rate/11025;
  264.  
  265.         memset(channelinfo, 0, sizeof(channelinfo));
  266.         memset(sounds, 0, sizeof(sounds));
  267.  
  268. #ifndef NO_SDL_MIXER
  269.         if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers) < 0) {
  270.                 fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
  271.                 main_info.no_sound = 1;
  272.                 return 1;
  273.         }
  274.  
  275.         Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels);
  276.         printf("Opened audio at %dHz %dbit %s, %d bytes audio buffer\n", audio_rate, (audio_format & 0xFF), (audio_channels > 1) ? "stereo" : "mono", audio_buffers);
  277.  
  278.         Mix_SetMusicCMD(getenv("MUSIC_CMD"));
  279.  
  280.         Mix_SetPostMix(mix_sound, NULL);
  281. #else
  282.         main_info.no_sound = 1;
  283.         return 1;
  284. #endif
  285.  
  286.         return 0;
  287. }
  288.  
  289. void dj_deinit(void)
  290. {
  291.         if (main_info.no_sound)
  292.                 return;
  293.  
  294. #ifndef NO_SDL_MIXER
  295.         Mix_HaltMusic();
  296.         if (current_music)
  297.                 Mix_FreeMusic(current_music);
  298.         current_music = NULL;
  299.  
  300.         Mix_CloseAudio();
  301. #endif
  302.  
  303.         SDL_Quit();
  304. }
  305.  
  306. void dj_start(void)
  307. {
  308. }
  309.  
  310. void dj_stop(void)
  311. {
  312. }
  313.  
  314. char dj_autodetect_sd(void)
  315. {
  316.         return 0;
  317. }
  318.  
  319. char dj_set_stereo(char flag)
  320. {
  321.         return 0;
  322. }
  323.  
  324. void dj_set_auto_mix(char flag)
  325. {
  326. }
  327.  
  328. unsigned short dj_set_mixing_freq(unsigned short freq)
  329. {
  330.         return freq;
  331. }
  332.  
  333. void dj_set_dma_time(unsigned short time)
  334. {
  335. }
  336.  
  337. void dj_set_nosound(char flag)
  338. {
  339. }
  340.  
  341. /* mix handling */
  342.  
  343. void dj_mix(void)
  344. {
  345. }
  346.  
  347. /* sfx handling */
  348.  
  349. char dj_set_num_sfx_channels(char num_channels)
  350. {
  351.         return num_channels;
  352. }
  353.  
  354. void dj_set_sfx_volume(char volume)
  355. {
  356.         if (main_info.no_sound)
  357.                 return;
  358.  
  359.         SDL_LockAudio();
  360.         global_sfx_volume = volume*2;
  361.         SDL_UnlockAudio();
  362. }
  363.  
  364. void dj_play_sfx(unsigned char sfx_num, unsigned short freq, char volume, char panning, unsigned short delay, char channel)
  365. {
  366.         int slot;
  367.  
  368.         if (main_info.music_no_sound || main_info.no_sound)
  369.                 return;
  370.  
  371.         if (channel<0) {
  372.                 for (slot=0; slot<MAX_CHANNELS; slot++)
  373.                         if (channelinfo[slot].data==NULL)
  374.                                 break;
  375.                 if (slot>=MAX_CHANNELS)
  376.                         return;
  377.         } else
  378.                 slot = channel;
  379.  
  380.         SDL_LockAudio();
  381.         addsfx((short *)sounds[sfx_num].buf, sounds[sfx_num].length, sounds[sfx_num].loop, freq, slot);
  382.         updateSoundParams(slot, volume*2);
  383.         SDL_UnlockAudio();
  384. }
  385.  
  386. char dj_get_sfx_settings(unsigned char sfx_num, sfx_data *data)
  387. {
  388.         if (main_info.no_sound)
  389.                 return 0;
  390.  
  391.         memcpy(data, &sounds[sfx_num], sizeof(sfx_data));
  392.         return 0;
  393. }
  394.  
  395. char dj_set_sfx_settings(unsigned char sfx_num, sfx_data *data)
  396. {
  397.         if (main_info.no_sound)
  398.                 return 0;
  399.  
  400.         memcpy(&sounds[sfx_num], data, sizeof(sfx_data));
  401.         return 0;
  402. }
  403.  
  404. void dj_set_sfx_channel_volume(char channel_num, char volume)
  405. {
  406.         if (main_info.no_sound)
  407.                 return;
  408.  
  409.         SDL_LockAudio();
  410.         updateSoundParams(channel_num, volume*2);
  411.         SDL_UnlockAudio();
  412. }
  413.  
  414. void dj_stop_sfx_channel(char channel_num)
  415. {
  416.         if (main_info.no_sound)
  417.                 return;
  418.  
  419.         SDL_LockAudio();
  420.         stopchan(channel_num);
  421.         SDL_UnlockAudio();
  422. }
  423.  
  424. char dj_load_sfx(unsigned char * file_handle, char *filename, int file_length, char sfx_type, unsigned char sfx_num)
  425. {
  426.         unsigned int i;
  427.         unsigned char *src;
  428.         unsigned short *dest;
  429.        
  430.         if (main_info.no_sound)
  431.                 return 0;
  432.  
  433.         sounds[sfx_num].buf = malloc(file_length);
  434.  
  435.         memcpy(sounds[sfx_num].buf, file_handle, file_length);
  436.  
  437.         sounds[sfx_num].length = file_length / 2;
  438.         src = sounds[sfx_num].buf;
  439.         dest = (unsigned short *)sounds[sfx_num].buf;
  440.         for (i=0; i<sounds[sfx_num].length; i++)
  441.         {
  442.                 unsigned short temp;
  443.                 temp = src[0] + (src[1] << 8);
  444.                 *dest = temp;
  445.                 src += 2;
  446.                 dest++;
  447.         }
  448.         return 0;
  449. }
  450.  
  451. void dj_free_sfx(unsigned char sfx_num)
  452. {
  453.         if (main_info.no_sound)
  454.                 return;
  455.  
  456.         free(sounds[sfx_num].buf);
  457.         memset(&sounds[sfx_num], 0, sizeof(sfx_data));
  458. }
  459.  
  460. /* mod handling */
  461.  
  462. char dj_ready_mod(char mod_num)
  463. {
  464. #ifndef NO_SDL_MIXER
  465.         FILE *tmp;
  466. # if ((defined _MSC_VER) || (defined __MINGW32__))
  467.         char filename[] = "jnb.tmpmusic.mod";
  468. # else
  469.         char filename[] = "/tmp/jnb.tmpmusic.mod";
  470. # endif
  471.         unsigned char *fp;
  472.         int len;
  473.  
  474.         if (main_info.no_sound)
  475.                 return 0;
  476.  
  477.         switch (mod_num) {
  478.         case MOD_MENU:
  479.                 fp = dat_open("jump.mod");
  480.                 len = dat_filelen("jump.mod");
  481.                 break;
  482.         case MOD_GAME:
  483.                 fp = dat_open("bump.mod");
  484.                 len = dat_filelen("bump.mod");
  485.                 break;
  486.         case MOD_SCORES:
  487.                 fp = dat_open("scores.mod");
  488.                 len = dat_filelen("scores.mod");
  489.                 break;
  490.         default:
  491.                 fprintf(stderr, "bogus parameter to dj_ready_mod()\n");
  492.                 fp = NULL;
  493.                 len = 0;
  494.                 break;
  495.         }
  496.  
  497.         if (Mix_PlayingMusic())
  498.                 Mix_FadeOutMusic(1500);
  499.  
  500.         if (current_music) {
  501.                 Mix_FreeMusic(current_music);
  502.                 current_music = NULL;
  503.         }
  504.  
  505.         if (fp == NULL) {
  506.                 return 0;
  507.         }
  508.  
  509.         tmp = fopen(filename, "wb");
  510.         if (tmp) {
  511.         fwrite(fp, len, 1, tmp);
  512.                 fflush(tmp);
  513.                 fclose(tmp);
  514.         }
  515.  
  516.         current_music = Mix_LoadMUS(filename);
  517.         unlink(filename);
  518.         if (current_music == NULL) {
  519.                 fprintf(stderr, "Couldn't load music: %s\n", SDL_GetError());
  520.                 return 0;
  521.         }
  522.  
  523. #endif
  524.  
  525.         return 0;
  526. }
  527.  
  528. char dj_start_mod(void)
  529. {
  530. #ifndef NO_SDL_MIXER
  531.         if (main_info.no_sound)
  532.                 return 0;
  533.  
  534.         Mix_VolumeMusic(0);
  535.         Mix_PlayMusic(current_music, -1);
  536. #endif
  537.  
  538.         return 0;
  539. }
  540.  
  541. void dj_stop_mod(void)
  542. {
  543. #ifndef NO_SDL_MIXER
  544.         if (main_info.no_sound)
  545.                 return;
  546.  
  547.         Mix_HaltMusic();
  548. #endif
  549. }
  550.  
  551. void dj_set_mod_volume(char volume)
  552. {
  553. #ifndef NO_SDL_MIXER
  554.         if (main_info.no_sound)
  555.                 return;
  556.  
  557.         Mix_VolumeMusic(volume);
  558. #endif
  559. }
  560.  
  561. char dj_load_mod(unsigned char * file_handle, char *filename, char mod_num)
  562. {
  563.         return 0;
  564. }
  565.  
  566. void dj_free_mod(char mod_num)
  567. {
  568. }
  569.