diff --git a/linuxdoom-1.10/i_sound.c b/linuxdoom-1.10/i_sound.c index 18d8a55..7bdf6fe 100644 --- a/linuxdoom-1.10/i_sound.c +++ b/linuxdoom-1.10/i_sound.c @@ -1,12 +1,412 @@ #ifdef _WIN32 -char* sndserver_filename = "./sndserver "; + +#define SAMPLECOUNT 512 +#define NUM_CHANNELS 8 +// It is 2 for 16bit, and 2 for two channels. +#define BUFMUL 4 +#define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL) + +#define SAMPLERATE 11025 // Hz +#define SAMPLESIZE 2 // 16bit + +signed short mixbuffer[MIXBUFFERSIZE]; + +int lengths[NUMSFX]; + +// 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]; + +// The channel step amount... +unsigned int channelstep[NUM_CHANNELS]; +// ... and a 0.16 bit remainder of last step. +unsigned int channelstepremainder[NUM_CHANNELS]; + + +// SFX id of the playing sound effect. +// Used to catch duplicates (like chainsaw). +int channelids[NUM_CHANNELS]; + +// Volume lookups. +int vol_lookup[128*256]; + +// Pitch to stepping lookup, unused. +int steptable[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> 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; +} // Init at program start... -void I_InitSound(){} +void I_InitSound(){ + int i; + + // Initialize external data (all sounds) at start, keep static. + fprintf( stderr, "I_InitSound: "); + + for (i=1 ; idata; + lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)]; + } + } + + fprintf( stderr, " pre-cached all sound data\n"); +} + +// +// 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). +// +// This function currently supports only 16bit. +// +void I_UpdateSound( void ) +{ +#ifdef SNDINTR + // Debug. Count buffer misses with interrupt. + static int misses = 0; +#endif + + + // Mix current sound data. + // Data, from raw sound, for right and left. + register unsigned int sample; + register int dl; + register int dr; + + // Pointers in global mixbuffer, left, right, end. + signed short* leftout; + signed short* rightout; + signed short* leftend; + // 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; + 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, + // that is 512 values for two channels. + 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 < NUM_CHANNELS; chan++ ) + { + // Check channel, if active. + if (channels[ chan ]) + { + // 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; + + dl *= 8; + dr *= 8; + + 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; + + // Increment current pointers in mixbuffer. + leftout += step; + rightout += step; + } + +#ifdef SNDINTR + // 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++; +#endif +} -// ... update sound buffer and audio device at runtime... -void I_UpdateSound(void){} void I_SubmitSound(void){} // ... shut down and relase at program termination. @@ -17,22 +417,82 @@ void I_ShutdownSound(void){} // SFX I/O // -// Initialize channels? -void I_SetChannels(){} +// 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