Annotation of doom/i_soorig, revision 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.