From 5922475e89dc6ff205949e8a0edbe36d8cb1482a Mon Sep 17 00:00:00 2001 From: zicodxx <> Date: Fri, 6 Oct 2006 16:34:53 +0000 Subject: [PATCH] implemented sound code of d2x --- SConstruct | 2 +- arch/sdl/digi.c | 887 +++++++++++++++--------------------------------- main/digi.h | 29 ++ main/inferno.c | 5 - main/newdemo.c | 82 +++-- main/newdemo.h | 6 +- 6 files changed, 367 insertions(+), 644 deletions(-) diff --git a/SConstruct b/SConstruct index 0f4b146ae..4d3001be3 100755 --- a/SConstruct +++ b/SConstruct @@ -59,7 +59,7 @@ common_sources = [ 'iff/iff.c', 'main/ai.c', 'main/aipath.c', -'main/altsound.c', +'main/digiobj.c', 'main/args.c', 'main/automap.c', 'main/ban.c', diff --git a/arch/sdl/digi.c b/arch/sdl/digi.c index a28343d47..1e5002b36 100755 --- a/arch/sdl/digi.c +++ b/arch/sdl/digi.c @@ -1,24 +1,35 @@ -// SDL digital audio support +/* $Id: digi.c,v 1.1.1.1 2006/03/17 19:53:41 zicodxx Exp $ */ +/* + * + * SDL digital audio support + * + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif #include #include #include #include -#include +#include "types.h" #include "error.h" #include "mono.h" #include "fix.h" #include "vecmat.h" -#include "gr.h" // needed for piggy.h +#include "gr.h" #include "piggy.h" #include "digi.h" #include "sounds.h" #include "wall.h" #include "newdemo.h" #include "kconfig.h" -#include "altsound.h" + +int digi_sample_rate = 11025; //SAMPLE_RATE_11K; //edited 05/17/99 Matt Mueller - added ifndef NO_ASM //added on 980905 by adb to add inline fixmul for mixer on i386 @@ -100,43 +111,6 @@ static const Uint8 mix8[] = 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; -#define SOF_USED 1 // Set if this sample is used -#define SOF_PLAYING 2 // Set if this sample is playing on a channel -#define SOF_LINK_TO_OBJ 4 // Sound is linked to a moving object. If object dies, then finishes play and quits. -#define SOF_LINK_TO_POS 8 // Sound is linked to segment, pos -#define SOF_PLAY_FOREVER 16 // Play forever (or until level is stopped), otherwise plays once - -typedef struct sound_object { - short signature; // A unique signature to this sound - ubyte flags; // Used to tell if this slot is used and/or currently playing, and how long. - fix max_volume; // Max volume that this sound is playing at - fix max_distance; // The max distance that this sound can be heard at... - int volume; // Volume that this sound is playing at - int pan; // Pan value that this sound is playing at - int handle; // What handle this sound is playing on. Valid only if SOF_PLAYING is set. - short soundnum; // The sound number that is playing - union { - struct { - short segnum; // Used if SOF_LINK_TO_POS field is used - short sidenum; - vms_vector position; - }pos; - struct { - short objnum; // Used if SOF_LINK_TO_OBJ field is used - short objsignature; - }obj; - }link; -} sound_object; -#define lp_segnum link.pos.segnum -#define lp_sidenum link.pos.sidenum -#define lp_position link.pos.position - -#define lo_objnum link.obj.objnum -#define lo_objsignature link.obj.objsignature - -#define MAX_SOUND_OBJECTS 16 -sound_object SoundObjects[MAX_SOUND_OBJECTS]; -short next_signature=0; //added/changed on 980905 by adb to make sfx volume work, on 990221 by adb changed F1_0 to F1_0 / 2 #define SOUND_MAX_VOLUME (F1_0 / 2) @@ -144,116 +118,108 @@ short next_signature=0; int digi_volume = SOUND_MAX_VOLUME; //end edit by adb -int digi_lomem = 0; - static int digi_initialised = 0; struct sound_slot { - int soundno; - int playing; // Is there a sample playing on this channel? - int looped; // Play this sample looped? - fix pan; // 0 = far left, 1 = far right - fix volume; // 0 = nothing, 1 = fully on - //changed on 980905 by adb from char * to unsigned char * - unsigned char *samples; - //end changes by adb - unsigned int length; // Length of the sample - unsigned int position; // Position we are at at the moment. + int soundno; + int playing; // Is there a sample playing on this channel? + int looped; // Play this sample looped? + fix pan; // 0 = far left, 1 = far right + fix volume; // 0 = nothing, 1 = fully on + //changed on 980905 by adb from char * to unsigned char * + unsigned char *samples; + //end changes by adb + unsigned int length; // Length of the sample + unsigned int position; // Position we are at at the moment. + int soundobj; // Which soundobject is on this channel + int persistent; // This can't be pre-empted } SoundSlots[MAX_SOUND_SLOTS]; static SDL_AudioSpec WaveSpec; -static int digi_sounds_initialized = 0; -//added on 980905 by adb to add rotating/volume based sound kill system static int digi_max_channels = 16; -static int next_handle = 0; -int SampleHandles[32]; -void reset_sounds_on_channel(int channel); -//end edit by adb -void digi_reset_digi_sounds(void); +static int next_channel = 0; + +void digi_stop_sound(int channel); +int digi_xlat_sound(int soundno); /* Audio mixing callback */ //changed on 980905 by adb to cleanup, add pan support and optimize mixer static void audio_mixcallback(void *userdata, Uint8 *stream, int len) { - Uint8 *streamend = stream + len; - struct sound_slot *sl; - if (!digi_initialised) return; - - for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++) - { - if (sl->playing) - { - Uint8 *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length; - Uint8 *sp = stream; - signed char v; - fix vl, vr; - int x; + Uint8 *streamend = stream + len; + struct sound_slot *sl; - if ((x = sl->pan) & 0x8000) - { - vl = 0x20000 - x * 2; - vr = 0x10000; - } - else - { - vl = 0x10000; - vr = x * 2; - } - vl = fixmul(vl, (x = sl->volume)); - vr = fixmul(vr, x); - while (sp < streamend) - { - if (sldata == slend) - { - if (!sl->looped) - { - sl->playing = 0; - break; - } - sldata = sl->samples; - } - v = *(sldata++) - 0x80; - *(sp) = mix8[ *sp + fixmul(v, vl) + 0x80 ]; sp++; - *(sp) = mix8[ *sp + fixmul(v, vr) + 0x80 ]; sp++; - } - sl->position = sldata - sl->samples; - } - } + if (!digi_initialised) + return; + + memset(stream, 0x80, len); // fix "static" sound bug on Mac OS X + + for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++) { + if (sl->playing) { + Uint8 *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length; + Uint8 *sp = stream, s; + signed char v; + fix vl, vr; + int x; + + if ((x = sl->pan) & 0x8000) { + vl = 0x20000 - x * 2; + vr = 0x10000; + } else { + vl = 0x10000; + vr = x * 2; + } + vl = fixmul(vl, (x = sl->volume)); + vr = fixmul(vr, x); + while (sp < streamend) { + if (sldata == slend) { + if (!sl->looped) { + sl->playing = 0; + break; + } + sldata = sl->samples; + } + v = *(sldata++) - 0x80; + s = *sp; + *(sp++) = mix8[ s + fixmul(v, vl) + 0x80 ]; + s = *sp; + *(sp++) = mix8[ s + fixmul(v, vr) + 0x80 ]; + } + sl->position = sldata - sl->samples; + } + } } //end changes by adb /* Initialise audio devices. */ int digi_init() { - if (SDL_InitSubSystem(SDL_INIT_AUDIO)<0){ - Error("SDL audio initialisation failed: %s.",SDL_GetError()); - } - //added on 980905 by adb to init sound kill system - memset(SampleHandles, 255, sizeof(SampleHandles)); - //end edit by adb - - WaveSpec.freq = 11025; -//added/changed by Sam Lantinga on 12/01/98 for new SDL version - WaveSpec.format = AUDIO_U8; - WaveSpec.channels = 2; -//end this section addition/change - SL - WaveSpec.samples = SOUND_BUFFER_SIZE; - WaveSpec.callback = audio_mixcallback; - - if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) { -//edited on 10/05/98 by Matt Mueller - should keep running, just with no sound. - printf("\nError: Couldn't open audio: %s\n", SDL_GetError()); -//killed exit(2); - return 1; -//end edit -MM - } - SDL_PauseAudio(0); - - atexit(digi_close); - digi_initialised = 1; - return 0; + if (SDL_InitSubSystem(SDL_INIT_AUDIO)<0) { + Error("SDL audio initialisation failed: %s.",SDL_GetError()); + } + + WaveSpec.freq = digi_sample_rate; + //added/changed by Sam Lantinga on 12/01/98 for new SDL version + WaveSpec.format = AUDIO_U8; + WaveSpec.channels = 2; + //end this section addition/change - SL + WaveSpec.samples = SOUND_BUFFER_SIZE; + WaveSpec.callback = audio_mixcallback; + + if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) { + //edited on 10/05/98 by Matt Mueller - should keep running, just with no sound. + Warning("\nError: Couldn't open audio: %s\n", SDL_GetError()); + //killed exit(2); + return 1; + //end edit -MM + } + SDL_PauseAudio(0); + + atexit(digi_close); + digi_initialised = 1; + return 0; } /* Toggle audio */ @@ -262,469 +228,114 @@ void digi_reset() { } /* Shut down audio */ void digi_close() { - if (!digi_initialised) return; - digi_initialised = 0; - SDL_CloseAudio(); -} - -static int get_free_slot() -{ - int i; - for (i=0; i= 0) && (SoundSlots[SampleHandles[next_handle]].playing) ) - { - if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries= digi_max_channels ) - next_handle = 0; - ntries++; - goto TryNextChannel; - } - //mprintf(( 0, "[SS:%d]", next_handle )); - SoundSlots[SampleHandles[next_handle]].playing = 0; - SampleHandles[next_handle] = -1; - } - //end edit by adb - - slot = get_free_slot(); - if (slot<0) return -1; - - SoundSlots[slot].soundno = soundnum; - SoundSlots[slot].samples = Sounddat(soundnum)->data; - SoundSlots[slot].length = Sounddat(soundnum)->length; - SoundSlots[slot].volume = fixmul(digi_volume, volume); - SoundSlots[slot].pan = pan; - SoundSlots[slot].position = 0; - SoundSlots[slot].looped = 0; - SoundSlots[slot].playing = 1; - - //added on 980905 by adb to add sound kill system from original sos digi.c - reset_sounds_on_channel(slot); - SampleHandles[next_handle] = slot; - next_handle++; - if ( next_handle >= digi_max_channels ) - next_handle = 0; - //end edit by adb - - return slot; -} - - //added on 980905 by adb to add sound kill system from original sos digi.c -void reset_sounds_on_channel( int channel ) -{ - int i; - - for (i=0; idata; - SoundSlots[slot].length = Sounddat(SoundObjects[obj].soundnum)->length; - SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume); - SoundSlots[slot].pan = SoundObjects[obj].pan; - SoundSlots[slot].position = 0; - SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER); - SoundSlots[slot].playing = 1; - - SoundObjects[obj].signature = next_signature++; - SoundObjects[obj].handle = slot; - - SoundObjects[obj].flags |= SOF_PLAYING; - //added on 980905 by adb to add sound kill system from original sos digi.c - reset_sounds_on_channel(slot); - //end edit by adb - - return 0; -} - - -// Play the given sound number. -// Volume is max at F1_0. -void digi_play_sample( int soundno, fix max_volume ) -{ -#ifdef NEWDEMO - if ( Newdemo_state == ND_STATE_RECORDING ) - newdemo_record_sound( soundno ); -#endif if (!digi_initialised) return; - - if (digi_xlat_sound(soundno) < 0 ) return; - - digi_start_sound(soundno, max_volume, F0_5); + digi_initialised = 0; +#ifdef __MINGW32__ + SDL_Delay(500); // CloseAudio hangs if it's called too soon after opening? +#endif + SDL_CloseAudio(); } -// Play the given sound number. If the sound is already playing, -// restart it. -void digi_play_sample_once( int soundno, fix max_volume ) +void digi_stop_all_channels() { int i; -#ifdef NEWDEMO - if ( Newdemo_state == ND_STATE_RECORDING ) - newdemo_record_sound( soundno ); -#endif - - if (!digi_initialised) return; - - if (digi_xlat_sound(soundno) < 0 ) return; - - for (i=0; i < MAX_SOUND_SLOTS; i++) - if (SoundSlots[i].soundno == soundno) - SoundSlots[i].playing = 0; - digi_start_sound(soundno, max_volume, F0_5); - + for (i = 0; i < MAX_SOUND_SLOTS; i++) + digi_stop_sound(i); } -void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff + +extern void digi_end_soundobj(int channel); +extern int SoundQ_channel; +extern void SoundQ_end(); +int verify_sound_channel_free(int channel); + +// Volume 0-F1_0 +int digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj) { - no_dups = 1; - -#ifdef NEWDEMO - if ( Newdemo_state == ND_STATE_RECORDING ) { - if ( no_dups ) - newdemo_record_sound_3d_once( soundno, angle, volume ); - else - newdemo_record_sound_3d( soundno, angle, volume ); - } -#endif - if (!digi_initialised) return; - if (digi_xlat_sound(soundno) < 0 ) return; - - if (volume < MIN_VOLUME ) return; - digi_start_sound(soundno, volume, angle); -} - -void digi_get_sound_loc( vms_matrix * listener, vms_vector * listener_pos, int listener_seg, vms_vector * sound_pos, int sound_seg, fix max_volume, int *volume, int *pan, fix max_distance ) -{ - vms_vector vector_to_sound; - fix angle_from_ear, cosang,sinang; - fix distance; - fix path_distance; - - *volume = 0; - *pan = 0; - - max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far. - - // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation. - distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos ); - - if (distance < max_distance ) { - int num_search_segs = f2i(max_distance/20); - if ( num_search_segs < 1 ) num_search_segs = 1; - - path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG ); - if ( path_distance > -1 ) { - *volume = max_volume - fixdiv(path_distance,max_distance); - //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume )); - if (*volume > 0 ) { - angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec); - fix_sincos(angle_from_ear,&sinang,&cosang); - //mprintf( (0, "volume is %.2f\n", f2fl(*volume) )); - if (Config_channels_reversed) cosang *= -1; - *pan = (cosang + F1_0)/2; - } else { - *volume = 0; - } - } - } -} - -int digi_link_sound_to_object2( int soundnum, short objnum, int forever, fix max_volume, fix max_distance ) -{ - int i,volume,pan; - object * objp; - - if ( max_volume < 0 ) return -1; -// if ( max_volume > F1_0 ) max_volume = F1_0; + int i, starting_channel; if (!digi_initialised) return -1; - if (soundnum < 0 ) return -1; - if (Sounddat(soundnum)->data==NULL) { - Int3(); - return -1; - } - if ((objnum<0)||(objnum>Highest_object_index)) - return -1; - if ( !forever ) { - // Hack to keep sounds from building up... - digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance ); - digi_play_sample_3d(soundnum, pan, volume, 0 ); - return -1; - } + if (soundnum < 0) return -1; - for (i=0; iorient, &Viewer->pos, Viewer->segnum, - &objp->pos, objp->segnum, SoundObjects[i].max_volume, - &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); - - if (!forever || SoundObjects[i].volume >= MIN_VOLUME) - digi_start_sound_object(i); - - return SoundObjects[i].signature; -} - -int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume ) -{ return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); } - -int digi_link_sound_to_pos2( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance ) -{ - int i, volume, pan; - - if ( max_volume < 0 ) return -1; -// if ( max_volume > F1_0 ) max_volume = F1_0; - - if (!digi_initialised) return -1; - if (digi_xlat_sound(soundnum) < 0 ) return -1; - if (Sounddat(soundnum)->data==NULL) { - Int3(); - return -1; - } - - if ((segnum<0)||(segnum>Highest_segment_index)) - return -1; - - if ( !forever ) { - // Hack to keep sounds from building up... - digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance ); - digi_play_sample_3d( soundnum, pan, volume, 0 ); - return -1; - } - - for (i=0; i= digi_max_channels) + next_channel = 0; + if (next_channel == starting_channel) + { + mprintf((1, "OUT OF SOUND CHANNELS!!!\n")); + return -1; + } + } + if (SoundSlots[next_channel].playing) + { + SoundSlots[next_channel].playing = 0; + if (SoundSlots[next_channel].soundobj > -1) + { + digi_end_soundobj(SoundSlots[next_channel].soundobj); + } + if (SoundQ_channel == next_channel) + SoundQ_end(); + } + +#ifndef NDEBUG + verify_sound_channel_free(next_channel); +#endif + + SoundSlots[next_channel].soundno = soundnum; + SoundSlots[next_channel].samples = GameSounds[soundnum].data; + SoundSlots[next_channel].length = GameSounds[soundnum].length; + SoundSlots[next_channel].volume = fixmul(digi_volume, volume); + SoundSlots[next_channel].pan = pan; + SoundSlots[next_channel].position = 0; + SoundSlots[next_channel].looped = looping; + SoundSlots[next_channel].playing = 1; + SoundSlots[next_channel].soundobj = soundobj; + SoundSlots[next_channel].persistent = 0; + if ((soundobj > -1) || (looping) || (volume > F1_0)) + SoundSlots[next_channel].persistent = 1; + + i = next_channel; + next_channel++; + if (next_channel >= digi_max_channels) + next_channel = 0; + + return i; +} + +// Returns the channel a sound number is playing on, or +// -1 if none. +int digi_find_channel(int soundno) +{ + if (!digi_initialised) + return -1; + + if (soundno < 0 ) + return -1; + + if (GameSounds[soundno].data == NULL) + { + Int3(); return -1; } - - SoundObjects[i].signature=next_signature++; - SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS; - if ( forever ) - SoundObjects[i].flags |= SOF_PLAY_FOREVER; - SoundObjects[i].lp_segnum = segnum; - SoundObjects[i].lp_sidenum = sidenum; - SoundObjects[i].lp_position = *pos; - SoundObjects[i].soundnum = soundnum; - SoundObjects[i].max_volume = max_volume; - SoundObjects[i].max_distance = max_distance; - SoundObjects[i].volume = 0; - SoundObjects[i].pan = 0; - digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, - &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum, - SoundObjects[i].max_volume, - &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); - - if (!forever || SoundObjects[i].volume >= MIN_VOLUME) - digi_start_sound_object(i); - - return SoundObjects[i].signature; + //FIXME: not implemented + return -1; } -int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume ) -{ - return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 ); -} - -void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum ) -{ - int i,killed; - - if (!digi_initialised) return; - - killed = 0; - - for (i=0; i 1 ) { - mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum )); - } -} - -void digi_kill_sound_linked_to_object( int objnum ) -{ - int i,killed; - - if (!digi_initialised) return; - - killed = 0; - - for (i=0; i 1 ) { - mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum )); - } -} - -void digi_sync_sounds() -{ - int i; - int oldvolume, oldpan; - - if (!digi_initialised) return; - - for (i=0; iorient, &Viewer->pos, Viewer->segnum, - &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum, - SoundObjects[i].max_volume, - &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); - - } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) { - object * objp; - - objp = &Objects[SoundObjects[i].lo_objnum]; - - if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) { - // The object that this is linked to is dead, so just end this sound if it is looping. - if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) { - SoundSlots[SoundObjects[i].handle].playing = 0; - } - SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound - continue; // Go on to next sound... - } else { - digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, - &objp->pos, objp->segnum, SoundObjects[i].max_volume, - &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); - } - } - - if (oldvolume != SoundObjects[i].volume) { - if ( SoundObjects[i].volume < MIN_VOLUME || Function_mode == FMODE_MENU) { - // Sound is too far away, so stop it from playing. - if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) { - SoundSlots[SoundObjects[i].handle].playing = 0; - SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing - } - } else { - if (!(SoundObjects[i].flags & SOF_PLAYING)) { - digi_start_sound_object(i); - } else { - SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0); - } - } - } - - if (oldpan != SoundObjects[i].pan) { - if (SoundObjects[i].flags & SOF_PLAYING) - SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan; - } - } - } -} - -void digi_init_sounds() -{ - int i; - - if (!digi_initialised) return; - - digi_reset_digi_sounds(); - - for (i=0; i (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) ) - digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS); + if (digi_max_channels > MAX_SOUND_SLOTS) + digi_max_channels = MAX_SOUND_SLOTS; if ( !digi_initialised ) return; - digi_reset_digi_sounds(); + digi_stop_all_channels(); } int digi_get_max_channels() { @@ -795,30 +395,91 @@ int digi_get_max_channels() { } // end edit by adb -void digi_reset_digi_sounds() { - int i; +int digi_is_channel_playing(int channel) +{ + if (!digi_initialised) + return 0; - for (i=0; i< MAX_SOUND_SLOTS; i++) - SoundSlots[i].playing=0; - - //added on 980905 by adb to reset sound kill system - memset(SampleHandles, 255, sizeof(SampleHandles)); - next_handle = 0; - //end edit by adb + return SoundSlots[channel].playing; +} + +void digi_set_channel_volume(int channel, int volume) +{ + if (!digi_initialised) + return; + + if (!SoundSlots[channel].playing) + return; + + SoundSlots[channel].volume = fixmuldiv(volume, digi_volume, F1_0); +} + +void digi_set_channel_pan(int channel, int pan) +{ + if (!digi_initialised) + return; + + if (!SoundSlots[channel].playing) + return; + + SoundSlots[channel].pan = pan; +} + +void digi_stop_sound(int channel) +{ + SoundSlots[channel].playing=0; + SoundSlots[channel].soundobj = -1; + SoundSlots[channel].persistent = 0; +} + +void digi_end_sound(int channel) +{ + if (!digi_initialised) + return; + + if (!SoundSlots[channel].playing) + return; + + SoundSlots[channel].soundobj = -1; + SoundSlots[channel].persistent = 0; } +#ifndef _WIN32 // MIDI stuff follows. -//added/killed on 11/25/98 by Matthew Mueller -//void digi_set_midi_volume( int mvolume ) { } -//void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {} -//void digi_stop_current_song() -//{ -//#ifdef HMIPLAY -// char buf[10]; -// -// sprintf(buf,"s"); -// send_ipc(buf); -//#endif -//} -//end this section kill - MM +#ifdef MACINTOSH +void digi_set_midi_volume( int mvolume ) { } +void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {} +#endif +void digi_stop_current_song() +{ +#ifdef HMIPLAY + char buf[10]; + + sprintf(buf,"s"); + send_ipc(buf); +#endif +} +void digi_pause_midi() {} +void digi_resume_midi() {} +#endif + +#ifndef NDEBUG +void digi_debug() +{ + int i; + int n_voices = 0; + + if (!digi_initialised) + return; + + for (i = 0; i < digi_max_channels; i++) + { + if (digi_is_channel_playing(i)) + n_voices++; + } + + mprintf_at((0, 2, 0, "DIGI: Active Sound Channels: %d/%d (HMI says %d/32) ", n_voices, digi_max_channels, -1)); + //mprintf_at((0, 3, 0, "DIGI: Number locked sounds: %d ", digi_total_locks )); +} +#endif diff --git a/main/digi.h b/main/digi.h index 9089ad02f..b47b20e01 100755 --- a/main/digi.h +++ b/main/digi.h @@ -209,5 +209,34 @@ extern int digi_get_max_channels(); extern int digi_lomem; +extern int digi_xlat_sound(int soundno); + +extern void digi_stop_sound( int channel ); + +// Returns the channel a sound number is playing on, or +// -1 if none. +extern int digi_find_channel(int soundno); + +// Volume 0-F1_0 +extern int digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj); + +// Stops all sounds that are playing +void digi_stop_all_channels(); + +extern void digi_end_sound( int channel ); +extern void digi_set_channel_pan( int channel, int pan ); +extern void digi_set_channel_volume( int channel, int volume ); +extern int digi_is_channel_playing(int channel); +extern void digi_pause_midi(); +extern void digi_debug(); +extern void digi_stop_current_song(); + +extern void digi_play_sample_looping( int soundno, fix max_volume,int loop_start, int loop_end ); +extern void digi_change_looping_volume( fix volume ); +extern void digi_stop_looping_sound(); + +// Plays a queued voice sound. +extern void digi_start_sound_queued( short soundnum, fix volume ); + #endif diff --git a/main/inferno.c b/main/inferno.c index e66761784..ad4102138 100755 --- a/main/inferno.c +++ b/main/inferno.c @@ -400,11 +400,6 @@ int main(int argc,char **argv) printf("\n%s\n", TXT_HELP); - if ((t = FindArg( "-altsounds" ))) { - load_alt_sounds(Args[t+1]); - atexit(free_alt_sounds); - } - if ((t = FindArg( "-missiondir" ))) cfile_use_alternate_hogdir(Args[t+1]); else diff --git a/main/newdemo.c b/main/newdemo.c index fe15b72c8..bca6172ff 100755 --- a/main/newdemo.c +++ b/main/newdemo.c @@ -136,6 +136,8 @@ void DoJasonInterpolate (fix recorded_time); #define ND_EVENT_DOOR_OPENING 41 // with segment/side #endif #define ND_EVENT_LASER_LEVEL 42 // with old/new level +#define ND_EVENT_LINK_SOUND_TO_OBJ 43 // record digi_link_sound_to_object3 +#define ND_EVENT_KILL_SOUND_TO_OBJ 44 // record digi_kill_sound_linked_to_object #define NORMAL_PLAYBACK 0 #define SKIP_PLAYBACK 1 @@ -236,6 +238,18 @@ int newdemo_read( void *buffer, int elsize, int nelem ) return num_read; } +int newdemo_find_object( int signature ) +{ + int i; + object * objp; + objp = Objects; + for (i=0; i<=Highest_object_index; i++, objp++ ) { + if ( (objp->type != OBJ_NONE) && (objp->signature == signature)) + return i; + } + return -1; +} + int newdemo_write( void *buffer, int elsize, int nelem ) { int num_written, total_size; @@ -245,7 +259,6 @@ int newdemo_write( void *buffer, int elsize, int nelem ) return 0; //End add -GC - total_size = elsize * nelem; frame_bytes_written += total_size; Newdemo_num_written += total_size; @@ -425,13 +438,13 @@ void nd_read_object(object *obj) * Do render type first, since with render_type == RT_NONE, we * blow by all other object information */ - nd_read_byte(&(obj->render_type)); - nd_read_byte(&(obj->type)); + nd_read_byte((sbyte *)&(obj->render_type)); + nd_read_byte((sbyte *)&(obj->type)); if ((obj->render_type == RT_NONE) && (obj->type != OBJ_CAMERA)) return; - nd_read_byte(&(obj->id)); - nd_read_byte(&(obj->flags)); + nd_read_byte((sbyte *)&(obj->id)); + nd_read_byte((sbyte *)&(obj->flags)); nd_read_short((short *)&(obj->signature)); nd_read_shortpos(obj); @@ -456,7 +469,7 @@ void nd_read_object(object *obj) case OBJ_POWERUP: obj->control_type = CT_POWERUP; - nd_read_byte(&(obj->movement_type)); // might have physics movement + nd_read_byte((sbyte *)&(obj->movement_type)); // might have physics movement obj->size = Powerup_info[obj->id].size; break; @@ -477,8 +490,8 @@ void nd_read_object(object *obj) break; default: - nd_read_byte(&(obj->control_type)); - nd_read_byte(&(obj->movement_type)); + nd_read_byte((sbyte *)&(obj->control_type)); + nd_read_byte((sbyte *)&(obj->movement_type)); nd_read_fix(&(obj->size)); break; } @@ -487,7 +500,7 @@ void nd_read_object(object *obj) if ((obj->type == OBJ_WEAPON) && (obj->render_type == RT_WEAPON_VCLIP)) nd_read_fix(&(obj->lifeleft)); else { - nd_read_byte((ubyte *)&(obj->lifeleft)); + nd_read_byte((sbyte *)&(obj->lifeleft)); obj->lifeleft = (fix)((int)obj->lifeleft << 12); } @@ -913,6 +926,27 @@ void newdemo_record_sound_3d_once( int soundno, int angle, int volume ) { start_time(); } +void newdemo_record_link_sound_to_object3( int soundno, short objnum, fix max_volume, fix max_distance, int loop_start, int loop_end ) +{ + stop_time(); + nd_write_byte( ND_EVENT_LINK_SOUND_TO_OBJ ); + nd_write_int( soundno ); + nd_write_int( Objects[objnum].signature ); + nd_write_int( max_volume ); + nd_write_int( max_distance ); + nd_write_int( loop_start ); + nd_write_int( loop_end ); + start_time(); +} + +void newdemo_record_kill_sound_linked_to_object( int objnum ) +{ + stop_time(); + nd_write_byte( ND_EVENT_KILL_SOUND_TO_OBJ ); + nd_write_int( Objects[objnum].signature ); + start_time(); +} + void newdemo_record_wall_hit_process( int segnum, int side, int damage, int playernum ) { stop_time(); @@ -1256,7 +1290,7 @@ int newdemo_read_demo_start(int rnd_demo) sbyte i, laser_level; char current_mission[9]; - nd_read_byte(&c); + nd_read_byte((sbyte *)&c); if ((c != ND_EVENT_START_DEMO) || nd_bad_read) { newmenu_item m[1]; @@ -1313,7 +1347,7 @@ JasonPlaybackTotal=0; } #else if (Newdemo_game_mode & GM_TEAM) { - nd_read_byte(&(Netgame.team_vector)); + nd_read_byte((sbyte *)&(Netgame.team_vector)); nd_read_string(Netgame.team_name[0]); nd_read_string(Netgame.team_name[1]); } @@ -1376,8 +1410,8 @@ JasonPlaybackTotal=0; nd_recorded_total = 0; nd_playback_total = 0; - nd_read_byte(&energy); - nd_read_byte(&shield); + nd_read_byte((sbyte *)&energy); + nd_read_byte((sbyte *)&shield); nd_read_int((int *)&(Players[Player_num].flags)); if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) { @@ -1463,7 +1497,7 @@ int newdemo_read_frame_information() prev_obj = NULL; while( !done ) { - nd_read_byte(&c); + nd_read_byte((sbyte *)&c); if (nd_bad_read) { done = -1; break; } switch( c ) { @@ -1673,9 +1707,9 @@ int newdemo_read_frame_information() #ifndef SHAREWARE ubyte old_energy; - nd_read_byte(&old_energy); + nd_read_byte((sbyte *)&old_energy); #endif - nd_read_byte(&energy); + nd_read_byte((sbyte *)&energy); if (nd_bad_read) {done = -1; break; } #ifdef SHAREWARE Players[Player_num].energy = i2f(energy); @@ -1695,9 +1729,9 @@ int newdemo_read_frame_information() #ifndef SHAREWARE ubyte old_shield; - nd_read_byte(&old_shield); + nd_read_byte((sbyte *)&old_shield); #endif - nd_read_byte(&shield); + nd_read_byte((sbyte *)&shield); if (nd_bad_read) {done = -1; break; } #ifdef SHAREWARE Players[Player_num].shields = i2f(shield); @@ -1863,9 +1897,9 @@ int newdemo_read_frame_information() ubyte side,cside; nd_read_short(&seg); - nd_read_byte(&side); + nd_read_byte((sbyte *)&side); nd_read_short(&cseg); - nd_read_byte(&cside); + nd_read_byte((sbyte *)&cside); nd_read_short( &tmap ); if ((Newdemo_vcr_state != ND_STATE_PAUSED) && (Newdemo_vcr_state != ND_STATE_REWINDING) && (Newdemo_vcr_state != ND_STATE_ONEFRAMEBACKWARD)) Segments[seg].sides[side].tmap_num = Segments[cseg].sides[cside].tmap_num = tmap; @@ -1877,9 +1911,9 @@ int newdemo_read_frame_information() ubyte side,cside; nd_read_short(&seg); - nd_read_byte(&side); + nd_read_byte((sbyte *)&side); nd_read_short(&cseg); - nd_read_byte(&cside); + nd_read_byte((sbyte *)&cside); nd_read_short( &tmap ); if ((Newdemo_vcr_state != ND_STATE_PAUSED) && (Newdemo_vcr_state != ND_STATE_REWINDING) && (Newdemo_vcr_state != ND_STATE_ONEFRAMEBACKWARD)) { Assert(tmap!=0 && Segments[seg].sides[side].tmap_num2!=0); @@ -2272,8 +2306,8 @@ void newdemo_goto_end() nd_read_short(&bshort); nd_read_int(&bint); - nd_read_byte(&energy); - nd_read_byte(&shield); + nd_read_byte((sbyte *)&energy); + nd_read_byte((sbyte *)&shield); Players[Player_num].energy = i2f(energy); Players[Player_num].shields = i2f(shield); nd_read_int((int *)&(Players[Player_num].flags)); diff --git a/main/newdemo.h b/main/newdemo.h index 8409b856d..72b05a08b 100755 --- a/main/newdemo.h +++ b/main/newdemo.h @@ -262,7 +262,11 @@ extern void newdemo_stop_playback(); extern void newdemo_start_recording(); extern void newdemo_stop_recording(); -extern int newdemo_get_percent_done(); +extern int newdemo_get_percent_done(); + +extern void newdemo_record_link_sound_to_object3( int soundno, short objnum, fix max_volume, fix max_distance, int loop_start, int loop_end ); +extern int newdemo_find_object( int signature ); +extern void newdemo_record_kill_sound_linked_to_object( int objnum ); #endif