123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741 |
- // Emacs style mode select -*- C++ -*-
- //-----------------------------------------------------------------------------
- //
- // $Id: soundsrv.c,v 1.3 1997/01/29 22:40:44 b1 Exp $
- //
- // Copyright (C) 1993-1996 by id Software, Inc.
- //
- // This source is available for distribution and/or modification
- // only under the terms of the DOOM Source Code License as
- // published by id Software. All rights reserved.
- //
- // The source is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
- // for more details.
- //
- //
- // $Log: soundsrv.c,v $
- // Revision 1.3 1997/01/29 22:40:44 b1
- // Reformatting, S (sound) module files.
- //
- // Revision 1.2 1997/01/21 19:00:07 b1
- // First formatting run:
- // using Emacs cc-mode.el indentation for C++ now.
- //
- // Revision 1.1 1997/01/19 17:22:50 b1
- // Initial check in DOOM sources as of Jan. 10th, 1997
- //
- //
- // DESCRIPTION:
- // UNIX soundserver, run as a separate process,
- // started by DOOM program.
- // Originally conceived fopr SGI Irix,
- // mostly used with Linux voxware.
- //
- //-----------------------------------------------------------------------------
- static const char rcsid[] = "$Id: soundsrv.c,v 1.3 1997/01/29 22:40:44 b1 Exp $";
- #include <math.h>
- #include <sys/types.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <malloc.h>
- #include <sys/stat.h>
- #include <sys/time.h>
- #include "sounds.h"
- #include "soundsrv.h"
- #include "wadread.h"
- //
- // Department of Redundancy Department.
- //
- typedef struct wadinfo_struct
- {
- // should be IWAD
- char identification[4];
- int numlumps;
- int infotableofs;
-
- } wadinfo_t;
- typedef struct filelump_struct
- {
- int filepos;
- int size;
- char name[8];
-
- } filelump_t;
- // an internal time keeper
- static int mytime = 0;
- // number of sound effects
- int numsounds;
- // longest sound effect
- int longsound;
- // lengths of all sound effects
- int lengths[NUMSFX];
- // mixing buffer
- signed short mixbuffer[MIXBUFFERSIZE];
- // file descriptor of sfx device
- int sfxdevice;
- // file descriptor of music device
- int musdevice;
- // the channel data pointers
- unsigned char* channels[8];
- // the channel step amount
- unsigned int channelstep[8];
- // 0.16 bit remainder of last step
- unsigned int channelstepremainder[8];
- // the channel data end pointers
- unsigned char* channelsend[8];
- // time that the channel started playing
- int channelstart[8];
- // the channel handles
- int channelhandles[8];
- // the channel left volume lookup
- int* channelleftvol_lookup[8];
- // the channel right volume lookup
- int* channelrightvol_lookup[8];
- // sfx id of the playing sound effect
- int channelids[8];
- int snd_verbose=1;
- int steptable[256];
- int vol_lookup[128*256];
- static void derror(char* msg)
- {
- fprintf(stderr, "error: %s\n", msg);
- exit(-1);
- }
- int mix(void)
- {
- register int dl;
- register int dr;
- register unsigned int sample;
-
- signed short* leftout;
- signed short* rightout;
- signed short* leftend;
-
- int step;
- leftout = mixbuffer;
- rightout = mixbuffer+1;
- step = 2;
- leftend = mixbuffer + SAMPLECOUNT*step;
- // mix into the mixing buffer
- while (leftout != leftend)
- {
- dl = 0;
- dr = 0;
- if (channels[0])
- {
- sample = *channels[0];
- dl += channelleftvol_lookup[0][sample];
- dr += channelrightvol_lookup[0][sample];
- channelstepremainder[0] += channelstep[0];
- channels[0] += channelstepremainder[0] >> 16;
- channelstepremainder[0] &= 65536-1;
- if (channels[0] >= channelsend[0])
- channels[0] = 0;
- }
- if (channels[1])
- {
- sample = *channels[1];
- dl += channelleftvol_lookup[1][sample];
- dr += channelrightvol_lookup[1][sample];
- channelstepremainder[1] += channelstep[1];
- channels[1] += channelstepremainder[1] >> 16;
- channelstepremainder[1] &= 65536-1;
- if (channels[1] >= channelsend[1])
- channels[1] = 0;
- }
- if (channels[2])
- {
- sample = *channels[2];
- dl += channelleftvol_lookup[2][sample];
- dr += channelrightvol_lookup[2][sample];
- channelstepremainder[2] += channelstep[2];
- channels[2] += channelstepremainder[2] >> 16;
- channelstepremainder[2] &= 65536-1;
- if (channels[2] >= channelsend[2])
- channels[2] = 0;
- }
-
- if (channels[3])
- {
- sample = *channels[3];
- dl += channelleftvol_lookup[3][sample];
- dr += channelrightvol_lookup[3][sample];
- channelstepremainder[3] += channelstep[3];
- channels[3] += channelstepremainder[3] >> 16;
- channelstepremainder[3] &= 65536-1;
- if (channels[3] >= channelsend[3])
- channels[3] = 0;
- }
-
- if (channels[4])
- {
- sample = *channels[4];
- dl += channelleftvol_lookup[4][sample];
- dr += channelrightvol_lookup[4][sample];
- channelstepremainder[4] += channelstep[4];
- channels[4] += channelstepremainder[4] >> 16;
- channelstepremainder[4] &= 65536-1;
- if (channels[4] >= channelsend[4])
- channels[4] = 0;
- }
-
- if (channels[5])
- {
- sample = *channels[5];
- dl += channelleftvol_lookup[5][sample];
- dr += channelrightvol_lookup[5][sample];
- channelstepremainder[5] += channelstep[5];
- channels[5] += channelstepremainder[5] >> 16;
- channelstepremainder[5] &= 65536-1;
- if (channels[5] >= channelsend[5])
- channels[5] = 0;
- }
-
- if (channels[6])
- {
- sample = *channels[6];
- dl += channelleftvol_lookup[6][sample];
- dr += channelrightvol_lookup[6][sample];
- channelstepremainder[6] += channelstep[6];
- channels[6] += channelstepremainder[6] >> 16;
- channelstepremainder[6] &= 65536-1;
- if (channels[6] >= channelsend[6])
- channels[6] = 0;
- }
- if (channels[7])
- {
- sample = *channels[7];
- dl += channelleftvol_lookup[7][sample];
- dr += channelrightvol_lookup[7][sample];
- channelstepremainder[7] += channelstep[7];
- channels[7] += channelstepremainder[7] >> 16;
- channelstepremainder[7] &= 65536-1;
- if (channels[7] >= channelsend[7])
- channels[7] = 0;
- }
- // Has been char instead of short.
- // if (dl > 127) *leftout = 127;
- // else if (dl < -128) *leftout = -128;
- // else *leftout = dl;
- // if (dr > 127) *rightout = 127;
- // else if (dr < -128) *rightout = -128;
- // else *rightout = dr;
-
- if (dl > 0x7fff)
- *leftout = 0x7fff;
- else if (dl < -0x8000)
- *leftout = -0x8000;
- else
- *leftout = dl;
- if (dr > 0x7fff)
- *rightout = 0x7fff;
- else if (dr < -0x8000)
- *rightout = -0x8000;
- else
- *rightout = dr;
- leftout += step;
- rightout += step;
- }
- return 1;
- }
- void
- grabdata
- ( int c,
- char** v )
- {
- int i;
- char* name;
- char* doom1wad;
- char* doomwad;
- char* doomuwad;
- char* doom2wad;
- char* doom2fwad;
- // Now where are TNT and Plutonia. Yuck.
-
- // char *home;
- char* doomwaddir;
- doomwaddir = getenv("DOOMWADDIR");
- if (!doomwaddir)
- doomwaddir = ".";
- doom1wad = malloc(strlen(doomwaddir)+1+9+1);
- sprintf(doom1wad, "%s/doom1.wad", doomwaddir);
- doom2wad = malloc(strlen(doomwaddir)+1+9+1);
- sprintf(doom2wad, "%s/doom2.wad", doomwaddir);
- doom2fwad = malloc(strlen(doomwaddir)+1+10+1);
- sprintf(doom2fwad, "%s/doom2f.wad", doomwaddir);
-
- doomuwad = malloc(strlen(doomwaddir)+1+8+1);
- sprintf(doomuwad, "%s/doomu.wad", doomwaddir);
-
- doomwad = malloc(strlen(doomwaddir)+1+8+1);
- sprintf(doomwad, "%s/doom.wad", doomwaddir);
- // home = getenv("HOME");
- // if (!home)
- // derror("Please set $HOME to your home directory");
- // sprintf(basedefault, "%s/.doomrc", home);
- for (i=1 ; i<c ; i++)
- {
- if (!strcmp(v[i], "-quiet"))
- {
- snd_verbose = 0;
- }
- }
- numsounds = NUMSFX;
- longsound = 0;
- if (! access(doom2fwad, R_OK) )
- name = doom2fwad;
- else if (! access(doom2wad, R_OK) )
- name = doom2wad;
- else if (! access(doomuwad, R_OK) )
- name = doomuwad;
- else if (! access(doomwad, R_OK) )
- name = doomwad;
- else if (! access(doom1wad, R_OK) )
- name = doom1wad;
- // else if (! access(DEVDATA "doom2.wad", R_OK) )
- // name = DEVDATA "doom2.wad";
- // else if (! access(DEVDATA "doom.wad", R_OK) )
- // name = DEVDATA "doom.wad";
- else
- {
- fprintf(stderr, "Could not find wadfile anywhere\n");
- exit(-1);
- }
-
- openwad(name);
- if (snd_verbose)
- fprintf(stderr, "loading from [%s]\n", name);
- for (i=1 ; i<NUMSFX ; i++)
- {
- if (!S_sfx[i].link)
- {
- S_sfx[i].data = getsfx(S_sfx[i].name, &lengths[i]);
- if (longsound < lengths[i]) longsound = lengths[i];
- } else {
- S_sfx[i].data = S_sfx[i].link->data;
- lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)];
- }
- // test only
- // {
- // int fd;
- // char name[10];
- // sprintf(name, "sfx%d", i);
- // fd = open(name, O_WRONLY|O_CREAT, 0644);
- // write(fd, S_sfx[i].data, lengths[i]);
- // close(fd);
- // }
- }
- }
- static struct timeval last={0,0};
- //static struct timeval now;
- static struct timezone whocares;
- void updatesounds(void)
- {
- mix();
- I_SubmitOutputBuffer(mixbuffer, SAMPLECOUNT);
- }
- int
- addsfx
- ( int sfxid,
- int volume,
- int step,
- int seperation )
- {
- static unsigned short handlenums = 0;
-
- int i;
- int rc = -1;
-
- int oldest = mytime;
- int oldestnum = 0;
- int slot;
- int rightvol;
- int leftvol;
- // play these sound effects
- // only one at a time
- if ( sfxid == sfx_sawup
- || sfxid == sfx_sawidl
- || sfxid == sfx_sawful
- || sfxid == sfx_sawhit
- || sfxid == sfx_stnmov
- || sfxid == sfx_pistol )
- {
- for (i=0 ; i<8 ; i++)
- {
- if (channels[i] && channelids[i] == sfxid)
- {
- channels[i] = 0;
- break;
- }
- }
- }
- for (i=0 ; i<8 && channels[i] ; i++)
- {
- if (channelstart[i] < oldest)
- {
- oldestnum = i;
- oldest = channelstart[i];
- }
- }
- if (i == 8)
- slot = oldestnum;
- else
- slot = i;
- channels[slot] = (unsigned char *) S_sfx[sfxid].data;
- channelsend[slot] = channels[slot] + lengths[sfxid];
- if (!handlenums)
- handlenums = 100;
-
- channelhandles[slot] = rc = handlenums++;
- channelstep[slot] = step;
- channelstepremainder[slot] = 0;
- channelstart[slot] = mytime;
- // (range: 1 - 256)
- seperation += 1;
- // (x^2 seperation)
- leftvol =
- volume - (volume*seperation*seperation)/(256*256);
- seperation = seperation - 257;
- // (x^2 seperation)
- rightvol =
- volume - (volume*seperation*seperation)/(256*256);
- // sanity check
- if (rightvol < 0 || rightvol > 127)
- derror("rightvol out of bounds");
-
- if (leftvol < 0 || leftvol > 127)
- derror("leftvol out of bounds");
-
- // get the proper lookup table piece
- // for this volume level
- channelleftvol_lookup[slot] = &vol_lookup[leftvol*256];
- channelrightvol_lookup[slot] = &vol_lookup[rightvol*256];
- channelids[slot] = sfxid;
- return rc;
- }
- void outputushort(int num)
- {
- static unsigned char buff[5] = { 0, 0, 0, 0, '\n' };
- static char* badbuff = "xxxx\n";
- // outputs a 16-bit # in hex or "xxxx" if -1.
- if (num < 0)
- {
- write(1, badbuff, 5);
- }
- else
- {
- buff[0] = num>>12;
- buff[0] += buff[0] > 9 ? 'a'-10 : '0';
- buff[1] = (num>>8) & 0xf;
- buff[1] += buff[1] > 9 ? 'a'-10 : '0';
- buff[2] = (num>>4) & 0xf;
- buff[2] += buff[2] > 9 ? 'a'-10 : '0';
- buff[3] = num & 0xf;
- buff[3] += buff[3] > 9 ? 'a'-10 : '0';
- write(1, buff, 5);
- }
- }
- void initdata(void)
- {
- int i;
- int j;
-
- int* steptablemid = steptable + 128;
- for (i=0 ;
- i<sizeof(channels)/sizeof(unsigned char *) ;
- i++)
- {
- channels[i] = 0;
- }
-
- gettimeofday(&last, &whocares);
- for (i=-128 ; i<128 ; i++)
- steptablemid[i] = pow(2.0, (i/64.0))*65536.0;
- // generates volume lookup tables
- // which also turn the unsigned samples
- // into signed samples
- // for (i=0 ; i<128 ; i++)
- // for (j=0 ; j<256 ; j++)
- // vol_lookup[i*256+j] = (i*(j-128))/127;
-
- for (i=0 ; i<128 ; i++)
- for (j=0 ; j<256 ; j++)
- vol_lookup[i*256+j] = (i*(j-128)*256)/127;
- }
- void quit(void)
- {
- I_ShutdownMusic();
- I_ShutdownSound();
- exit(0);
- }
- fd_set fdset;
- fd_set scratchset;
- int
- main
- ( int c,
- char** v )
- {
- int done = 0;
- int rc;
- int nrc;
- int sndnum;
- int handle = 0;
-
- unsigned char commandbuf[10];
- struct timeval zerowait = { 0, 0 };
-
- int step;
- int vol;
- int sep;
-
- int i;
- int waitingtofinish=0;
- // get sound data
- grabdata(c, v);
- // init any data
- initdata();
- I_InitSound(11025, 16);
- I_InitMusic();
- if (snd_verbose)
- fprintf(stderr, "ready\n");
-
- // parse commands and play sounds until done
- FD_ZERO(&fdset);
- FD_SET(0, &fdset);
- while (!done)
- {
- mytime++;
- if (!waitingtofinish)
- {
- do {
- scratchset = fdset;
- rc = select(FD_SETSIZE, &scratchset, 0, 0, &zerowait);
- if (rc > 0)
- {
- // fprintf(stderr, "select is true\n");
- // got a command
- nrc = read(0, commandbuf, 1);
- if (!nrc)
- {
- done = 1;
- rc = 0;
- }
- else
- {
- if (snd_verbose)
- fprintf(stderr, "cmd: %c", commandbuf[0]);
- switch (commandbuf[0])
- {
- case 'p':
- // play a new sound effect
- read(0, commandbuf, 9);
- if (snd_verbose)
- {
- commandbuf[9]=0;
- fprintf(stderr, "%s\n", commandbuf);
- }
- commandbuf[0] -=
- commandbuf[0]>='a' ? 'a'-10 : '0';
- commandbuf[1] -=
- commandbuf[1]>='a' ? 'a'-10 : '0';
- commandbuf[2] -=
- commandbuf[2]>='a' ? 'a'-10 : '0';
- commandbuf[3] -=
- commandbuf[3]>='a' ? 'a'-10 : '0';
- commandbuf[4] -=
- commandbuf[4]>='a' ? 'a'-10 : '0';
- commandbuf[5] -=
- commandbuf[5]>='a' ? 'a'-10 : '0';
- commandbuf[6] -=
- commandbuf[6]>='a' ? 'a'-10 : '0';
- commandbuf[7] -=
- commandbuf[7]>='a' ? 'a'-10 : '0';
- // p<snd#><step><vol><sep>
- sndnum = (commandbuf[0]<<4) + commandbuf[1];
- step = (commandbuf[2]<<4) + commandbuf[3];
- step = steptable[step];
- vol = (commandbuf[4]<<4) + commandbuf[5];
- sep = (commandbuf[6]<<4) + commandbuf[7];
- handle = addsfx(sndnum, vol, step, sep);
- // returns the handle
- // outputushort(handle);
- break;
-
- case 'q':
- read(0, commandbuf, 1);
- waitingtofinish = 1; rc = 0;
- break;
-
- case 's':
- {
- int fd;
- read(0, commandbuf, 3);
- commandbuf[2] = 0;
- fd = open((char*)commandbuf, O_CREAT|O_WRONLY, 0644);
- commandbuf[0] -= commandbuf[0]>='a' ? 'a'-10 : '0';
- commandbuf[1] -= commandbuf[1]>='a' ? 'a'-10 : '0';
- sndnum = (commandbuf[0]<<4) + commandbuf[1];
- write(fd, S_sfx[sndnum].data, lengths[sndnum]);
- close(fd);
- }
- break;
-
- default:
- fprintf(stderr, "Did not recognize command\n");
- break;
- }
- }
- }
- else if (rc < 0)
- {
- quit();
- }
- } while (rc > 0);
- }
- updatesounds();
- if (waitingtofinish)
- {
- for(i=0 ; i<8 && !channels[i] ; i++);
-
- if (i==8)
- done=1;
- }
- }
- quit();
- return 0;
- }
|