doom

a minimalistic implementation of doom
git clone git://ssnf.xyz/doom
Log | Files | Refs

soundsrv.c (13245B)


      1 #define LENGTH(x) (sizeof(x)/sizeof(x[0]))
      2 #include <string.h>
      3 #include <sys/types.h>
      4 #include <stdio.h>
      5 #include <fcntl.h>
      6 #include <sys/ioctl.h>
      7 #include <unistd.h>
      8 #include <stdlib.h>
      9 #include <malloc.h>
     10 #include <sys/stat.h>
     11 #include <sys/time.h>
     12 #include "sounds.h"
     13 #include "soundsrv.h"
     14 
     15 typedef struct wadinfo_struct
     16 {
     17     char	identification[4];	
     18     int		numlumps;
     19     int		infotableofs;
     20 } wadinfo_t;
     21 
     22 typedef struct filelump_struct
     23 {
     24     int		filepos;
     25     int		size;
     26     char	name[8];
     27 } filelump_t;
     28 
     29 static int	mytime = 0;
     30 int 		numsounds;
     31 int 		longsound;
     32 int 		lengths[NUMSFX];
     33 signed short	mixbuffer[MIXBUFFERSIZE];
     34 int		sfxdevice;			
     35 int 		musdevice;			
     36 unsigned char*	channels[8];
     37 unsigned int	channelstep[8];
     38 unsigned int	channelstepremainder[8];
     39 unsigned char*	channelsend[8];
     40 int		channelstart[8];
     41 int 		channelhandles[8];
     42 int*		channelleftvol_lookup[8];
     43 int*		channelrightvol_lookup[8];
     44 int		channelids[8];			
     45 int		snd_verbose=1;
     46 int steptable[256] = {
     47 16384, 16562, 16742, 16925, 17109, 17295, 17484, 17674, 17866, 18061, 18258, 18456, 18657, 18861, 19066, 19274, 19483, 19696, 19910, 20127, 20346, 20568, 20792, 21018, 21247, 21478, 21712, 21949, 22188, 22429, 22673, 22920, 23170, 23422, 23677, 23935, 24196, 24459, 24726, 24995, 25267, 25542, 25820, 26102, 26386, 26673, 26964, 27257, 27554, 27854, 28157, 28464, 28774, 29087, 29404, 29724, 30048, 30375, 30706, 31040, 31378, 31720, 32065, 32415, 32768, 33124, 33485, 33850, 34218, 34591, 34968, 35348, 35733, 36122, 36516, 36913, 37315, 37722, 38132, 38548, 38967, 39392, 39821, 40254, 40693, 41136, 41584, 42037, 42494, 42957, 43425, 43898, 44376, 44859, 45347, 45841, 46340, 46845, 47355, 47871, 48392, 48919, 49452, 49990, 50535, 51085, 51641, 52204, 52772, 53347, 53928, 54515, 55108, 55709, 56315, 56928, 57548, 58175, 58809, 59449, 60096, 60751, 61412, 62081, 62757, 63440, 64131, 64830, 65536, 66249, 66971, 67700, 68437, 69182, 69936, 70697, 71467, 72245, 73032, 73827, 74631, 75444, 76265, 77096, 77935, 78784, 79642, 80509, 81386, 82272, 83168, 84074, 84989, 85915, 86850, 87796, 88752, 89718, 90695, 91683, 92681, 93691, 94711, 95742, 96785, 97839, 98904, 99981, 101070, 102170, 103283, 104408, 105545, 106694, 107856, 109030, 110217, 111418, 112631, 113857, 115097, 116351, 117618, 118898, 120193, 121502, 122825, 124162, 125514, 126881, 128263, 129660, 131072, 132499, 133942, 135400, 136875, 138365, 139872, 141395, 142935, 144491, 146064, 147655, 149263, 150888, 152531, 154192, 155871, 157569, 159284, 161019, 162772, 164545, 166337, 168148, 169979, 171830, 173701, 175592, 177504, 179437, 181391, 183367, 185363, 187382, 189422, 191485, 193570, 195678, 197809, 199963, 202140, 204341, 206566, 208816, 211090, 213388, 215712, 218061, 220435, 222836, 225262, 227715, 230195, 232702, 235236, 237797, 240387, 243004, 245650, 248325, 251029, 253763, 256526, 259320
     48 };
     49 int		vol_lookup[128*256];
     50 static void derror(char* msg)
     51 {
     52     fprintf(stderr, "error: %s\n", msg);
     53     exit(-1);
     54 }
     55 int mix(void)
     56 {
     57     register int		dl;
     58     register int		dr;
     59     register unsigned int	sample;
     60     signed short*		leftout;
     61     signed short*		rightout;
     62     signed short*		leftend;
     63     int				step;
     64     leftout = mixbuffer;
     65     rightout = mixbuffer+1;
     66     step = 2;
     67     leftend = mixbuffer + SAMPLECOUNT*step;
     68     while (leftout != leftend)
     69     {
     70 	dl = 0;
     71 	dr = 0;
     72 	if (channels[0])
     73 	{
     74 	    sample = *channels[0];
     75 	    dl += channelleftvol_lookup[0][sample];
     76 	    dr += channelrightvol_lookup[0][sample];
     77 	    channelstepremainder[0] += channelstep[0];
     78 	    channels[0] += channelstepremainder[0] >> 16;
     79 	    channelstepremainder[0] &= 65536-1;
     80 	    if (channels[0] >= channelsend[0])
     81 		channels[0] = 0;
     82 	}
     83 	if (channels[1])
     84 	{
     85 	    sample = *channels[1];
     86 	    dl += channelleftvol_lookup[1][sample];
     87 	    dr += channelrightvol_lookup[1][sample];
     88 	    channelstepremainder[1] += channelstep[1];
     89 	    channels[1] += channelstepremainder[1] >> 16;
     90 	    channelstepremainder[1] &= 65536-1;
     91 	    if (channels[1] >= channelsend[1])
     92 		channels[1] = 0;
     93 	}
     94 	if (channels[2])
     95 	{
     96 	    sample = *channels[2];
     97 	    dl += channelleftvol_lookup[2][sample];
     98 	    dr += channelrightvol_lookup[2][sample];
     99 	    channelstepremainder[2] += channelstep[2];
    100 	    channels[2] += channelstepremainder[2] >> 16;
    101 	    channelstepremainder[2] &= 65536-1;
    102 	    if (channels[2] >= channelsend[2])
    103 		channels[2] = 0;
    104 	}
    105 	
    106 	if (channels[3])
    107 	{
    108 	    sample = *channels[3];
    109 	    dl += channelleftvol_lookup[3][sample];
    110 	    dr += channelrightvol_lookup[3][sample];
    111 	    channelstepremainder[3] += channelstep[3];
    112 	    channels[3] += channelstepremainder[3] >> 16;
    113 	    channelstepremainder[3] &= 65536-1;
    114 	    if (channels[3] >= channelsend[3])
    115 		channels[3] = 0;
    116 	}
    117 	
    118 	if (channels[4])
    119 	{
    120 	    sample = *channels[4];
    121 	    dl += channelleftvol_lookup[4][sample];
    122 	    dr += channelrightvol_lookup[4][sample];
    123 	    channelstepremainder[4] += channelstep[4];
    124 	    channels[4] += channelstepremainder[4] >> 16;
    125 	    channelstepremainder[4] &= 65536-1;
    126 	    if (channels[4] >= channelsend[4])
    127 		channels[4] = 0;
    128 	}
    129 	
    130 	if (channels[5])
    131 	{
    132 	    sample = *channels[5];
    133 	    dl += channelleftvol_lookup[5][sample];
    134 	    dr += channelrightvol_lookup[5][sample];
    135 	    channelstepremainder[5] += channelstep[5];
    136 	    channels[5] += channelstepremainder[5] >> 16;
    137 	    channelstepremainder[5] &= 65536-1;
    138 	    if (channels[5] >= channelsend[5])
    139 		channels[5] = 0;
    140 	}
    141 	
    142 	if (channels[6])
    143 	{
    144 	    sample = *channels[6];
    145 	    dl += channelleftvol_lookup[6][sample];
    146 	    dr += channelrightvol_lookup[6][sample];
    147 	    channelstepremainder[6] += channelstep[6];
    148 	    channels[6] += channelstepremainder[6] >> 16;
    149 	    channelstepremainder[6] &= 65536-1;
    150 	    if (channels[6] >= channelsend[6])
    151 		channels[6] = 0;
    152 	}
    153 	if (channels[7])
    154 	{
    155 	    sample = *channels[7];
    156 	    dl += channelleftvol_lookup[7][sample];
    157 	    dr += channelrightvol_lookup[7][sample];
    158 	    channelstepremainder[7] += channelstep[7];
    159 	    channels[7] += channelstepremainder[7] >> 16;
    160 	    channelstepremainder[7] &= 65536-1;
    161 	    if (channels[7] >= channelsend[7])
    162 		channels[7] = 0;
    163 	}
    164 	
    165 	
    166 	
    167 	
    168 	
    169 	
    170 	
    171 	
    172 	if (dl > 0x7fff)
    173 	    *leftout = 0x7fff;
    174 	else if (dl < -0x8000)
    175 	    *leftout = -0x8000;
    176 	else
    177 	    *leftout = dl;
    178 	if (dr > 0x7fff)
    179 	    *rightout = 0x7fff;
    180 	else if (dr < -0x8000)
    181 	    *rightout = -0x8000;
    182 	else
    183 	    *rightout = dr;
    184 	leftout += step;
    185 	rightout += step;
    186     }
    187     return 1;
    188 }
    189 void
    190 grabdata
    191 ( int		c,
    192   char**	v )
    193 {
    194     int		i;
    195     char*	name;
    196     char*	doom1wad;
    197     char*	doomwad;
    198     char*	doomuwad;
    199     char*	doom2wad;
    200     char*	doom2fwad;
    201     char*	doomwaddir;
    202     doomwaddir = getenv("DOOMWADDIR");
    203     if (!doomwaddir)
    204 	doomwaddir = ".";
    205     doom1wad = malloc(strlen(doomwaddir)+1+9+1);
    206     sprintf(doom1wad, "%s/doom1.wad", doomwaddir);
    207     doom2wad = malloc(strlen(doomwaddir)+1+9+1);
    208     sprintf(doom2wad, "%s/doom2.wad", doomwaddir);
    209     doom2fwad = malloc(strlen(doomwaddir)+1+10+1);
    210     sprintf(doom2fwad, "%s/doom2f.wad", doomwaddir);
    211     doomuwad = malloc(strlen(doomwaddir)+1+8+1);
    212     sprintf(doomuwad, "%s/doomu.wad", doomwaddir);
    213     doomwad = malloc(strlen(doomwaddir)+1+8+1);
    214     sprintf(doomwad, "%s/doom.wad", doomwaddir);
    215     for (i=1 ; i<c ; i++)
    216     {
    217 	if (!strcmp(v[i], "-quiet"))
    218 	{
    219 	    snd_verbose = 0;
    220 	}
    221     }
    222     numsounds = NUMSFX;
    223     longsound = 0;
    224     if (! access(doom2fwad, R_OK) )
    225 	name = doom2fwad;
    226     else if (! access(doom2wad, R_OK) )
    227 	name = doom2wad;
    228     else if (! access(doomuwad, R_OK) )
    229 	name = doomuwad;
    230     else if (! access(doomwad, R_OK) )
    231 	name = doomwad;
    232     else if (! access(doom1wad, R_OK) )
    233 	name = doom1wad;
    234     else
    235     {
    236 	fprintf(stderr, "Could not find wadfile anywhere\n");
    237 	exit(-1);
    238     }
    239     openwad(name);
    240     if (snd_verbose)
    241 	fprintf(stderr, "loading from [%s]\n", name);
    242     for (i=1 ; i<NUMSFX ; i++)
    243     {
    244 	if (!S_sfx[i].link)
    245 	{
    246 	    S_sfx[i].data = getsfx(S_sfx[i].name, &lengths[i]);
    247 	    if (longsound < lengths[i]) longsound = lengths[i];
    248 	} else {
    249 	    S_sfx[i].data = S_sfx[i].link->data;
    250 	    lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(SfxInfo)];
    251 	}
    252 	
    253 	
    254 	
    255 	
    256 	
    257 	
    258 	
    259 	
    260 	
    261     }
    262 }
    263 void updatesounds(void)
    264 {
    265     mix();
    266     I_SubmitOutputBuffer(mixbuffer, SAMPLECOUNT);
    267 }
    268 int
    269 addsfx
    270 ( int		sfxid,
    271   int		volume,
    272   int		step,
    273   int		seperation )
    274 {
    275     static unsigned short	handlenums = 0;
    276     int		i;
    277     int		rc = -1;
    278     int		oldest = mytime;
    279     int		oldestnum = 0;
    280     int		slot;
    281     int		rightvol;
    282     int		leftvol;
    283     if ( sfxid == sfx_sawup
    284 	 || sfxid == sfx_sawidl
    285 	 || sfxid == sfx_sawful
    286 	 || sfxid == sfx_sawhit
    287 	 || sfxid == sfx_stnmov
    288 	 || sfxid == sfx_pistol )
    289     {
    290 	for (i=0 ; i<8 ; i++)
    291 	{
    292 	    if (channels[i] && channelids[i] == sfxid)
    293 	    {
    294 		channels[i] = 0;
    295 		break;
    296 	    }
    297 	}
    298     }
    299     for (i=0 ; i<8 && channels[i] ; i++)
    300     {
    301 	if (channelstart[i] < oldest)
    302 	{
    303 	    oldestnum = i;
    304 	    oldest = channelstart[i];
    305 	}
    306     }
    307     if (i == 8)
    308 	slot = oldestnum;
    309     else
    310 	slot = i;
    311     channels[slot] = (unsigned char *) S_sfx[sfxid].data;
    312     channelsend[slot] = channels[slot] + lengths[sfxid];
    313     if (!handlenums)
    314 	handlenums = 100;
    315     channelhandles[slot] = rc = handlenums++;
    316     channelstep[slot] = step;
    317     channelstepremainder[slot] = 0;
    318     channelstart[slot] = mytime;
    319     seperation += 1;
    320     leftvol =
    321 	volume - (volume*seperation*seperation)/(256*256);
    322     seperation = seperation - 257;
    323     rightvol =
    324 	volume - (volume*seperation*seperation)/(256*256);	
    325     if (rightvol < 0 || rightvol > 127)
    326 	derror("rightvol out of bounds");
    327     if (leftvol < 0 || leftvol > 127)
    328 	derror("leftvol out of bounds");
    329     channelleftvol_lookup[slot] = &vol_lookup[leftvol*256];
    330     channelrightvol_lookup[slot] = &vol_lookup[rightvol*256];
    331     channelids[slot] = sfxid;
    332     return rc;
    333 }
    334 void outputushort(int num)
    335 {
    336     static unsigned char	buff[5] = { 0, 0, 0, 0, '\n' };
    337     static char*		badbuff = "xxxx\n";
    338     if (num < 0)
    339     {
    340 	write(1, badbuff, 5);
    341     }
    342     else
    343     {
    344 	buff[0] = num>>12;
    345 	buff[0] += buff[0] > 9 ? 'a'-10 : '0';
    346 	buff[1] = (num>>8) & 0xf;
    347 	buff[1] += buff[1] > 9 ? 'a'-10 : '0';
    348 	buff[2] = (num>>4) & 0xf;
    349 	buff[2] += buff[2] > 9 ? 'a'-10 : '0';
    350 	buff[3] = num & 0xf;
    351 	buff[3] += buff[3] > 9 ? 'a'-10 : '0';
    352 	write(1, buff, 5);
    353     }
    354 }
    355 void initdata(void)
    356 {
    357     int  i, j;
    358     int* steptablemid;
    359 	steptablemid = steptable + 128;
    360     for (i = 0 ; i < LENGTH(channels); ++i)
    361 		channels[i] = 0;
    362 	for (i = 0; i < 128; ++i)
    363 		for (j=0 ; j<256 ; j++)
    364 			vol_lookup[i*256+j] = (i*(j-128)*256)/127;
    365 }
    366 void quit(void)
    367 {
    368     I_ShutdownMusic();
    369     I_ShutdownSound();
    370     exit(0);
    371 }
    372 fd_set		fdset;
    373 fd_set		scratchset;
    374 
    375 int
    376 main(int c, char** v)
    377 {
    378     int		done = 0;
    379     int		rc;
    380     int		nrc;
    381     int		sndnum;
    382     int		handle = 0;
    383     unsigned char	commandbuf[10];
    384     struct timeval	zerowait = { 0, 0 };
    385     int 	step;
    386     int 	vol;
    387     int		sep;
    388     int		i;
    389     int		waitingtofinish=0;
    390     grabdata(c, v);
    391     initdata();		
    392     I_InitSound(11025, 16);
    393     I_InitMusic();
    394     if (snd_verbose)
    395 	fprintf(stderr, "ready\n");
    396     FD_ZERO(&fdset);
    397     FD_SET(0, &fdset);
    398     while (!done)
    399     {
    400 	mytime++;
    401 	if (!waitingtofinish)
    402 	{
    403 	    do {
    404 		scratchset = fdset;
    405 		rc = select(FD_SETSIZE, &scratchset, 0, 0, &zerowait);
    406 		if (rc > 0)
    407 		{
    408 		    
    409 		    
    410 		    nrc = read(0, commandbuf, 1);
    411 		    if (!nrc)
    412 		    {
    413 			done = 1;
    414 			rc = 0;
    415 		    }
    416 		    else
    417 		    {
    418 			if (snd_verbose)
    419 			    fprintf(stderr, "cmd: %c", commandbuf[0]);
    420 			switch (commandbuf[0])
    421 			{
    422 			  case 'p':
    423 			    
    424 			    read(0, commandbuf, 9);
    425 			    if (snd_verbose)
    426 			    {
    427 				commandbuf[9]=0;
    428 				fprintf(stderr, "%s\n", commandbuf);
    429 			    }
    430 			    commandbuf[0] -=
    431 				commandbuf[0]>='a' ? 'a'-10 : '0';
    432 			    commandbuf[1] -=
    433 				commandbuf[1]>='a' ? 'a'-10 : '0';
    434 			    commandbuf[2] -=
    435 				commandbuf[2]>='a' ? 'a'-10 : '0';
    436 			    commandbuf[3] -=
    437 				commandbuf[3]>='a' ? 'a'-10 : '0';
    438 			    commandbuf[4] -=
    439 				commandbuf[4]>='a' ? 'a'-10 : '0';
    440 			    commandbuf[5] -=
    441 				commandbuf[5]>='a' ? 'a'-10 : '0';
    442 			    commandbuf[6] -=
    443 				commandbuf[6]>='a' ? 'a'-10 : '0';
    444 			    commandbuf[7] -=
    445 				commandbuf[7]>='a' ? 'a'-10 : '0';
    446 			    
    447 			    sndnum = (commandbuf[0]<<4) + commandbuf[1];
    448 			    step = (commandbuf[2]<<4) + commandbuf[3];
    449 			    step = steptable[step];
    450 			    vol = (commandbuf[4]<<4) + commandbuf[5];
    451 			    sep = (commandbuf[6]<<4) + commandbuf[7];
    452 			    handle = addsfx(sndnum, vol, step, sep);
    453 			    
    454 			    
    455 			    break;
    456 			    
    457 			  case 'q':
    458 			    read(0, commandbuf, 1);
    459 			    waitingtofinish = 1; rc = 0;
    460 			    break;
    461 			    
    462 			  case 's':
    463 			  {
    464 			      int fd;
    465 			      read(0, commandbuf, 3);
    466 			      commandbuf[2] = 0;
    467 			      fd = open((char*)commandbuf, O_CREAT|O_WRONLY, 0644);
    468 			      commandbuf[0] -= commandbuf[0]>='a' ? 'a'-10 : '0';
    469 			      commandbuf[1] -= commandbuf[1]>='a' ? 'a'-10 : '0';
    470 			      sndnum = (commandbuf[0]<<4) + commandbuf[1];
    471 			      write(fd, S_sfx[sndnum].data, lengths[sndnum]);
    472 			      close(fd);
    473 			  }
    474 			  break;
    475 			  
    476 			  default:
    477 			    fprintf(stderr, "Did not recognize command\n");
    478 			    break;
    479 			}
    480 		    }
    481 		}
    482 		else if (rc < 0)
    483 		{
    484 		    quit();
    485 		}
    486 	    } while (rc > 0);
    487 	}
    488 	updatesounds();
    489 	if (waitingtofinish)
    490 	{
    491 	    for(i=0 ; i<8 && !channels[i] ; i++);
    492 	    
    493 	    if (i==8)
    494 		done=1;
    495 	}
    496     }
    497     quit();
    498     return 0;
    499 }