From 9fa822847de1c2d64b8e2186e9ec74277f28cc16 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Thu, 4 Aug 2005 21:48:32 +0000 Subject: Turn on compiler optimisation and warning options Add SDL_mixer sound code Subversion-branch: /trunk/chocolate-doom Subversion-revision: 39 --- src/i_sound.c | 781 +++++++--------------------------------------------------- 1 file changed, 83 insertions(+), 698 deletions(-) (limited to 'src/i_sound.c') diff --git a/src/i_sound.c b/src/i_sound.c index 82019c0d..ce13778b 100644 --- a/src/i_sound.c +++ b/src/i_sound.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: i_sound.c 23 2005-07-23 21:32:47Z fraggle $ +// $Id: i_sound.c 39 2005-08-04 21:48:32Z fraggle $ // // Copyright(C) 1993-1996 Id Software, Inc. // Copyright(C) 2005 Simon Howard @@ -22,6 +22,10 @@ // 02111-1307, USA. // // $Log$ +// Revision 1.6 2005/08/04 21:48:32 fraggle +// Turn on compiler optimisation and warning options +// Add SDL_mixer sound code +// // Revision 1.5 2005/07/23 21:32:47 fraggle // Add missing errno.h, fix crash on startup when no IWAD present // @@ -44,28 +48,12 @@ //----------------------------------------------------------------------------- static const char -rcsid[] = "$Id: i_sound.c 23 2005-07-23 21:32:47Z fraggle $"; +rcsid[] = "$Id: i_sound.c 39 2005-08-04 21:48:32Z fraggle $"; #include #include -#include -#include - -#include - -#include -#include - -#include -#include -#include - -// Linux voxware output. -#include - -// Timer stuff. Experimental. -#include -#include +#include +#include #include "z_zone.h" @@ -73,332 +61,78 @@ rcsid[] = "$Id: i_sound.c 23 2005-07-23 21:32:47Z fraggle $"; #include "i_sound.h" #include "m_argv.h" #include "m_misc.h" +#include "m_swap.h" #include "w_wad.h" #include "doomdef.h" -// UNIX hack, to be removed. -#ifdef SNDSERV -// Separate sound server process. -FILE* sndserver=0; -char* sndserver_filename = "./sndserver "; -#elif SNDINTR - -// Update all 30 millisecs, approx. 30fps synchronized. -// Linux resolution is allegedly 10 millisecs, -// scale is microseconds. -#define SOUND_INTERVAL 500 - -// Get the interrupt. Set duration in millisecs. -int I_SoundSetTimer( int duration_of_tick ); -void I_SoundDelTimer( void ); -#else -// None? -#endif - - -// A quick hack to establish a protocol between -// synchronous mix buffer updates and asynchronous -// audio writes. Probably redundant with gametic. -static int flag = 0; - -// 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 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 - -// The actual lengths of all sound effects. -int lengths[NUMSFX]; - -// The actual output device. -int audio_fd; - -// The global mixing buffer. -// Basically, samples from all active internal channels -// are modifed and added, and stored in the buffer -// that is submitted to the audio device. -signed short mixbuffer[MIXBUFFERSIZE]; - - -// 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]; - -// Volume lookups. -int vol_lookup[128*256]; - -// Hardware left and right channel volume lookup. -int* channelleftvol_lookup[NUM_CHANNELS]; -int* channelrightvol_lookup[NUM_CHANNELS]; - +static int sound_initialised = 0; +static Mix_Chunk sound_chunks[NUMSFX]; +static byte *expand_sound_data(byte *data, int samplerate, int length) +{ + byte *result = data; + int i; -// -// Safe ioctl, convenience. -// -void -myioctl -( int fd, - int command, - int* arg ) -{ - int rc; - extern int errno; - - rc = ioctl(fd, command, arg); - if (rc < 0) + if (samplerate == 11025) { - fprintf(stderr, "ioctl(dsp,%d,arg) failed\n", command); - fprintf(stderr, "errno=%d\n", errno); - exit(-1); - } -} - - + // need to expand to 2 channels, and expand 8 bit samples to 16 bits + result = Z_Malloc(length * 4, PU_STATIC, NULL); + for (i=0; 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; -} + // need to load the sound + lumpnum = I_GetSfxLumpNum(&S_sfx[sound]); + data = W_CacheLumpNum(lumpnum, PU_STATIC); + samplerate = (data[3] << 8) | data[2]; + length = (data[5] << 8) | data[4]; + sound_chunks[sound].allocated = 1; + sound_chunks[sound].abuf = expand_sound_data(data + 8, samplerate, length); + sound_chunks[sound].alen = (length * 2 * 22050) / samplerate; + sound_chunks[sound].volume = 128; + } + return &sound_chunks[sound]; +} // // SFX API @@ -411,24 +145,6 @@ addsfx // 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; - - // Okay, reset internal mixing channels to zero. - /*for (i=0; i> 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 (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 } @@ -671,8 +254,6 @@ void I_UpdateSound( void ) void I_SubmitSound(void) { - // Write it to DSP device. - write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL); } @@ -684,13 +265,9 @@ I_UpdateSoundParams 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; + Mix_SetPanning(handle, + ((254 - sep) * vol) / 8, + ((sep) * vol) / 8); } @@ -698,41 +275,11 @@ I_UpdateSoundParams void I_ShutdownSound(void) { -#ifdef SNDSERV - if (sndserver) - { - // Send a "quit" command. - fprintf(sndserver, "q\n"); - fflush(sndserver); - } -#else - // Wait till all pending sounds are finished. - int done = 0; - int i; - - - // FIXME (below). - fprintf( stderr, "I_ShutdownSound: NOT finishing pending sounds\n"); - fflush( stderr ); - - while ( !done ) - { - for( i=0 ; i<8 && !channels[i] ; i++); - - // FIXME. No proper channel output. - //if (i==8) - done=1; - } -#ifdef SNDINTR - I_SoundDelTimer(); -#endif - - // Cleaning up -releasing the DSP device. - close ( audio_fd ); -#endif + if (!sound_initialised) + return; - // Done. - return; + Mix_CloseAudio(); + SDL_QuitSubSystem(SDL_INIT_AUDIO); } @@ -743,91 +290,22 @@ void I_ShutdownSound(void) void I_InitSound() { -#ifdef SNDSERV - char buffer[256]; - - if (getenv("DOOMWADDIR")) - sprintf(buffer, "%s/%s", - getenv("DOOMWADDIR"), - sndserver_filename); - else - sprintf(buffer, "%s", sndserver_filename); - - // start sound process - if ( !access(buffer, X_OK) ) - { - strcat(buffer, " -quiet"); - sndserver = popen(buffer, "w"); - } - else - fprintf(stderr, "Could not start sound server [%s]\n", buffer); -#else - - int i; - -#ifdef SNDINTR - fprintf( stderr, "I_SoundSetTimer: %d microsecs\n", SOUND_INTERVAL ); - I_SoundSetTimer( SOUND_INTERVAL ); -#endif - - // 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"); - - - i = 11 | (2<<16); - myioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &i); - myioctl(audio_fd, SNDCTL_DSP_RESET, 0); - - i=SAMPLERATE; - - myioctl(audio_fd, SNDCTL_DSP_SPEED, &i); - - i=1; - myioctl(audio_fd, SNDCTL_DSP_STEREO, &i); - - myioctl(audio_fd, SNDCTL_DSP_GETFMTS, &i); - - if (i&=AFMT_S16_LE) - myioctl(audio_fd, SNDCTL_DSP_SETFMT, &i); - else - fprintf(stderr, "Could not play signed 16 data\n"); - - fprintf(stderr, " configured audio device\n" ); - - - // 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)]; + printf("Unable to set up sound.\n"); + return; } - } - 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"); + if (Mix_OpenAudio(22050, AUDIO_U8, 2, 1024) < 0) + { + printf("Error initialising SDL_mixer: %s\n", SDL_GetError()); + } -#endif + sound_initialised = 1; + + SDL_PauseAudio(0); + + printf("sound started.\n"); } @@ -896,96 +374,3 @@ int I_QrySongPlaying(int handle) -// -// 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 sig = SIGALRM; - -// 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. - write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL); - - // 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"); -} -- cgit v1.2.3