#ifdef LINUXAUDIO /* SoundIt library 0.021 Copyright 1994 Brad Pitzel pitzel@cs.sfu.ca Feel free to use/distribute/modify as long as proper credits are included. */ #include "soundIt.h" #include #include /* PATH_MAX */ #include #include #include #include #include #include #include #include #include #include /*==========================================================================*/ /* the mix buff, where the channels are mixed into. The mix buffer is then dumped to the sound device (/dev/dsp). Samples are mixed in Vunclipbuf (buffer of ints), then the values in Vunclipbuf are clipped to values between 0 and 255, and stored into Vclippedbuf (buffer of unsigned chars). */ struct Mix { unsigned char *Vclippedbuf; int *Vunclipbuf; int Vsize; }; typedef struct Mix Mix; /*==========================================================================*/ struct Channel { unsigned char *Vstart,*Vcurrent; /* ptr's into a playing sample */ int Vlen; /* length of sample in bytes */ int Vleft; /* bytes left of sample to play */ int Snum; }; typedef struct Channel Channel; /*==========================================================================*/ /* variables prefixed with S_ are static */ /* 0 if mixer isn't initialized or init failed, 1 if mixer is good */ static int sampleMixerStatus = 0; static const Sample *S_sounds = NULL; /* ptr to array of samples */ static int S_num_sounds = 0; /* size of 'sounds' array above */ static int S_fd_snddev = -1; /* file # for sound device once open */ static int S_fd_pipe[2] = { -1, -1 }; /* pipe to talk to child process */ static int S_son_pid = -1; /* process ID for the forked sound mixer */ static const char *S_snddev = NULL; /* char string for device, ie "/dev/dsp" */ static int S_num_channels = 6; /* number of channels to mix */ static int S_playback_freq = 0; /* playback frequency (in Hz) */ /*==========================================================================*/ /* non-public functions, used only within this file*/ int Snd_init_dev(); int Snd_restore_dev(); void Chan_reset( Channel *chan ); /* init channel structure */ /* start a sample playing on a channel */ void Chan_assign( Channel *chan, const Sample *snd, int sound_num ); /* mix all channels together into the 'mix' structure */ int Chan_mixAll( Mix *mix, Channel *ch ); /* used by Chan_mixAll to mix the 1st channel */ int Chan_copyIn( Channel *chan, Mix *mix ); /* used by Chan_mixAll to mix the middle channels */ int Chan_mixIn( Channel *chan, Mix *mix ); /* used by Chan_mixAll to mix the last channel */ int Chan_finalMixIn( Channel *chan, Mix *mix ); void Chan_resetSound( Channel *chan, int nr ); /* alloc mem for mix buffer, and deallocate function */ /* The sound channels are mixed together into the mix buffer */ /* then the mix buffer data is sent directly to the sound device */ void Mix_alloc( Mix *mix, int size ); void Mix_dealloc( Mix *mix ); /*==========================================================================*/ /* justing for testing, normally not called */ void dump_snd_list() { int i=0; for(i=0; iVstart=NULL; chan->Vcurrent=NULL; chan->Vlen=0; chan->Vleft=0; } /*==========================================================================*/ void Chan_assign( Channel *chan, const Sample *snd, int sound_num ) { chan->Vstart = snd->data; chan->Vcurrent= chan->Vstart; chan->Vlen = snd->len; chan->Vleft = snd->len; chan->Snum = sound_num; } /*==========================================================================*/ int Chan_copyIn( Channel *chan, Mix *mix ) { int i,*p = mix->Vunclipbuf, result, min; result = (chan->Vleft>0) ? 1 : 0; min = (chan->Vleft < mix->Vsize) ? chan->Vleft : mix->Vsize; for(i=0; iVcurrent++; } chan->Vleft -= i; /* fill the remaining (if any) part of the mix buffer with silence */ while (iVsize) { *p++ = 128; i++; } return result; } /*==========================================================================*/ int Chan_mixIn( Channel *chan, Mix *mix ) { int i,*p = mix->Vunclipbuf, result, min; result = (chan->Vleft>0) ? 1 : 0; min = (chan->Vleft < mix->Vsize) ? chan->Vleft : mix->Vsize; for(i=0; iVcurrent++) - 128; } chan->Vleft -= i; return result; } /*========================================================================*/ /* clip an int to a value between 0 and 255 */ static inline unsigned char clip(int i) { return (i<0) ? 0 : ( (i>255) ? 255 : i ); } /*==========================================================================*/ int Chan_finalMixIn( Channel *chan, Mix *mix ) { register int i; int *p = mix->Vunclipbuf, result, min; unsigned char *final = mix->Vclippedbuf; result = (chan->Vleft>0) ? 1 : 0; min = (chan->Vleft < mix->Vsize) ? chan->Vleft : mix->Vsize; for(i=0; iVcurrent++) - 128; *final++ = clip(*p++); } chan->Vleft -= i; /* copy rest of Vunclipbuf over to Vclippedbuf */ while (iVsize) { *final++ = clip(*p++); i++; } return result; } /*==========================================================================*/ void Mix_alloc(Mix *mix, int size) { mix->Vclippedbuf = (unsigned char *)calloc( sizeof(char), size); mix->Vunclipbuf = (int *)calloc( sizeof(int), size); mix->Vsize = size; if ((mix->Vclippedbuf==NULL)||(mix->Vunclipbuf==NULL)) { fprintf(stderr,"Unable to allocate memory for mixer buffer\n"); exit(-1); } } /*==========================================================================*/ void Mix_dealloc( Mix *mix) { if (mix->Vclippedbuf) free(mix->Vclippedbuf); if (mix->Vunclipbuf) free(mix->Vunclipbuf); } /*==========================================================================*/ /* Mixes together the channels into one sound. Returns # of channels currently playing *any* sound Therefore, return 0 means to channels have a sample, therefore no sound is playing */ int Chan_mixAll( Mix *mix, Channel *chan ) { int result = 0,i=0; result = Chan_copyIn( chan, mix); //printf("***************************\n"); /* we want to loop for S_num_channels-2 */ for(i=2;iVlen, chan->Vleft); result += Chan_mixIn( ++chan, mix); } //printf("Vlen = %d , Vleft = %d\n",chan->Vlen, chan->Vleft); result += Chan_finalMixIn( ++chan, mix); return result; } /*==========================================================================*/ /* Stop playing select sound in channels */ void Chan_resetSound( Channel *chan, int nr ) { int i; printf("kill here "); for(i = 0; i < S_num_channels; i++){ if (chan->Snum == nr) { Chan_reset(chan); printf("KILLL OK!!!\n"); } chan++; } } /*==========================================================================*/ /* given the name of a .raw sound file, load it into the Sample struct */ /* pointed to by 'sample' */ /* Returns -1 couldn't open/read file */ /* -2 couldn't alloc memory) */ int Snd_loadRawSample( const char *file, Sample *sample ) { FILE *fp; sample->data = NULL; sample->len = 0; fp = fopen(file,"r"); if (fp==NULL) return -1; /* get length of the file */ sample->len = lseek( fileno(fp), 0, SEEK_END ); /* go back to beginning of file */ lseek( fileno(fp), 0, SEEK_SET ); /* alloc memory for sample */ sample->data = (unsigned char *)malloc( sample->len ); if (sample->data==NULL) { fclose(fp); return -2; } fread( sample->data, 1, sample->len, fp ); fclose(fp); return 0; } #endif