sdlbomber/sound.c
2009-08-28 22:06:06 +02:00

191 lines
3.4 KiB
C

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <SDL_audio.h>
#include <SDL_error.h>
#include "sound.h"
#ifndef DATADIR
#define DATADIR "data"
#endif
int sound_enabled = 1;
static char dirlist[]=DATADIR;
static int readsound(int num);
#define NUMSOUNDS ((int)(sizeof(soundnames)/sizeof(char*)))
#define MIXMAX 16
#define SOUND_QUIET -1
static const char *soundnames[] = {
"bomb1.raw",
"power1.raw",
"death.raw",
"drop.raw",
"bomb2.raw",
"power2.raw",
};
typedef struct sample
{
char *data;
int len;
} sample;
#define SNDFRAGMENT 1024
static sample samples[NUMSOUNDS];
static int soundworking=0;
static int fragment;
// static int soundwrite,soundread;
static int *soundbuffer;
static int soundbufferlen;
static unsigned char sndclip[8192];
#define MAXSOUNDCOMMANDS 32
static char soundcommands[MAXSOUNDCOMMANDS];
static int soundtake,soundput;
static int sndplaying[MIXMAX],sndposition[MIXMAX];
static void fillaudio(void *udata,Uint8 *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<NUMSOUNDS)
{
for(i=0;i<MIXMAX;++i)
if(!sndposition[i])
{
sndposition[i]=1;
sndplaying[i]=com;
break;
}
}
}
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++];
}
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=22050;
wanted.channels=2;
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;
}
}
int readsound(int num) {
char name[256],*p1,*p2,ch;
int i,file,size,len;
p1=dirlist;
for(;;)
{
p2=name;
while(*p1 && (ch=*p1++)!=',')
*p2++=ch;
if(p2>name && p2[-1]!='/') *p2++='/';
strcpy(p2,soundnames[num]);
file=open(name,O_RDONLY);
if(file>=0) break;
if(!*p1)
{
samples[num].len=-1;
return 0;
}
}
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);
return 0;
}
void playsound(int n) {
if (sound_enabled) {
soundcommands[soundput]=n;
soundput=(soundput+1)&(MAXSOUNDCOMMANDS-1);
}
}