📄 i_sound_sdl.c
字号:
// Emacs style mode select -*- C++ -*- //-----------------------------------------------------------------------------//// $Id: i_sound_sdl.c,v 1.1 2003/09/08 19:41:53 jasonk 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_sdl.c,v $// Revision 1.1 2003/09/08 19:41:53 jasonk// Addition of packages directory and associated files.//// Revision 1.1 2000/12/08 21:07:53 jeffw// nxdoom initial entry -- No nxdoom/Makefile so it won't build automatically////// DESCRIPTION:// System interface for sound.////-----------------------------------------------------------------------------static const charrcsid[] = "$Id: i_sound_sdl.c,v 1.1 2003/09/08 19:41:53 jasonk Exp $";#include <math.h>#include "SDL_audio.h"#include "SDL_mutex.h"#include "SDL_byteorder.h"#include "SDL_version.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"// 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.static int SAMPLECOUNT= 512;#define NUM_CHANNELS 8#define SAMPLERATE 11025 // Hz// The actual lengths of all sound effects.int lengths[NUMSFX];// The actual output device.int audio_fd;// The channel step amount...unsigned int channelstep[NUM_CHANNELS];// ... and a 0.16 bit remainder of last step.unsigned int channelstepremainder[NUM_CHANNELS];// The channel data pointers, start and end.unsigned char* channels[NUM_CHANNELS];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.int channelstart[NUM_CHANNELS];// The sound in channel handles,// determined on registration,// might be used to unregister/stop/modify,// currently unused.int channelhandles[NUM_CHANNELS];// SFX id of the playing sound effect.// Used to catch duplicates (like chainsaw).int channelids[NUM_CHANNELS]; // Pitch to stepping lookup, unused.int steptable[256];// Volume lookups.int vol_lookup[128*256];// Hardware left and right channel volume lookup.int* channelleftvol_lookup[NUM_CHANNELS];int* channelrightvol_lookup[NUM_CHANNELS];//// This function loads the sound data from the WAD lump,// for single sound.//void*getsfx( 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, PU_STATIC ); // 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.//intaddsfx( 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; 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().//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; // 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -