/* SCAVENGER by David Ashley  dash@.com SDL version by Barry Mead bmead15@cox.net */
/* License GPL.  See COPYING for details of GPL License */
/* $Author$    $Date$   $Id$   $Revision$ */

#include "scav.h"

char dirlist[]="data";


#define NUMSOUNDS	(sizeof(soundnames)/sizeof(char*))
#define MIXMAX 16

#define SOUND_QUIET -1

char soundactive=0;

char *soundnames[] =
{
"fall.raw",
"dig.raw",
"pop.raw",
"victory.raw",
"death.raw"
};
typedef struct sample
{
	char *data;
	int len;
} sample;

#define SNDFRAGMENT 512

sample samples[NUMSOUNDS];

int soundworking=0;
int fragment;
int soundwrite,soundread;
int *soundbuffer;
int soundbufferlen;
unsigned char sndclip[8192];

#define MAXSOUNDCOMMANDS 32
char soundcommands[MAXSOUNDCOMMANDS];
int soundtake,soundput;

int sndplaying[MIXMAX],sndposition[MIXMAX];
void fillaudio(void *udata, uint8_t *buffer,int len)
{
char com,*p;
int i,j,*ip;
int which;

	while(soundtake!=soundput)
	{
		com=soundcommands[soundtake];
		soundtake=(soundtake+1)&(MAXSOUNDCOMMANDS-1);
		if(com==SOUND_QUIET) {memset(sndposition,0,sizeof(sndposition));continue;}
		if((com&63)<NUMSOUNDS)
		{
			if(com&64)
			{
				for(i=0;i<MIXMAX;++i)
					if(sndplaying[i]==(com&63))
						sndposition[i]=0;
			} else
			{
				for(i=0;i<MIXMAX;++i)
					if(!sndposition[i])
					{
						sndposition[i]=1;
						sndplaying[i]=com;
						break;
					}
			}
		} else if(com==-1)
		{
			for(i=0;i<MIXMAX;++i)
				sndposition[i]=0;
		}
	}
	memset(soundbuffer,0,soundbufferlen);
	for(i=0;i<MIXMAX;++i)
	{
		if(!sndposition[i]) continue;
		which=sndplaying[i];
		if(sndposition[i]==samples[which].len)
		{
			sndposition[i]=0;
			continue;
		}
		p=samples[which].data;
		if(!p) continue;
		p+=len*(sndposition[i]++ -1);
		ip=soundbuffer;
		j=len;
		while(j--) *ip++ += *p++;
	}
	j=len;
	ip=soundbuffer;;
	while(j--) *buffer++ = sndclip[4096+*ip++];
	for(i=0;i<MIXMAX;++i)
		if(sndposition[i]) break;
	if(i==MIXMAX) soundactive=0;
}


void readsound(int num)
{
char name[256],*p1;
int i,file,size,len;
	for(i=0;;)
	{
		if(!expandpath(name,soundnames[num],i))
		{
			samples[num].len=-1;
			return;
		}
		file=open(name,O_RDONLY|O_BINARY);
		if(file>=0) break;
		++i;
	}
	size=lseek(file,0,SEEK_END);
	lseek(file,0,SEEK_SET);
	len=samples[num].len=(size+fragment-1)/fragment;
	len*=fragment;
	p1=samples[num].data=malloc(len);
	if(p1)
	{
		i=read(file,p1,size);
		if(len-size) memset(p1+size,0,len-size);
		while(size--) *p1++ ^= 0x80;
	} else
		samples[num].data=0;
	close(file);
}

int soundopen(void)
{
SDL_AudioSpec wanted;
int i,j;

	soundtake=soundput=0;
	memset(sndposition,0,sizeof(sndposition));
	memset(sndplaying,0,sizeof(sndplaying));
	fragment=SNDFRAGMENT; //<<1;
	soundbufferlen=fragment*sizeof(int);
	soundbuffer=malloc(soundbufferlen);
	if(!soundbuffer) return -2;

	memset(&wanted,0,sizeof(wanted));
	wanted.freq=11025;
	wanted.channels=1;
	wanted.format=AUDIO_U8;
	wanted.samples=fragment; //>>1;
	wanted.callback=fillaudio;
	wanted.userdata=0;

	if(SDL_OpenAudio(&wanted,0)<0)
	{
		fprintf(stderr,"Couldn't open audio: %s\n",SDL_GetError());
		return -1;
	}
	soundworking=1;

	for(i=0;i<8192;i++)
	{
		j=i-4096;
		sndclip[i]=j > 127 ? 255 : (j<-128 ? 0 : j+128);
	}

	for(i=0;i<NUMSOUNDS;++i)
		readsound(i);

	SDL_PauseAudio(0);
   return 0;
}
void soundclose(void)
{
	if(soundworking)
	{
		SDL_CloseAudio();
		soundworking=0;
	}
}

void playsound(int n)
{
	if(n>=0 && n<64) soundactive=1;
	soundcommands[soundput]=n;
	soundput=(soundput+1)&(MAXSOUNDCOMMANDS-1);
}
