⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i_sound.c

📁 The source code of Doom legacy for windows
💻 C
📖 第 1 页 / 共 2 页
字号:
  }#endif}int I_SoundIsPlaying(int handle){    // Ouch.    // return gametic < handle;#ifndef SNDSERV    int i;    for (i=0; i<cv_numChannels.value; i++)    {      if (channelhandles[i] == handle)        return 1;    }#endif    return 0;}//// This function loops all active (internal) sound//  channels, retrieves a given number of samples//  from the raw sound data, modifies it according//  to the current (internal) channel parameters,//  mixes the per channel samples into the global//  mixbuffer, clamping it to the allowed range,//  and sets up everything for transferring the//  contents of the mixbuffer to the (two)//  hardware channels (left and right, that is).//void I_UpdateSound( void ){  // Debug. Count buffer misses with interrupt.  static int misses = 0;  // Flag. Will be set if the mixing buffer really gets updated.  int updated = 0;    // Mix current sound data.  // Data, from raw sound, for right and left.  register unsigned int sample;  register int          dl;  register int          dr;  unsigned short        sdl;  unsigned short        sdr;    // Pointers in global mixbuffer, left, right, end.  signed short*         leftout;  signed short*         rightout;  signed short*         leftend;  unsigned char*        bothout;          // Step in mixbuffer, left and right, thus two.  int                   step;  // Mixing channel index.  int                   chan;        // Left and right channel    //  are in global mixbuffer, alternating.    leftout = mixbuffer;    rightout = mixbuffer+1;    bothout = (unsigned char *)mixbuffer;    step = 2;    // Determine end, for left channel only    //  (right channel is implicit).    leftend = mixbuffer + SAMPLECOUNT*step;    // Mix sounds into the mixing buffer.    // Loop over step*SAMPLECOUNT.    while (leftout != leftend)    {        // Reset left/right value.         dl = 0;        dr = 0;        // Love thy L2 chache - made this a loop.        // Now more channels could be set at compile time        //  as well. Thus loop those  channels.        for ( chan = 0; chan < cv_numChannels.value; chan++ )        {            // Check channel, if active.            if (channels[ chan ])            {                // we are updating the mixer buffer, set flag                updated++;                // Get the raw data from the channel.                 sample = *channels[ chan ];                // Add left and right part                //  for this channel (sound)                //  to the current data.                // Adjust volume accordingly.                dl += channelleftvol_lookup[ chan ][sample];                dr += channelrightvol_lookup[ chan ][sample];                // Increment index ???                channelstepremainder[ chan ] += channelstep[ chan ];                // MSB is next sample???                channels[ chan ] += channelstepremainder[ chan ] >> 16;                // Limit to LSB???                channelstepremainder[ chan ] &= 65536-1;                // Check whether we are done.                if (channels[ chan ] >= channelsend[ chan ])                    channels[ chan ] = 0;            }        }                // Clamp to range. Left hardware channel.        // Has been char instead of short.        // if (dl > 127) *leftout = 127;        // else if (dl < -128) *leftout = -128;        // else *leftout = dl;        if (!audio_8bit_flag)        {            if (dl > 0x7fff)                *leftout = 0x7fff;            else if (dl < -0x8000)                *leftout = -0x8000;            else                *leftout = dl;            // Same for right hardware channel.            if (dr > 0x7fff)                *rightout = 0x7fff;            else if (dr < -0x8000)                *rightout = -0x8000;            else                *rightout = dr;        }        else        {            if (dl > 0x7fff)                dl = 0x7fff;            else if (dl < -0x8000)                dl = -0x8000;            sdl = dl ^ 0xfff8000;            if (dr > 0x7fff)                dr = 0x7fff;            else if (dr < -0x8000)                dr = -0x8000;            sdr = dr ^ 0xfff8000;                    *bothout++ = (((sdr + sdl) / 2) >> 8);        }        // Increment current pointers in mixbuffer.        leftout += step;        rightout += step;    }    if (updated)    {        // Debug check.        if ( flag )        {          misses += flag;          flag = 0;        }        if ( misses > 10 )        {          fprintf( stderr, "I_SoundUpdate: missed 10 buffer writes\n");          misses = 0;        }            // Increment flag for update.        flag++;    }}// // This is used to write out the mixbuffer//  during each game loop update.//voidI_SubmitSound(void){  // Write it to DSP device.  if (flag)  {    if (!audio_8bit_flag)      write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL);    else      write(audio_fd, mixbuffer, SAMPLECOUNT);    flag = 0;  }}voidI_UpdateSoundParams( int   handle,  int   vol,  int   sep,  int   pitch){  // I fail too see that this is used.  // Would be using the handle to identify  //  on which channel the sound might be active,  //  and resetting the channel parameters.  // UNUSED.  handle = vol = sep = pitch = 0;}void I_ShutdownSound(void){    #ifdef SNDSERV  if (sndserver)  {    // Send a "quit" command.    fputc('q',sndserver);    fflush(sndserver);  }#else  // Wait till all pending sounds are finished.  int done = 0;  int i;    if (nosound)    return;#ifdef SNDINTR  I_SoundDelTimer();#endif    while ( !done )  {    for( i=0 ; i<cv_numChannels.value && !channels[i] ; i++)      ;    if (i==cv_numChannels.value)      done++;    else    {        I_UpdateSound();        I_SubmitSound();    }  }  // Cleaning up -releasing the DSP device.  close ( audio_fd );#endif  // Done.  return;}voidI_StartupSound(){ #ifdef SNDSERV  char buffer[2048];  char *fn_snd;    if (nosound)    return;  fn_snd = searchpath(sndserver_cmd.string);    // start sound process  if ( !access(fn_snd, X_OK) )  {    sprintf(buffer, "%s %s", fn_snd, sndserver_arg.string);    sndserver = popen(buffer, "w");  }  else    fprintf(stderr, "Could not start sound server [%s]\n", fn_snd);#else      int i, j;  if (nosound)    return;  // Secure and configure sound device first.  fprintf( stderr, "I_InitSound: ");    audio_fd = open("/dev/dsp", O_WRONLY);  if (audio_fd<0)  {    fprintf(stderr, "Could not open /dev/dsp\n");    nosound++;    return;  }                     #ifndef OLD_SOUND_DRIVER  myioctl(audio_fd, SNDCTL_DSP_RESET, 0);#endif  if (getenv("DOOM_SOUND_SAMPLEBITS") == NULL)  {    myioctl(audio_fd, SNDCTL_DSP_GETFMTS, &i);    if (i&=AFMT_S16_LE)        {      j = 11 | (2<<16);                                                 myioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &j);      myioctl(audio_fd, SNDCTL_DSP_SETFMT, &i);      i=1;      myioctl(audio_fd, SNDCTL_DSP_STEREO, &i);    }    else    {      i = 10 | (2<<16);                                                 myioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &i);      i=AFMT_U8;      myioctl(audio_fd, SNDCTL_DSP_SETFMT, &i);      audio_8bit_flag++;    }  }  else  {    i = 10 | (2<<16);                                               myioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &i);    i=AFMT_U8;    myioctl(audio_fd, SNDCTL_DSP_SETFMT, &i);    audio_8bit_flag++;  }    i=SAMPLERATE;  myioctl(audio_fd, SNDCTL_DSP_SPEED, &i);    fprintf(stderr, " configured %dbit audio device\n",          (audio_8bit_flag) ? 8 : 16 );#ifdef SNDINTR  fprintf( stderr, "I_SoundSetTimer: %d microsecs\n", SOUND_INTERVAL );  I_SoundSetTimer( SOUND_INTERVAL );#endif      // Initialize external data (all sounds) at start, keep static.  fprintf( stderr, "I_InitSound: ");  // Do we have a sound lump for the chaingun?  if (W_CheckNumForName("dschgun") == -1)  {    // No, so link it to the pistol sound    //S_sfx[sfx_chgun].link = &S_sfx[sfx_pistol];    //S_sfx[sfx_chgun].pitch = 150;    //S_sfx[sfx_chgun].volume = 0;    //S_sfx[sfx_chgun].data = 0;    fprintf(stderr, "linking chaingun sound to pistol sound,");  }  else  {    fprintf(stderr, "found chaingun sound,");  }    //for (i=1 ; i<NUMSFX ; i++)  //{   //  lengths[i] = 0;  //}  fprintf( stderr, " pre-cached all sound data\n");    // Now initialize mixbuffer with zero.  for ( i = 0; i< MIXBUFFERSIZE; i++ )    mixbuffer[i] = 0;    // Finished initialization.  fprintf(stderr, "I_InitSound: sound module ready\n");    #endif}//// MUSIC API.// Music done now, we'll use Michael Heasley's musserver.//void I_InitMusic(void){#ifdef MUSSERV  char buffer[2048];  char *fn_mus;#endif  if (nomusic)    return;#ifdef MUSSERV  fn_mus = searchpath(musserver_cmd.string);  // now try to start the music server process  if (!access(fn_mus, X_OK)) {    int p;    sprintf(buffer, "%s %s", fn_mus, musserver_arg.string);    // check for a specific iwad file    if ( (p = M_CheckParm ("-iwad")) && p < myargc-1 ) {      sprintf(buffer, "%s -i %s", buffer, myargv[p+1]);    }      fprintf(stderr, "Starting music server [%s]\n", buffer);    musserver = popen(buffer, "w");    msg_id = msgget(53075, IPC_CREAT | 0777);  }  else    fprintf(stderr, "Could not start music server [%s]\n", fn_mus);#endif}void I_ShutdownMusic(void){  if (nomusic)    return;#ifdef MUSSERV  if (musserver)  {    // send a "quit" command.    if (msg_id != -1)      msgctl(msg_id, IPC_RMID, (struct msqid_ds *) NULL);  }#endif}static int      looping=0;static int      musicdies=-1;void I_PlaySong(int handle, int looping){  // UNUSED.  handle = looping = 0;  musicdies = gametic + TICRATE*30;  if (nomusic)    return;}void I_PauseSong (int handle){  // UNUSED.  handle = 0;  if (nomusic)    return;}void I_ResumeSong (int handle){  // UNUSED.  handle = 0;  if (nomusic)    return;}void I_StopSong(int handle){  // UNUSED.  handle = 0;  looping = 0;  musicdies = 0;  if (nomusic)    return;}void I_UnRegisterSong(int handle){  // UNUSED.  handle = 0;}// BP: len is unused but is just to have compatible apiint I_RegisterSong(void* data,int len){#ifdef MUSSERV  struct {        long msg_type;        char msg_text[12];  } msg_buffer;#endif  if (nomusic) {    data = NULL;    return 1;  }#ifdef MUSSERV  if (msg_id != -1) {    msg_buffer.msg_type = 6;    memset(msg_buffer.msg_text, 0, 12);    sprintf(msg_buffer.msg_text, "d_%s", (char *) data);    msgsnd(msg_id, (struct msgbuf *) &msg_buffer, 12, IPC_NOWAIT);  }#else  data = NULL;#endif  return 1;}// Is the song playing?int I_QrySongPlaying(int handle){  // UNUSED.  handle = 0;  return looping || musicdies > gametic;}//// Experimental stuff.// A Linux timer interrupt, for asynchronous//  sound output.// I ripped this out of the Timer class in//  our Difference Engine, including a few//  SUN remains...//  #ifdef sun    typedef     sigset_t        tSigSet;#else        typedef     int             tSigSet;#endif// We might use SIGVTALRM and ITIMER_VIRTUAL, if the process//  time independend timer happens to get lost due to heavy load.// SIGALRM and ITIMER_REAL doesn't really work well.// There are issues with profiling as well.//static int /*__itimer_which*/  itimer = ITIMER_REAL;static int /*__itimer_which*/  itimer = ITIMER_VIRTUAL;//static int sig = SIGALRM;static int sig = SIGVTALRM;// Interrupt handler.void I_HandleSoundTimer( int ignore ){  // Debug.  //fprintf( stderr, "%c", '+' ); fflush( stderr );    // Feed sound device if necesary.  if ( flag )  {    // See I_SubmitSound().    // Write it to DSP device.    if (!audio_8bit_flag)        write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL);    else        write(audio_fd, mixbuffer, SAMPLECOUNT);    // Reset flag counter.    flag = 0;  }  else    return;    // UNUSED, but required.  ignore = 0;  return;}// Get the interrupt. Set duration in millisecs.int I_SoundSetTimer( int duration_of_tick ){  // Needed for gametick clockwork.  struct itimerval    value;  struct itimerval    ovalue;  struct sigaction    act;  struct sigaction    oact;  int res;    // This sets to SA_ONESHOT and SA_NOMASK, thus we can not use it.  //     signal( _sig, handle_SIG_TICK );    // Now we have to change this attribute for repeated calls.  act.sa_handler = I_HandleSoundTimer;#ifndef sun      //ac  t.sa_mask = _sig;#endif  act.sa_flags = SA_RESTART;    sigaction( sig, &act, &oact );  value.it_interval.tv_sec    = 0;  value.it_interval.tv_usec   = duration_of_tick;  value.it_value.tv_sec       = 0;  value.it_value.tv_usec      = duration_of_tick;  // Error is -1.  res = setitimer( itimer, &value, &ovalue );  // Debug.  if ( res == -1 )    fprintf( stderr, "I_SoundSetTimer: interrupt n.a.\n");    return res;}// Remove the interrupt. Set duration to zero.void I_SoundDelTimer(){  // Debug.  if ( I_SoundSetTimer( 0 ) == -1)    fprintf( stderr, "I_SoundDelTimer: failed to remove interrupt. Doh!\n");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -