// 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 #include #include #include #include #include #include #include #include #include #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 ; idata; 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 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 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; }