/*
 *    SPEED - by Shawn Hargreaves, 1999
 *
 *    This file is quite possibly the most entirely pointless piece of
 *    code that I have ever written. I didn't want to include any external
 *    data, you see, so everything has to work entirely from C source,
 *    which means generating all the sounds from code. I don't know why
 *    I'm bothering, because this probably won't sound too good :-)
 */

#include <math.h>
#include <allegro.h>

#include "speed.h"



/* generated sample waveforms */
static SAMPLE *zap;
static SAMPLE *bang;
static SAMPLE *bigbang;
static SAMPLE *ping;



#define RAND   (((float)(rand() & 255) / 255.0) - 0.5)



/* initialises the sound system */
void init_sound()
{
   float f, osc1, osc2, freq1, freq2, vol, val;
   char *p;
   int i;

   /* zap (firing sound) consists of multiple falling saw waves */
   zap = create_sample(8, FALSE, 22050, 8192);

   p = (char *)zap->data;

   osc1 = 0;
   freq1 = 0.02;

   osc2 = 0;
   freq2 = 0.025;

   for (i=0; i<zap->len; i++) {
      vol = (float)(zap->len - i) / (float)zap->len * 127;

      *p = 128 + (fmod(osc1, 1) + fmod(osc2, 1) - 1) * vol;

      osc1 += freq1;
      freq1 -= 0.000001;

      osc2 += freq2;
      freq2 -= 0.00000125;

      p++;
   }

   /* bang (explosion) consists of filtered noise */
   bang = create_sample(8, FALSE, 22050, 8192);

   p = (char *)bang->data;

   val = 0;

   for (i=0; i<bang->len; i++) {
      vol = (float)(bang->len - i) / (float)bang->len * 255;
      val = (val * 0.75) + (RAND * 0.25);
      *p = 128 + val * vol;
      p++;
   }

   /* big bang (explosion) consists of noise plus rumble */
   bigbang = create_sample(8, FALSE, 11025, 24576);

   p = (char *)bigbang->data;

   val = 0;

   osc1 = 0;
   osc2 = 0;

   for (i=0; i<bigbang->len; i++) {
      vol = (float)(bigbang->len - i) / (float)bigbang->len * 128;

      f = 0.5 + ((float)i / (float)bigbang->len * 0.4);
      val = (val * f) + (RAND * (1-f));

      *p = 128 + (val + (sin(osc1) + sin(osc2)) / 4) * vol;

      osc1 += 0.03;
      osc2 += 0.04;

      p++;
   }

   /* ping consists of two sine waves */
   ping = create_sample(8, FALSE, 22050, 8192);

   p = (char *)ping->data;

   osc1 = 0;
   osc2 = 0;

   for (i=0; i<ping->len; i++) {
      vol = (float)(ping->len - i) / (float)ping->len * 31;

      *p = 128 + (sin(osc1) + sin(osc2) - 1) * vol;

      osc1 += 0.2;
      osc2 += 0.3;

      p++;
   }
}



/* closes down the sound system */
void shutdown_sound()
{
   destroy_sample(zap);
   destroy_sample(bang);
   destroy_sample(bigbang);
   destroy_sample(ping);
}



/* plays a shoot sound effect */
void sfx_shoot()
{
   play_sample(zap, 96, 128, 1000, FALSE);
}



/* plays an alien explosion sound effect */
void sfx_explode_alien()
{
   play_sample(bang, 192, 128, 1000, FALSE);
}



/* plays a block explosion sound effect */
void sfx_explode_block()
{
   play_sample(bang, 224, 128, 400, FALSE);
}



/* plays a player explosion sound effect */
void sfx_explode_player()
{
   play_sample(bigbang, 255, 128, 1000, FALSE);
}



/* timer callback for playing ping samples */
static int ping_vol;
static int ping_freq;
static int ping_count;


static void ping_proc(void)
{
   ping_freq = ping_freq*4/3;

   play_sample(ping, ping_vol, 128, ping_freq, FALSE);

   if (!--ping_count) 
      remove_int(ping_proc);
}

END_OF_STATIC_FUNCTION(ping_proc);



/* plays a ping sound effect */
void sfx_ping(int times)
{
   static int virgin = TRUE;

   if (times) {
      if (virgin) {
	 LOCK_VARIABLE(ping);
	 LOCK_VARIABLE(ping_vol);
	 LOCK_VARIABLE(ping_freq);
	 LOCK_VARIABLE(ping_count);
	 LOCK_FUNCTION(ping_proc);

	 virgin = FALSE;
      }

      if (times > 1) {
	 ping_vol = 255;
	 ping_freq = 500;
      }
      else {
	 ping_vol = 128;
	 ping_freq = 1000;
      }

      ping_count = times;

      play_sample(ping, ping_vol, 128, ping_freq, FALSE);

      install_int(ping_proc, 300);
   }
   else
      play_sample(ping, 255, 128, 500, FALSE);
}

