Annotation of doom/i_soorig, revision 1.1.1.1

1.1       root        1: // Emacs style mode select   -*- C++ -*- 
                      2: //-----------------------------------------------------------------------------
                      3: //
                      4: // $Id:$
                      5: //
                      6: // Copyright (C) 1993-1996 by id Software, Inc.
                      7: //
                      8: // This program is free software; you can redistribute it and/or
                      9: // modify it under the terms of the GNU General Public License
                     10: // as published by the Free Software Foundation; either version 2
                     11: // of the License, or (at your option) any later version.
                     12: //
                     13: // This program is distributed in the hope that it will be useful,
                     14: // but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     16: // GNU General Public License for more details.
                     17: //
                     18: // $Log:$
                     19: //
                     20: // DESCRIPTION:
                     21: //     System interface for sound.
                     22: //
                     23: //-----------------------------------------------------------------------------
                     24: 
                     25: static const char
                     26: rcsid[] = "$Id: i_unix.c,v 1.5 1997/02/03 22:45:10 b1 Exp $";
                     27: 
                     28: #include <stdio.h>
                     29: #include <stdlib.h>
                     30: #include <stdarg.h>
                     31: 
                     32: #include <math.h>
                     33: 
                     34: #include <sys/time.h>
                     35: #include <sys/types.h>
                     36: 
                     37: #ifndef LINUX
                     38: #include <sys/filio.h>
                     39: #endif
                     40: 
                     41: #include <fcntl.h>
                     42: #include <unistd.h>
                     43: #include <sys/ioctl.h>
                     44: 
                     45: // Linux voxware output.
                     46: #include <linux/soundcard.h>
                     47: 
                     48: // Timer stuff. Experimental.
                     49: #include <time.h>
                     50: #include <signal.h>
                     51: 
                     52: #include "z_zone.h"
                     53: 
                     54: #include "i_system.h"
                     55: #include "i_sound.h"
                     56: #include "m_argv.h"
                     57: #include "m_misc.h"
                     58: #include "w_wad.h"
                     59: 
                     60: #include "doomdef.h"
                     61: 
                     62: // UNIX hack, to be removed.
                     63: #ifdef SNDSERV
                     64: // Separate sound server process.
                     65: FILE*  sndserver=0;
                     66: char*  sndserver_filename = "./sndserver ";
                     67: #elif SNDINTR
                     68: 
                     69: // Update all 30 millisecs, approx. 30fps synchronized.
                     70: // Linux resolution is allegedly 10 millisecs,
                     71: //  scale is microseconds.
                     72: #define SOUND_INTERVAL     500
                     73: 
                     74: // Get the interrupt. Set duration in millisecs.
                     75: int I_SoundSetTimer( int duration_of_tick );
                     76: void I_SoundDelTimer( void );
                     77: #else
                     78: // None?
                     79: #endif
                     80: 
                     81: 
                     82: // A quick hack to establish a protocol between
                     83: // synchronous mix buffer updates and asynchronous
                     84: // audio writes. Probably redundant with gametic.
                     85: static int flag = 0;
                     86: 
                     87: // The number of internal mixing channels,
                     88: //  the samples calculated for each mixing step,
                     89: //  the size of the 16bit, 2 hardware channel (stereo)
                     90: //  mixing buffer, and the samplerate of the raw data.
                     91: 
                     92: 
                     93: // Needed for calling the actual sound output.
                     94: #define SAMPLECOUNT            512
                     95: #define NUM_CHANNELS           8
                     96: // It is 2 for 16bit, and 2 for two channels.
                     97: #define BUFMUL                  4
                     98: #define MIXBUFFERSIZE          (SAMPLECOUNT*BUFMUL)
                     99: 
                    100: #define SAMPLERATE             11025   // Hz
                    101: #define SAMPLESIZE             2       // 16bit
                    102: 
                    103: // The actual lengths of all sound effects.
                    104: int            lengths[NUMSFX];
                    105: 
                    106: // The actual output device.
                    107: int    audio_fd;
                    108: 
                    109: // The global mixing buffer.
                    110: // Basically, samples from all active internal channels
                    111: //  are modifed and added, and stored in the buffer
                    112: //  that is submitted to the audio device.
                    113: signed short   mixbuffer[MIXBUFFERSIZE];
                    114: 
                    115: 
                    116: // The channel step amount...
                    117: unsigned int   channelstep[NUM_CHANNELS];
                    118: // ... and a 0.16 bit remainder of last step.
                    119: unsigned int   channelstepremainder[NUM_CHANNELS];
                    120: 
                    121: 
                    122: // The channel data pointers, start and end.
                    123: unsigned char* channels[NUM_CHANNELS];
                    124: unsigned char* channelsend[NUM_CHANNELS];
                    125: 
                    126: 
                    127: // Time/gametic that the channel started playing,
                    128: //  used to determine oldest, which automatically
                    129: //  has lowest priority.
                    130: // In case number of active sounds exceeds
                    131: //  available channels.
                    132: int            channelstart[NUM_CHANNELS];
                    133: 
                    134: // The sound in channel handles,
                    135: //  determined on registration,
                    136: //  might be used to unregister/stop/modify,
                    137: //  currently unused.
                    138: int            channelhandles[NUM_CHANNELS];
                    139: 
                    140: // SFX id of the playing sound effect.
                    141: // Used to catch duplicates (like chainsaw).
                    142: int            channelids[NUM_CHANNELS];                       
                    143: 
                    144: // Pitch to stepping lookup, unused.
                    145: int            steptable[256];
                    146: 
                    147: // Volume lookups.
                    148: int            vol_lookup[128*256];
                    149: 
                    150: // Hardware left and right channel volume lookup.
                    151: int*           channelleftvol_lookup[NUM_CHANNELS];
                    152: int*           channelrightvol_lookup[NUM_CHANNELS];
                    153: 
                    154: 
                    155: 
                    156: 
                    157: //
                    158: // Safe ioctl, convenience.
                    159: //
                    160: void
                    161: myioctl
                    162: ( int  fd,
                    163:   int  command,
                    164:   int* arg )
                    165: {   
                    166:     int                rc;
                    167:     extern int errno;
                    168:     
                    169:     rc = ioctl(fd, command, arg);  
                    170:     if (rc < 0)
                    171:     {
                    172:        fprintf(stderr, "ioctl(dsp,%d,arg) failed\n", command);
                    173:        fprintf(stderr, "errno=%d\n", errno);
                    174:        exit(-1);
                    175:     }
                    176: }
                    177: 
                    178: 
                    179: 
                    180: 
                    181: 
                    182: //
                    183: // This function loads the sound data from the WAD lump,
                    184: //  for single sound.
                    185: //
                    186: void*
                    187: getsfx
                    188: ( char*         sfxname,
                    189:   int*          len )
                    190: {
                    191:     unsigned char*      sfx;
                    192:     unsigned char*      paddedsfx;
                    193:     int                 i;
                    194:     int                 size;
                    195:     int                 paddedsize;
                    196:     char                name[20];
                    197:     int                 sfxlump;
                    198: 
                    199:     
                    200:     // Get the sound data from the WAD, allocate lump
                    201:     //  in zone memory.
                    202:     sprintf(name, "ds%s", sfxname);
                    203: 
                    204:     // Now, there is a severe problem with the
                    205:     //  sound handling, in it is not (yet/anymore)
                    206:     //  gamemode aware. That means, sounds from
                    207:     //  DOOM II will be requested even with DOOM
                    208:     //  shareware.
                    209:     // The sound list is wired into sounds.c,
                    210:     //  which sets the external variable.
                    211:     // I do not do runtime patches to that
                    212:     //  variable. Instead, we will use a
                    213:     //  default sound for replacement.
                    214:     if ( W_CheckNumForName(name) == -1 )
                    215:       sfxlump = W_GetNumForName("dspistol");
                    216:     else
                    217:       sfxlump = W_GetNumForName(name);
                    218:     
                    219:     size = W_LumpLength( sfxlump );
                    220: 
                    221:     // Debug.
                    222:     // fprintf( stderr, "." );
                    223:     //fprintf( stderr, " -loading  %s (lump %d, %d bytes)\n",
                    224:     //      sfxname, sfxlump, size );
                    225:     //fflush( stderr );
                    226:     
                    227:     sfx = (unsigned char*)W_CacheLumpNum( sfxlump, PU_STATIC );
                    228: 
                    229:     // Pads the sound effect out to the mixing buffer size.
                    230:     // The original realloc would interfere with zone memory.
                    231:     paddedsize = ((size-8 + (SAMPLECOUNT-1)) / SAMPLECOUNT) * SAMPLECOUNT;
                    232: 
                    233:     // Allocate from zone memory.
                    234:     paddedsfx = (unsigned char*)Z_Malloc( paddedsize+8, PU_STATIC, 0 );
                    235:     // ddt: (unsigned char *) realloc(sfx, paddedsize+8);
                    236:     // This should interfere with zone memory handling,
                    237:     //  which does not kick in in the soundserver.
                    238: 
                    239:     // Now copy and pad.
                    240:     memcpy(  paddedsfx, sfx, size );
                    241:     for (i=size ; i<paddedsize+8 ; i++)
                    242:         paddedsfx[i] = 128;
                    243: 
                    244:     // Remove the cached lump.
                    245:     Z_Free( sfx );
                    246:     
                    247:     // Preserve padded length.
                    248:     *len = paddedsize;
                    249: 
                    250:     // Return allocated padded data.
                    251:     return (void *) (paddedsfx + 8);
                    252: }
                    253: 
                    254: 
                    255: 
                    256: 
                    257: 
                    258: //
                    259: // This function adds a sound to the
                    260: //  list of currently active sounds,
                    261: //  which is maintained as a given number
                    262: //  (eight, usually) of internal channels.
                    263: // Returns a handle.
                    264: //
                    265: int
                    266: addsfx
                    267: ( int          sfxid,
                    268:   int          volume,
                    269:   int          step,
                    270:   int          seperation )
                    271: {
                    272:     static unsigned short      handlenums = 0;
                    273:  
                    274:     int                i;
                    275:     int                rc = -1;
                    276:     
                    277:     int                oldest = gametic;
                    278:     int                oldestnum = 0;
                    279:     int                slot;
                    280: 
                    281:     int                rightvol;
                    282:     int                leftvol;
                    283: 
                    284:     // Chainsaw troubles.
                    285:     // Play these sound effects only one at a time.
                    286:     if ( sfxid == sfx_sawup
                    287:         || sfxid == sfx_sawidl
                    288:         || sfxid == sfx_sawful
                    289:         || sfxid == sfx_sawhit
                    290:         || sfxid == sfx_stnmov
                    291:         || sfxid == sfx_pistol  )
                    292:     {
                    293:        // Loop all channels, check.
                    294:        for (i=0 ; i<NUM_CHANNELS ; i++)
                    295:        {
                    296:            // Active, and using the same SFX?
                    297:            if ( (channels[i])
                    298:                 && (channelids[i] == sfxid) )
                    299:            {
                    300:                // Reset.
                    301:                channels[i] = 0;
                    302:                // We are sure that iff,
                    303:                //  there will only be one.
                    304:                break;
                    305:            }
                    306:        }
                    307:     }
                    308: 
                    309:     // Loop all channels to find oldest SFX.
                    310:     for (i=0; (i<NUM_CHANNELS) && (channels[i]); i++)
                    311:     {
                    312:        if (channelstart[i] < oldest)
                    313:        {
                    314:            oldestnum = i;
                    315:            oldest = channelstart[i];
                    316:        }
                    317:     }
                    318: 
                    319:     // Tales from the cryptic.
                    320:     // If we found a channel, fine.
                    321:     // If not, we simply overwrite the first one, 0.
                    322:     // Probably only happens at startup.
                    323:     if (i == NUM_CHANNELS)
                    324:        slot = oldestnum;
                    325:     else
                    326:        slot = i;
                    327: 
                    328:     // Okay, in the less recent channel,
                    329:     //  we will handle the new SFX.
                    330:     // Set pointer to raw data.
                    331:     channels[slot] = (unsigned char *) S_sfx[sfxid].data;
                    332:     // Set pointer to end of raw data.
                    333:     channelsend[slot] = channels[slot] + lengths[sfxid];
                    334: 
                    335:     // Reset current handle number, limited to 0..100.
                    336:     if (!handlenums)
                    337:        handlenums = 100;
                    338: 
                    339:     // Assign current handle number.
                    340:     // Preserved so sounds could be stopped (unused).
                    341:     channelhandles[slot] = rc = handlenums++;
                    342: 
                    343:     // Set stepping???
                    344:     // Kinda getting the impression this is never used.
                    345:     channelstep[slot] = step;
                    346:     // ???
                    347:     channelstepremainder[slot] = 0;
                    348:     // Should be gametic, I presume.
                    349:     channelstart[slot] = gametic;
                    350: 
                    351:     // Separation, that is, orientation/stereo.
                    352:     //  range is: 1 - 256
                    353:     seperation += 1;
                    354: 
                    355:     // Per left/right channel.
                    356:     //  x^2 seperation,
                    357:     //  adjust volume properly.
                    358:     leftvol =
                    359:        volume - ((volume*seperation*seperation) >> 16); ///(256*256);
                    360:     seperation = seperation - 257;
                    361:     rightvol =
                    362:        volume - ((volume*seperation*seperation) >> 16);        
                    363: 
                    364:     // Sanity check, clamp volume.
                    365:     if (rightvol < 0 || rightvol > 127)
                    366:        I_Error("rightvol out of bounds");
                    367:     
                    368:     if (leftvol < 0 || leftvol > 127)
                    369:        I_Error("leftvol out of bounds");
                    370:     
                    371:     // Get the proper lookup table piece
                    372:     //  for this volume level???
                    373:     channelleftvol_lookup[slot] = &vol_lookup[leftvol*256];
                    374:     channelrightvol_lookup[slot] = &vol_lookup[rightvol*256];
                    375: 
                    376:     // Preserve sound SFX id,
                    377:     //  e.g. for avoiding duplicates of chainsaw.
                    378:     channelids[slot] = sfxid;
                    379: 
                    380:     // You tell me.
                    381:     return rc;
                    382: }
                    383: 
                    384: 
                    385: 
                    386: 
                    387: 
                    388: //
                    389: // SFX API
                    390: // Note: this was called by S_Init.
                    391: // However, whatever they did in the
                    392: // old DPMS based DOS version, this
                    393: // were simply dummies in the Linux
                    394: // version.
                    395: // See soundserver initdata().
                    396: //
                    397: void I_SetChannels()
                    398: {
                    399:   // Init internal lookups (raw data, mixing buffer, channels).
                    400:   // This function sets up internal lookups used during
                    401:   //  the mixing process. 
                    402:   int          i;
                    403:   int          j;
                    404:     
                    405:   int* steptablemid = steptable + 128;
                    406:   
                    407:   // Okay, reset internal mixing channels to zero.
                    408:   /*for (i=0; i<NUM_CHANNELS; i++)
                    409:   {
                    410:     channels[i] = 0;
                    411:   }*/
                    412: 
                    413:   // This table provides step widths for pitch parameters.
                    414:   // I fail to see that this is currently used.
                    415:   for (i=-128 ; i<128 ; i++)
                    416:     steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0);
                    417:   
                    418:   
                    419:   // Generates volume lookup tables
                    420:   //  which also turn the unsigned samples
                    421:   //  into signed samples.
                    422:   for (i=0 ; i<128 ; i++)
                    423:     for (j=0 ; j<256 ; j++)
                    424:       vol_lookup[i*256+j] = (i*(j-128)*256)/127;
                    425: }      
                    426: 
                    427:  
                    428: void I_SetSfxVolume(int volume)
                    429: {
                    430:   // Identical to DOS.
                    431:   // Basically, this should propagate
                    432:   //  the menu/config file setting
                    433:   //  to the state variable used in
                    434:   //  the mixing.
                    435:   snd_SfxVolume = volume;
                    436: }
                    437: 
                    438: // MUSIC API - dummy. Some code from DOS version.
                    439: void I_SetMusicVolume(int volume)
                    440: {
                    441:   // Internal state variable.
                    442:   snd_MusicVolume = volume;
                    443:   // Now set volume on output device.
                    444:   // Whatever( snd_MusciVolume );
                    445: }
                    446: 
                    447: 
                    448: //
                    449: // Retrieve the raw data lump index
                    450: //  for a given SFX name.
                    451: //
                    452: int I_GetSfxLumpNum(sfxinfo_t* sfx)
                    453: {
                    454:     char namebuf[9];
                    455:     sprintf(namebuf, "ds%s", sfx->name);
                    456:     return W_GetNumForName(namebuf);
                    457: }
                    458: 
                    459: //
                    460: // Starting a sound means adding it
                    461: //  to the current list of active sounds
                    462: //  in the internal channels.
                    463: // As the SFX info struct contains
                    464: //  e.g. a pointer to the raw data,
                    465: //  it is ignored.
                    466: // As our sound handling does not handle
                    467: //  priority, it is ignored.
                    468: // Pitching (that is, increased speed of playback)
                    469: //  is set, but currently not used by mixing.
                    470: //
                    471: int
                    472: I_StartSound
                    473: ( int          id,
                    474:   int          vol,
                    475:   int          sep,
                    476:   int          pitch,
                    477:   int          priority )
                    478: {
                    479: 
                    480:   // UNUSED
                    481:   priority = 0;
                    482:   
                    483: #ifdef SNDSERV 
                    484:     if (sndserver)
                    485:     {
                    486:        fprintf(sndserver, "p%2.2x%2.2x%2.2x%2.2x\n", id, pitch, vol, sep);
                    487:        fflush(sndserver);
                    488:     }
                    489:     // warning: control reaches end of non-void function.
                    490:     return id;
                    491: #else
                    492:     // Debug.
                    493:     //fprintf( stderr, "starting sound %d", id );
                    494:     
                    495:     // Returns a handle (not used).
                    496:     id = addsfx( id, vol, steptable[pitch], sep );
                    497: 
                    498:     // fprintf( stderr, "/handle is %d\n", id );
                    499:     
                    500:     return id;
                    501: #endif
                    502: }
                    503: 
                    504: 
                    505: 
                    506: void I_StopSound (int handle)
                    507: {
                    508:   // You need the handle returned by StartSound.
                    509:   // Would be looping all channels,
                    510:   //  tracking down the handle,
                    511:   //  an setting the channel to zero.
                    512:   
                    513:   // UNUSED.
                    514:   handle = 0;
                    515: }
                    516: 
                    517: 
                    518: int I_SoundIsPlaying(int handle)
                    519: {
                    520:     // Ouch.
                    521:     return gametic < handle;
                    522: }
                    523: 
                    524: 
                    525: 
                    526: 
                    527: //
                    528: // This function loops all active (internal) sound
                    529: //  channels, retrieves a given number of samples
                    530: //  from the raw sound data, modifies it according
                    531: //  to the current (internal) channel parameters,
                    532: //  mixes the per channel samples into the global
                    533: //  mixbuffer, clamping it to the allowed range,
                    534: //  and sets up everything for transferring the
                    535: //  contents of the mixbuffer to the (two)
                    536: //  hardware channels (left and right, that is).
                    537: //
                    538: // This function currently supports only 16bit.
                    539: //
                    540: void I_UpdateSound( void )
                    541: {
                    542: #ifdef SNDINTR
                    543:   // Debug. Count buffer misses with interrupt.
                    544:   static int misses = 0;
                    545: #endif
                    546: 
                    547:   
                    548:   // Mix current sound data.
                    549:   // Data, from raw sound, for right and left.
                    550:   register unsigned int        sample;
                    551:   register int         dl;
                    552:   register int         dr;
                    553:   
                    554:   // Pointers in global mixbuffer, left, right, end.
                    555:   signed short*                leftout;
                    556:   signed short*                rightout;
                    557:   signed short*                leftend;
                    558:   // Step in mixbuffer, left and right, thus two.
                    559:   int                          step;
                    560: 
                    561:   // Mixing channel index.
                    562:   int                          chan;
                    563:     
                    564:     // Left and right channel
                    565:     //  are in global mixbuffer, alternating.
                    566:     leftout = mixbuffer;
                    567:     rightout = mixbuffer+1;
                    568:     step = 2;
                    569: 
                    570:     // Determine end, for left channel only
                    571:     //  (right channel is implicit).
                    572:     leftend = mixbuffer + SAMPLECOUNT*step;
                    573: 
                    574:     // Mix sounds into the mixing buffer.
                    575:     // Loop over step*SAMPLECOUNT,
                    576:     //  that is 512 values for two channels.
                    577:     while (leftout != leftend)
                    578:     {
                    579:        // Reset left/right value. 
                    580:        dl = 0;
                    581:        dr = 0;
                    582: 
                    583:        // Love thy L2 chache - made this a loop.
                    584:        // Now more channels could be set at compile time
                    585:        //  as well. Thus loop those  channels.
                    586:        for ( chan = 0; chan < NUM_CHANNELS; chan++ )
                    587:        {
                    588:            // Check channel, if active.
                    589:            if (channels[ chan ])
                    590:            {
                    591:                // Get the raw data from the channel. 
                    592:                sample = *channels[ chan ];
                    593:                // Add left and right part
                    594:                //  for this channel (sound)
                    595:                //  to the current data.
                    596:                // Adjust volume accordingly.
                    597:                dl += channelleftvol_lookup[ chan ][sample];
                    598:                dr += channelrightvol_lookup[ chan ][sample];
                    599:                // Increment index ???
                    600:                channelstepremainder[ chan ] += channelstep[ chan ];
                    601:                // MSB is next sample???
                    602:                channels[ chan ] += channelstepremainder[ chan ] >> 16;
                    603:                // Limit to LSB???
                    604:                channelstepremainder[ chan ] &= 65536-1;
                    605: 
                    606:                // Check whether we are done.
                    607:                if (channels[ chan ] >= channelsend[ chan ])
                    608:                    channels[ chan ] = 0;
                    609:            }
                    610:        }
                    611:        
                    612:        // Clamp to range. Left hardware channel.
                    613:        // Has been char instead of short.
                    614:        // if (dl > 127) *leftout = 127;
                    615:        // else if (dl < -128) *leftout = -128;
                    616:        // else *leftout = dl;
                    617: 
                    618:        if (dl > 0x7fff)
                    619:            *leftout = 0x7fff;
                    620:        else if (dl < -0x8000)
                    621:            *leftout = -0x8000;
                    622:        else
                    623:            *leftout = dl;
                    624: 
                    625:        // Same for right hardware channel.
                    626:        if (dr > 0x7fff)
                    627:            *rightout = 0x7fff;
                    628:        else if (dr < -0x8000)
                    629:            *rightout = -0x8000;
                    630:        else
                    631:            *rightout = dr;
                    632: 
                    633:        // Increment current pointers in mixbuffer.
                    634:        leftout += step;
                    635:        rightout += step;
                    636:     }
                    637: 
                    638: #ifdef SNDINTR
                    639:     // Debug check.
                    640:     if ( flag )
                    641:     {
                    642:       misses += flag;
                    643:       flag = 0;
                    644:     }
                    645:     
                    646:     if ( misses > 10 )
                    647:     {
                    648:       fprintf( stderr, "I_SoundUpdate: missed 10 buffer writes\n");
                    649:       misses = 0;
                    650:     }
                    651:     
                    652:     // Increment flag for update.
                    653:     flag++;
                    654: #endif
                    655: }
                    656: 
                    657: 
                    658: // 
                    659: // This would be used to write out the mixbuffer
                    660: //  during each game loop update.
                    661: // Updates sound buffer and audio device at runtime. 
                    662: // It is called during Timer interrupt with SNDINTR.
                    663: // Mixing now done synchronous, and
                    664: //  only output be done asynchronous?
                    665: //
                    666: void
                    667: I_SubmitSound(void)
                    668: {
                    669:   // Write it to DSP device.
                    670:   write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL);
                    671: }
                    672: 
                    673: 
                    674: 
                    675: void
                    676: I_UpdateSoundParams
                    677: ( int  handle,
                    678:   int  vol,
                    679:   int  sep,
                    680:   int  pitch)
                    681: {
                    682:   // I fail too see that this is used.
                    683:   // Would be using the handle to identify
                    684:   //  on which channel the sound might be active,
                    685:   //  and resetting the channel parameters.
                    686: 
                    687:   // UNUSED.
                    688:   handle = vol = sep = pitch = 0;
                    689: }
                    690: 
                    691: 
                    692: 
                    693: 
                    694: void I_ShutdownSound(void)
                    695: {    
                    696: #ifdef SNDSERV
                    697:   if (sndserver)
                    698:   {
                    699:     // Send a "quit" command.
                    700:     fprintf(sndserver, "q\n");
                    701:     fflush(sndserver);
                    702:   }
                    703: #else
                    704:   // Wait till all pending sounds are finished.
                    705:   int done = 0;
                    706:   int i;
                    707:   
                    708: 
                    709:   // FIXME (below).
                    710:   fprintf( stderr, "I_ShutdownSound: NOT finishing pending sounds\n");
                    711:   fflush( stderr );
                    712:   
                    713:   while ( !done )
                    714:   {
                    715:     for( i=0 ; i<8 && !channels[i] ; i++);
                    716:     
                    717:     // FIXME. No proper channel output.
                    718:     //if (i==8)
                    719:     done=1;
                    720:   }
                    721: #ifdef SNDINTR
                    722:   I_SoundDelTimer();
                    723: #endif
                    724:   
                    725:   // Cleaning up -releasing the DSP device.
                    726:   close ( audio_fd );
                    727: #endif
                    728: 
                    729:   // Done.
                    730:   return;
                    731: }
                    732: 
                    733: 
                    734: 
                    735: 
                    736: 
                    737: 
                    738: void
                    739: I_InitSound()
                    740: { 
                    741: #ifdef SNDSERV
                    742:   char buffer[256];
                    743:   
                    744:   if (getenv("DOOMWADDIR"))
                    745:     sprintf(buffer, "%s/%s",
                    746:            getenv("DOOMWADDIR"),
                    747:            sndserver_filename);
                    748:   else
                    749:     sprintf(buffer, "%s", sndserver_filename);
                    750:   
                    751:   // start sound process
                    752:   if ( !access(buffer, X_OK) )
                    753:   {
                    754:     strcat(buffer, " -quiet");
                    755:     sndserver = popen(buffer, "w");
                    756:   }
                    757:   else
                    758:     fprintf(stderr, "Could not start sound server [%s]\n", buffer);
                    759: #else
                    760:     
                    761:   int i;
                    762:   
                    763: #ifdef SNDINTR
                    764:   fprintf( stderr, "I_SoundSetTimer: %d microsecs\n", SOUND_INTERVAL );
                    765:   I_SoundSetTimer( SOUND_INTERVAL );
                    766: #endif
                    767:     
                    768:   // Secure and configure sound device first.
                    769:   fprintf( stderr, "I_InitSound: ");
                    770:   
                    771:   audio_fd = open("/dev/dsp", O_WRONLY);
                    772:   if (audio_fd<0)
                    773:     fprintf(stderr, "Could not open /dev/dsp\n");
                    774:   
                    775:                      
                    776:   i = 11 | (2<<16);                                           
                    777:   myioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &i);
                    778:   myioctl(audio_fd, SNDCTL_DSP_RESET, 0);
                    779:   
                    780:   i=SAMPLERATE;
                    781:   
                    782:   myioctl(audio_fd, SNDCTL_DSP_SPEED, &i);
                    783:   
                    784:   i=1;
                    785:   myioctl(audio_fd, SNDCTL_DSP_STEREO, &i);
                    786:   
                    787:   myioctl(audio_fd, SNDCTL_DSP_GETFMTS, &i);
                    788:   
                    789:   if (i&=AFMT_S16_LE)    
                    790:     myioctl(audio_fd, SNDCTL_DSP_SETFMT, &i);
                    791:   else
                    792:     fprintf(stderr, "Could not play signed 16 data\n");
                    793: 
                    794:   fprintf(stderr, " configured audio device\n" );
                    795: 
                    796:     
                    797:   // Initialize external data (all sounds) at start, keep static.
                    798:   fprintf( stderr, "I_InitSound: ");
                    799:   
                    800:   for (i=1 ; i<NUMSFX ; i++)
                    801:   { 
                    802:     // Alias? Example is the chaingun sound linked to pistol.
                    803:     if (!S_sfx[i].link)
                    804:     {
                    805:       // Load data from WAD file.
                    806:       S_sfx[i].data = getsfx( S_sfx[i].name, &lengths[i] );
                    807:     }  
                    808:     else
                    809:     {
                    810:       // Previously loaded already?
                    811:       S_sfx[i].data = S_sfx[i].link->data;
                    812:       lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)];
                    813:     }
                    814:   }
                    815: 
                    816:   fprintf( stderr, " pre-cached all sound data\n");
                    817:   
                    818:   // Now initialize mixbuffer with zero.
                    819:   for ( i = 0; i< MIXBUFFERSIZE; i++ )
                    820:     mixbuffer[i] = 0;
                    821:   
                    822:   // Finished initialization.
                    823:   fprintf(stderr, "I_InitSound: sound module ready\n");
                    824:     
                    825: #endif
                    826: }
                    827: 
                    828: 
                    829: 
                    830: 
                    831: //
                    832: // MUSIC API.
                    833: // Still no music done.
                    834: // Remains. Dummies.
                    835: //
                    836: void I_InitMusic(void)         { }
                    837: void I_ShutdownMusic(void)     { }
                    838: 
                    839: static int     looping=0;
                    840: static int     musicdies=-1;
                    841: 
                    842: void I_PlaySong(int handle, int looping)
                    843: {
                    844:   // UNUSED.
                    845:   handle = looping = 0;
                    846:   musicdies = gametic + TICRATE*30;
                    847: }
                    848: 
                    849: void I_PauseSong (int handle)
                    850: {
                    851:   // UNUSED.
                    852:   handle = 0;
                    853: }
                    854: 
                    855: void I_ResumeSong (int handle)
                    856: {
                    857:   // UNUSED.
                    858:   handle = 0;
                    859: }
                    860: 
                    861: void I_StopSong(int handle)
                    862: {
                    863:   // UNUSED.
                    864:   handle = 0;
                    865:   
                    866:   looping = 0;
                    867:   musicdies = 0;
                    868: }
                    869: 
                    870: void I_UnRegisterSong(int handle)
                    871: {
                    872:   // UNUSED.
                    873:   handle = 0;
                    874: }
                    875: 
                    876: int I_RegisterSong(void* data)
                    877: {
                    878:   // UNUSED.
                    879:   data = NULL;
                    880:   
                    881:   return 1;
                    882: }
                    883: 
                    884: // Is the song playing?
                    885: int I_QrySongPlaying(int handle)
                    886: {
                    887:   // UNUSED.
                    888:   handle = 0;
                    889:   return looping || musicdies > gametic;
                    890: }
                    891: 
                    892: 
                    893: 
                    894: //
                    895: // Experimental stuff.
                    896: // A Linux timer interrupt, for asynchronous
                    897: //  sound output.
                    898: // I ripped this out of the Timer class in
                    899: //  our Difference Engine, including a few
                    900: //  SUN remains...
                    901: //  
                    902: #ifdef sun
                    903:     typedef     sigset_t        tSigSet;
                    904: #else    
                    905:     typedef     int             tSigSet;
                    906: #endif
                    907: 
                    908: 
                    909: // We might use SIGVTALRM and ITIMER_VIRTUAL, if the process
                    910: //  time independend timer happens to get lost due to heavy load.
                    911: // SIGALRM and ITIMER_REAL doesn't really work well.
                    912: // There are issues with profiling as well.
                    913: static int /*__itimer_which*/  itimer = ITIMER_REAL;
                    914: 
                    915: static int sig = SIGALRM;
                    916: 
                    917: // Interrupt handler.
                    918: void I_HandleSoundTimer( int ignore )
                    919: {
                    920:   // Debug.
                    921:   //fprintf( stderr, "%c", '+' ); fflush( stderr );
                    922:   
                    923:   // Feed sound device if necesary.
                    924:   if ( flag )
                    925:   {
                    926:     // See I_SubmitSound().
                    927:     // Write it to DSP device.
                    928:     write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL);
                    929: 
                    930:     // Reset flag counter.
                    931:     flag = 0;
                    932:   }
                    933:   else
                    934:     return;
                    935:   
                    936:   // UNUSED, but required.
                    937:   ignore = 0;
                    938:   return;
                    939: }
                    940: 
                    941: // Get the interrupt. Set duration in millisecs.
                    942: int I_SoundSetTimer( int duration_of_tick )
                    943: {
                    944:   // Needed for gametick clockwork.
                    945:   struct itimerval    value;
                    946:   struct itimerval    ovalue;
                    947:   struct sigaction    act;
                    948:   struct sigaction    oact;
                    949: 
                    950:   int res;
                    951:   
                    952:   // This sets to SA_ONESHOT and SA_NOMASK, thus we can not use it.
                    953:   //     signal( _sig, handle_SIG_TICK );
                    954:   
                    955:   // Now we have to change this attribute for repeated calls.
                    956:   act.sa_handler = I_HandleSoundTimer;
                    957: #ifndef sun    
                    958:   //ac t.sa_mask = _sig;
                    959: #endif
                    960:   act.sa_flags = SA_RESTART;
                    961:   
                    962:   sigaction( sig, &act, &oact );
                    963: 
                    964:   value.it_interval.tv_sec    = 0;
                    965:   value.it_interval.tv_usec   = duration_of_tick;
                    966:   value.it_value.tv_sec       = 0;
                    967:   value.it_value.tv_usec      = duration_of_tick;
                    968: 
                    969:   // Error is -1.
                    970:   res = setitimer( itimer, &value, &ovalue );
                    971: 
                    972:   // Debug.
                    973:   if ( res == -1 )
                    974:     fprintf( stderr, "I_SoundSetTimer: interrupt n.a.\n");
                    975:   
                    976:   return res;
                    977: }
                    978: 
                    979: 
                    980: // Remove the interrupt. Set duration to zero.
                    981: void I_SoundDelTimer()
                    982: {
                    983:   // Debug.
                    984:   if ( I_SoundSetTimer( 0 ) == -1)
                    985:     fprintf( stderr, "I_SoundDelTimer: failed to remove interrupt. Doh!\n");
                    986: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.