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

📄 i_sound.c

📁 The source code of Doom legacy for windows
💻 C
字号:
// Emacs style mode select   -*- C++ -*-//-----------------------------------------------------------------------------//// $Id: i_sound.c,v 1.7 2001/04/14 14:15:14 metzgermeister Exp $//// Copyright (C) 1993-1996 by id Software, Inc.//// This source is available for distribution and/or modification// only under the terms of the DOOM Source Code License as// published by id Software. All rights reserved.//// The source is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License// for more details.//// $Log: i_sound.c,v $// Revision 1.7  2001/04/14 14:15:14  metzgermeister// fixed bug no sound device//// Revision 1.6  2001/04/09 20:21:56  metzgermeister// dummy for I_FreeSfx//// Revision 1.5  2001/03/25 18:11:24  metzgermeister//   * SDL sound bug with swapped stereo channels fixed//   * separate hw_trick.c now for HW_correctSWTrick(.)//// Revision 1.4  2001/03/09 21:53:56  metzgermeister// *** empty log message ***//// Revision 1.3  2000/11/02 19:49:40  bpereira// no message//// Revision 1.2  2000/09/10 10:56:00  metzgermeister// clean up & made it work again//// Revision 1.1  2000/08/21 21:17:32  metzgermeister// Initial import to CVS////// DESCRIPTION://      System interface for sound.////-----------------------------------------------------------------------------static const charrcsid[] = "$Id: i_sound.c,v 1.7 2001/04/14 14:15:14 metzgermeister Exp $";#include <math.h>#include <SDL/SDL.h>#include <SDL/SDL_audio.h>#include <SDL/SDL_mutex.h>#include <SDL/SDL_byteorder.h>#include <SDL/SDL_version.h>#include <unistd.h>#include "z_zone.h"#include "m_swap.h"#include "i_system.h"#include "i_sound.h"#include "m_argv.h"#include "m_misc.h"#include "w_wad.h"#include "doomdef.h"#include "doomstat.h"#include "s_sound.h"#include "doomtype.h"#include "d_main.h"#include <SDL/SDL_mixer.h>#include "qmus2mid.h"#define W_CacheLumpNum(num) (W_CacheLumpNum)((num),1)#define W_CacheLumpName(name) W_CacheLumpNum (W_GetNumForName(name))#define PIPE_CHECK(fh) if (broken_pipe) { fclose(fh); fh = NULL; broken_pipe = 0; }#define MIDBUFFERSIZE   128*1024// The number of internal mixing channels,//  the samples calculated for each mixing step,//  the size of the 16bit, 2 hardware channel (stereo)//  mixing buffer, and the samplerate of the raw data.// Needed for calling the actual sound output.#define NUM_CHANNELS            8#define SAMPLERATE              11025   // Hzstatic int samplecount = 512;static int              lengths[NUMSFX];                    // The actual lengths of all sound effects.static unsigned int     channelstep[NUM_CHANNELS];          // The channel step amount...static unsigned int     channelstepremainder[NUM_CHANNELS]; // ... and a 0.16 bit remainder of last step.// The channel data pointers, start and end.static unsigned char*   channels[NUM_CHANNELS];static unsigned char*   channelsend[NUM_CHANNELS];// Time/gametic that the channel started playing,//  used to determine oldest, which automatically//  has lowest priority.// In case number of active sounds exceeds//  available channels.static int              channelstart[NUM_CHANNELS];// The sound in channel handles,//  determined on registration,//  might be used to unregister/stop/modify,//  currently unused.static int              channelhandles[NUM_CHANNELS];// SFX id of the playing sound effect.// Used to catch duplicates (like chainsaw).static int              channelids[NUM_CHANNELS];// Pitch to stepping lookup, unused.static int              steptable[256];// Volume lookups.static int              vol_lookup[128*256];// Hardware left and right channel volume lookup.static int*             channelleftvol_lookup[NUM_CHANNELS];static int*             channelrightvol_lookup[NUM_CHANNELS];// Buffer for MIDIstatic char* musicbuffer;// Flags for the -nosound and -nomusic optionsextern boolean nosound;extern boolean nomusic;//// This function loads the sound data from the WAD lump,//  for single sound.//static void* getsfx(const char* sfxname, int* len){    unsigned char*      sfx;    unsigned char*      paddedsfx;    int                 i;    int                 size;    int                 paddedsize;    char                name[20];    int                 sfxlump;    // Get the sound data from the WAD, allocate lump    //  in zone memory.    sprintf(name, "ds%s", sfxname);    // Now, there is a severe problem with the    //  sound handling, in it is not (yet/anymore)    //  gamemode aware. That means, sounds from    //  DOOM II will be requested even with DOOM    //  shareware.    // The sound list is wired into sounds.c,    //  which sets the external variable.    // I do not do runtime patches to that    //  variable. Instead, we will use a    //  default sound for replacement.    if ( W_CheckNumForName(name) == -1 )        sfxlump = W_GetNumForName("dspistol");    else        sfxlump = W_GetNumForName(name);    size = W_LumpLength( sfxlump );    // Debug.    // fprintf( stderr, "." );    //fprintf( stderr, " -loading  %s (lump %d, %d bytes)\n",    //       sfxname, sfxlump, size );    //fflush( stderr );    sfx = (unsigned char*)W_CacheLumpNum(sfxlump);    // Pads the sound effect out to the mixing buffer size.    // The original realloc would interfere with zone memory.    paddedsize = ((size-8 + (samplecount-1)) / samplecount) * samplecount;    // Allocate from zone memory.    paddedsfx = (unsigned char*)Z_Malloc( paddedsize+8, PU_STATIC, 0 );    // ddt: (unsigned char *) realloc(sfx, paddedsize+8);    // This should interfere with zone memory handling,    //  which does not kick in in the soundserver.    // Now copy and pad.    memcpy(  paddedsfx, sfx, size );    for (i=size ; i<paddedsize+8 ; i++)        paddedsfx[i] = 128;    // Remove the cached lump.    Z_Free( sfx );    // Preserve padded length.    *len = paddedsize;    // Return allocated padded data.    return (void *) (paddedsfx + 8);}//// This function adds a sound to the//  list of currently active sounds,//  which is maintained as a given number//  (eight, usually) of internal channels.// Returns a handle.//static int addsfx ( int         sfxid,                    int         volume,                    int         step,                    int         seperation ){    static unsigned short       handlenums = 0;    int         i;    int         rc = -1;    int         oldest = gametic;    int         oldestnum = 0;    int         slot;    int         rightvol;    int         leftvol;    // Chainsaw troubles.    // Play these sound effects only one at a time.    if ( sfxid == sfx_sawup         || sfxid == sfx_sawidl         || sfxid == sfx_sawful         || sfxid == sfx_sawhit         || sfxid == sfx_stnmov         || sfxid == sfx_pistol  )    {        // Loop all channels, check.        for (i=0 ; i<NUM_CHANNELS ; i++)        {            // Active, and using the same SFX?            if ( (channels[i])                 && (channelids[i] == sfxid) )            {                // Reset.                channels[i] = 0;                // We are sure that iff,                //  there will only be one.                break;            }        }    }    // Loop all channels to find oldest SFX.    for (i=0; (i<NUM_CHANNELS) && (channels[i]); i++)    {        if (channelstart[i] < oldest)        {            oldestnum = i;            oldest = channelstart[i];        }    }    // Tales from the cryptic.    // If we found a channel, fine.    // If not, we simply overwrite the first one, 0.    // Probably only happens at startup.    if (i == NUM_CHANNELS)        slot = oldestnum;    else        slot = i;    // Okay, in the less recent channel,    //  we will handle the new SFX.    // Set pointer to raw data.    channels[slot] = (unsigned char *) S_sfx[sfxid].data;    // Set pointer to end of raw data.    channelsend[slot] = channels[slot] + lengths[sfxid];    // Reset current handle number, limited to 0..100.    if (!handlenums)        handlenums = 100;    // Assign current handle number.    // Preserved so sounds could be stopped (unused).    channelhandles[slot] = rc = handlenums++;    // Set stepping???    // Kinda getting the impression this is never used.    channelstep[slot] = step;    // ???    channelstepremainder[slot] = 0;    // Should be gametic, I presume.    channelstart[slot] = gametic;    // Separation, that is, orientation/stereo.    //  range is: 1 - 256    seperation += 1;    // Per left/right channel.    //  x^2 seperation,    //  adjust volume properly.    //    volume *= 8;    // Volume arrives in range 0..255 and it must be in 0..cv_soundvolume...    volume = (volume * cv_soundvolume.value) >> 6;    // Notice : sdldoom replaced all the calls to avoid this conversion    //    fprintf(stderr,"Volume dern : %d\n",volume);    leftvol =        volume - ((volume*seperation*seperation) >> 16); ///(256*256);    seperation = seperation - 257;    rightvol =        volume - ((volume*seperation*seperation) >> 16);    // Sanity check, clamp volume.    if (rightvol < 0 || rightvol > 127)        I_Error("rightvol out of bounds");    if (leftvol < 0 || leftvol > 127)        I_Error("leftvol out of bounds");    // Get the proper lookup table piece    //  for this volume level???    channelleftvol_lookup[slot] = &vol_lookup[leftvol*256];    channelrightvol_lookup[slot] = &vol_lookup[rightvol*256];    // Preserve sound SFX id,    //  e.g. for avoiding duplicates of chainsaw.    channelids[slot] = sfxid;    // You tell me.    return rc;}//// SFX API// Note: this was called by S_Init.// However, whatever they did in the// old DPMS based DOS version, this// were simply dummies in the Linux// version.// See soundserver initdata().//// Well... To keep compatibility with legacy doom, I have to call this in// I_InitSound since it is not called in S_Init... (emanne@absysteme.fr)void I_SetChannels(){    // Init internal lookups (raw data, mixing buffer, channels).    // This function sets up internal lookups used during    //  the mixing process.    int         i;    int         j;    int*        steptablemid = steptable + 128;    if(nosound)        return;  // Okay, reset internal mixing channels to zero.  /*for (i=0; i<NUM_CHANNELS; i++)  {    channels[i] = 0;  }*/  // This table provides step widths for pitch parameters.  // I fail to see that this is currently used.    for (i=-128 ; i<128 ; i++)        steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0);  // Generates volume lookup tables  //  which also turn the unsigned samples  //  into signed samples.    for (i=0 ; i<128 ; i++)        for (j=0 ; j<256 ; j++) {            vol_lookup[i*256+j] = (i*(j-128)*256)/127;            //fprintf(stderr, "vol_lookup[%d*256+%d] = %d\n", i, j, vol_lookup[i*256+j]);        }}void I_SetSfxVolume(int volume){    // Identical to DOS.    // Basically, this should propagate    //  the menu/config file setting    //  to the state variable used in    //  the mixing.    // printf("Setting volume to %d\n",volume);    CV_SetValue(&cv_soundvolume, volume);    //snd_SfxVolume = volume;}//// Retrieve the raw data lump index//  for a given SFX name.//int I_GetSfxLumpNum(sfxinfo_t* sfx){    char namebuf[9];    sprintf(namebuf, "ds%s", sfx->name);    return W_GetNumForName(namebuf);}void* I_GetSfx (sfxinfo_t*  sfx) {    int len;    return getsfx(sfx->name,&len);}// FIXME: dummy for now Apr.9 2001 by Robvoid I_FreeSfx(sfxinfo_t* sfx) {}//// Starting a sound means adding it//  to the current list of active sounds//  in the internal channels.// As the SFX info struct contains//  e.g. a pointer to the raw data,//  it is ignored.// As our sound handling does not handle//  priority, it is ignored.// Pitching (that is, increased speed of playback)//  is set, but currently not used by mixing.//int I_StartSound( int           id,                  int           vol,                  int           sep,                  int           pitch,                  int           priority ){    // UNUSED    priority = 0;    if(nosound)        return 0;    // Debug.    /*  fprintf( stderr, "starting sound %d vol %d sep %d pitch %d priority %d",        id,vol,sep,pitch,priority ); */    // Returns a handle (not used).    SDL_LockAudio();    id = addsfx( id, vol, steptable[pitch], sep );    SDL_UnlockAudio();    //    fprintf( stderr, "/handle is %d\n", id );    return id;}void I_StopSound (int handle){    // You need the handle returned by StartSound.    // Would be looping all channels,    //  tracking down the handle,    //  an setting the channel to zero.  // UNUSED.    handle = 0;}int I_SoundIsPlaying(int handle){    // Ouch.    return gametic < handle;}//// 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 given//  mixing buffer, and clamping it to the allowed//  range.//// This function currently supports only 16bit.//void I_UpdateSound () {    /* Pour une raison que j'ignore, la version SDL n'appelle jamais       ce truc directement. Fonction vide pour garder une compatibilit

⌨️ 快捷键说明

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