2 * $Logfile: /Freespace2/code/Object/ObjectSnd.cpp $
7 * C module for managing object-linked persistant sounds
10 * Revision 1.1 2002/05/03 03:28:10 root
14 * 11 9/08/99 8:56a Mikek
15 * Blast. Suppress a debug warning.
17 * 10 9/08/99 8:56a Mikek
18 * Whoops, broke the build with debug code.
20 * 9 9/08/99 8:42a Mikek
21 * Make flyby sounds a lot easier to trigger. Decrease some thresholds
22 * and remove the dot product check. This is handled by the delta
25 * 8 7/01/99 4:23p Dave
26 * Full support for multiple linked ambient engine sounds. Added "big
29 * 7 7/01/99 11:44a Dave
30 * Updated object sound system to allow multiple obj sounds per ship.
31 * Added hit-by-beam sound. Added killed by beam sound.
33 * 6 6/25/99 3:08p Dave
34 * Multiple flyby sounds.
36 * 5 5/23/99 8:11p Alanl
37 * Added support for EAX
39 * 4 5/18/99 11:50a Andsager
40 * Remove unused object type OBJ_GHOST_SAVE
42 * 3 4/23/99 12:01p Johnson
45 * 2 10/07/98 10:53a Dave
48 * 1 10/07/98 10:50a Dave
50 * 59 5/15/98 5:16p Dave
51 * Fix a standalone resetting bug.Tweaked PXO interface. Display captaincy
52 * status for team vs. team. Put in asserts to check for invalid team vs.
55 * 58 5/07/98 12:24a Hoffoss
56 * Finished up sidewinder force feedback support.
58 * 57 5/06/98 1:29p Dan
59 * AL: allow engine sounds to play polyphonically
61 * 56 5/06/98 10:27a Dan
62 * AL: Fix bug with object sounds and Aureal
64 * 55 4/19/98 9:32p Lawrance
65 * Add support for Shivan flyby sound
67 * 54 4/18/98 9:12p Lawrance
68 * Added Aureal support.
70 * 53 4/12/98 5:31p Lawrance
71 * use timer_get_milliseconds() instead of gettime()
73 * 52 4/08/98 8:33p Lawrance
74 * increase distance at which flyby sound is heard
76 * 51 4/01/98 9:21p John
77 * Made NDEBUG, optimized build with no warnings or errors.
79 * 50 3/21/98 3:36p Lawrance
80 * Don't change frequency unless a threshold change has been reached.
82 * 49 3/19/98 5:34p Lawrance
83 * Only play flyby sound if both ships involved are above a minimum speed
85 * 48 3/18/98 9:49a Lawrance
86 * fix uninitialized data bug
88 * 47 3/17/98 5:55p Lawrance
89 * Support object-linked sounds for asteroids.
91 * 46 3/14/98 4:59p Lawrance
92 * Fix bug with object sounds not getting cleared
94 * 45 2/22/98 2:48p John
95 * More String Externalization Classification
97 * 44 2/20/98 8:32p Lawrance
98 * Add radius parm to sound_play_3d()
100 * 43 2/12/98 11:53p Lawrance
101 * move engine pos closer to center of ship, ensure flyby sounds only play
102 * when flying past a small ship
104 * 42 2/11/98 5:38p Dave
105 * Put in a global inited flag for objsound.
107 * 41 2/11/98 11:30a Dan
108 * AL: fix DirectSound3D bug
110 * 40 2/11/98 10:28a Lawrance
111 * Fix attenuation problems related to engine position.
113 * 39 2/09/98 9:09p Lawrance
114 * ensure we don't get two flyby sounds too close together
116 * 38 2/02/98 8:23p Lawrance
117 * double distance at which a flyby sound is played
119 * 37 1/29/98 10:31a Lawrance
120 * Don't play doppler effect for cruisers and capital ships
122 * 36 1/20/98 10:04a Lawrance
123 * fix volume bug, do obj_snd_do_frame at 10Hz
125 * 35 1/20/98 9:47a Mike
126 * Suppress optimized compiler warnings.
127 * Some secondary weapon work.
129 * 34 1/10/98 1:14p John
130 * Added explanation to debug console commands
132 * 33 12/21/97 4:33p John
133 * Made debug console functions a class that registers itself
134 * automatically, so you don't need to add the function to
135 * debugfunctions.cpp.
137 * 32 11/20/97 6:45p Lawrance
138 * allow two looping debris sounds to play
140 * 31 11/04/97 10:18a Dan
141 * initialize closest_obj to NULL
143 * 30 11/03/97 11:09p Lawrance
144 * Only play flyby sound for ships (ie not debris).
146 * 29 10/26/97 3:22p Lawrance
147 * use volume and not distance when deciding which engine sounds to play
149 * 28 10/22/97 10:37a Johnson
150 * ALAN: ensure that object sounds are only deleted once
152 * 27 10/10/97 7:43p Lawrance
153 * use SF_ENGINES_ON flag
155 * 26 10/06/97 4:13p Lawrance
156 * use engine pos when updating volume for object sounds
158 * 25 10/01/97 5:55p Lawrance
159 * change call to snd_play_3d() to allow for arbitrary listening position
161 * 24 9/18/97 7:58a Lawrance
162 * use rear of ship when deciding where to play the engine sound
164 * 23 9/11/97 5:01p Dave
165 * Minor changes to handle ingame joining/dropping for multiplayer.
167 * 22 9/03/97 5:02p Lawrance
168 * add engine stuttering when a ship is dying
170 * 21 8/29/97 5:04p Dave
171 * Made sure ghost objects are handled correctly.
173 * 20 7/28/97 11:38a Lawrance
174 * let ship engine scale with speed for DirectSound3D engine sounds too
176 * 19 7/27/97 5:14p Lawrance
177 * add afterburners to the player control info
179 * 18 7/14/97 12:04a Lawrance
180 * make Obj_snd_enabled visible
182 * 17 7/09/97 12:07a Mike
183 * Changes in ship_info struct.
185 * 16 7/08/97 11:38a Lawrance
186 * added SIF_BIG_SHIP flag (used for object-linked engine sounds)
188 * 15 6/23/97 10:15a Lawrance
189 * fix bug with object linked sounds not stopping playing sounds
191 * 14 6/19/97 2:05p Lawrance
192 * when stopping a linked sound, stop it right away
194 * 13 6/09/97 11:50p Lawrance
195 * integrating DirectSound3D
197 * 12 6/08/97 5:59p Lawrance
198 * comment out ds3d stuff for now
200 * 11 6/06/97 4:13p Lawrance
201 * use an index instead of a pointer for object-linked sounds
203 * 10 6/05/97 1:37a Lawrance
204 * change to support snd_get_vol_and_pan()
206 * 9 6/05/97 1:07a Lawrance
207 * changes to support sound interface
209 * 8 6/02/97 1:50p Lawrance
210 * supporting integration with Direct3D
212 * 7 5/18/97 2:40p Lawrance
213 * added debug function to toggle doppler effect
215 * 6 5/15/97 9:05a Lawrance
216 * comment out some debugging nprintf()'s
218 * 5 5/14/97 10:47a Lawrance
219 * only play external engine sound for loudest ship
221 * 4 5/09/97 4:33p Lawrance
224 * 3 5/09/97 9:41a Lawrance
227 * 2 5/08/97 4:30p Lawrance
228 * split off object sound stuff into separate file
235 #include "objectsnd.h"
236 #include "linklist.h"
247 // Persistant sounds for objects (pointer to obj_snd is in object struct)
248 typedef struct _obj_snd {
249 _obj_snd *next, *prev;
250 int objnum; // object index of object that contains this sound
251 int id; // Index into Snds[] array
252 int instance; // handle of currently playing sound (a ds3d handle if USES_DS3D flag set)
253 int next_update; // timestamp that marks next allowed vol/pan change
254 float vol; // volume of sound (range: 0.0 -> 1.0)
255 float pan; // pan of sound (range: -1.0 -> 1.0)
256 int freq; // valid range: 100 -> 100000 Hz
258 vector offset; // offset from the center of the object where the sound lives
261 #define VOL_PAN_UPDATE 50 // time in ms to update a persistant sound vol/pan
262 #define MIN_PERSISTANT_VOL 0.10f
263 #define MIN_FORWARD_SPEED 5
264 #define SPEED_SOUND 600.0f // speed of sound in FreeSpace
266 #define MAX_OBJ_SOUNDS_PLAYING 5
267 static int Num_obj_sounds_playing;
269 #define OBJSND_CHANGE_FREQUENCY_THRESHOLD 10
271 static obj_snd obj_snd_list; // head of linked list of object sound structs
272 static int Doppler_enabled = TRUE;
274 #define MAX_OBJ_SNDS 256
275 obj_snd Objsnds[MAX_OBJ_SNDS];
277 int Obj_snd_enabled = TRUE;
278 int Obj_snd_last_update; // timer used to run object sound updates at fixed time intervals
279 int Obj_snd_level_inited=0;
282 #define FLYBY_MIN_DISTANCE 90
283 #define FLYBY_MIN_SPEED 50
284 #define FLYBY_MIN_RELATIVE_SPEED 100
285 #define FLYBY_MIN_NEXT_TIME 1000 // in ms
286 #define FLYBY_MIN_REPEAT_TIME 4000 // in ms
287 int Flyby_next_sound;
288 int Flyby_next_repeat;
289 object *Flyby_last_objp;
291 // return the world pos of the sound source on a ship.
292 void obj_snd_source_pos(vector *sound_pos, obj_snd *osp)
295 object *objp = &Objects[osp->objnum];
297 // get sound pos in world coords
298 vm_vec_unrotate(&offset_world, &osp->offset, &objp->orient);
299 vm_vec_add(sound_pos, &objp->pos, &offset_world);
302 // ---------------------------------------------------------------------------------------
305 // Debug console function for object linked persistant sounds
308 DCF(objsnd, "Persistant sound stuff" )
310 char buf1[16], buf2[64];
314 dc_get_arg(ARG_STRING|ARG_NONE);
316 if ( Dc_arg_type & ARG_NONE ) {
317 if ( Obj_snd_enabled == TRUE ) {
319 Obj_snd_enabled = FALSE;
322 Obj_snd_enabled = TRUE;
325 if ( !stricmp( Dc_arg, "list" )) {
326 for ( osp = GET_FIRST(&obj_snd_list); osp !=END_OF_LIST(&obj_snd_list); osp = GET_NEXT(osp) ) {
328 if ( osp->instance == -1 ) {
330 //sprintf(buf1,"OFF");
335 if ( Objects[osp->objnum].type == OBJ_SHIP ) {
336 sprintf(buf2, Ships[Objects[osp->objnum].instance].ship_name);
338 else if ( Objects[osp->objnum].type == OBJ_DEBRIS ) {
339 sprintf(buf2, "Debris");
342 sprintf(buf2, "Unknown");
348 obj_snd_source_pos(&source_pos, osp);
349 distance = vm_vec_dist_quick( &source_pos, &View_position );
351 dc_printf("Object %d => name: %s vol: %.2f pan: %.2f dist: %.2f status: %s\n", osp->objnum, buf2, osp->vol, osp->pan, distance, buf1);
353 dc_printf("Number object-linked sounds playing: %d\n", Num_obj_sounds_playing);
358 dc_printf ("Usage: objsnd [list]\n");
359 dc_printf ("[list] -- displays status of all objects with linked sounds\n");
360 dc_printf ("with no parameters, object sounds are toggled on/off\n");
365 dc_printf( "Object sounds are: %s\n", (Obj_snd_enabled?"ON":"OFF") );
370 // ---------------------------------------------------------------------------------------
371 // Debug console function for toggling doppler effection on/off
373 DCF_BOOL( doppler, Doppler_enabled )
376 // ---------------------------------------------------------------------------------------
377 // obj_snd_get_slot()
379 // Get a free slot in the Objsnds[] array
381 // returns -1 if no slot is available
382 int obj_snd_get_slot()
386 for ( i = 0; i < MAX_OBJ_SNDS; i++ ) {
387 if ( !(Objsnds[i].flags & OS_USED) )
394 // ---------------------------------------------------------------------------------------
397 // Called once at level start to initialize the persistant object sound system
399 void obj_snd_level_init()
403 list_init(&obj_snd_list);
404 for ( i = 0; i < MAX_OBJ_SNDS; i++ ) {
405 Objsnds[i].flags = 0;
408 Num_obj_sounds_playing = 0;
409 Flyby_next_sound = 1;
410 Flyby_next_repeat = 1;
411 Flyby_last_objp = NULL;
412 Obj_snd_last_update=0;
414 Obj_snd_level_inited=1;
418 // ---------------------------------------------------------------------------------------
421 // Stop a persistant sound from playing.
423 // parameters: objp => pointer to object that sound is to be stopped for
426 void obj_snd_stop(object *objp, int index)
432 if(index >= MAX_OBJECT_SOUNDS){
437 // if index is -1, kill all sounds for this guy
439 // kill all sounds for this guy
440 for(idx=0; idx<MAX_OBJECT_SOUNDS; idx++){
441 if ( objp->objsnd_num[idx] == -1 ){
445 osp = &Objsnds[objp->objsnd_num[idx]];
447 if ( osp->instance != -1 ) {
448 snd_stop(osp->instance);
455 Num_obj_sounds_playing--;
456 Assert(Num_obj_sounds_playing >= 0);
466 if ( objp->objsnd_num[index] == -1 ){
470 osp = &Objsnds[objp->objsnd_num[index]];
472 if ( osp->instance != -1 ) {
473 snd_stop(osp->instance);
480 Num_obj_sounds_playing--;
481 Assert(Num_obj_sounds_playing >= 0);
492 // ---------------------------------------------------------------------------------------
493 // obj_snd_stop_all()
495 // Stop all object-linked persistant sounds from playing
498 void obj_snd_stop_all()
502 for ( A = GET_FIRST(&obj_used_list); A !=END_OF_LIST(&obj_used_list); A = GET_NEXT(A) ) {
509 // ---------------------------------------------------------------------------------------
510 // obj_snd_get_freq()
512 // Calculate the frequency of a sound to be played, based on the relative velocities
513 // of the source and observor
515 // returns: frequency of the sound
517 int obj_snd_get_freq(int source_freq, object* source, object* observor, vector *source_pos)
519 vector v_os, v_so; // os == observor to source, so == source to observor
522 vm_vec_normalized_dir(&v_os, source_pos, &observor->pos);
523 vm_vec_normalized_dir(&v_so, &observor->pos, source_pos);
525 vo = vm_vec_dotprod(&v_os, &observor->phys_info.vel);
526 vs = vm_vec_dotprod(&v_so, &source->phys_info.vel);
528 freq = source_freq * ( (SPEED_SOUND + vo) / (SPEED_SOUND - vs) );
533 // ---------------------------------------------------------------------------------------
534 // obj_snd_stop_lowest_vol()
536 // Stop a playing object sound, if it is quieter than sound at new_distance
538 // input: new_vol => volume of requested sound to play
540 // returns: TRUE => A sound was stopped
541 // FALSE => A sound was not stopped
543 int obj_snd_stop_lowest_vol(float new_vol)
547 obj_snd *lowest_vol_osp = NULL;
549 int obj_snd_index = -1;
552 lowest_vol = 1000.0f;
553 for ( osp = GET_FIRST(&obj_snd_list); osp !=END_OF_LIST(&obj_snd_list); osp = GET_NEXT(osp) ) {
554 Assert(osp->objnum != -1);
555 objp = &Objects[osp->objnum];
557 if ( (osp->instance != -1) && (osp->vol < lowest_vol) ) {
558 lowest_vol = osp->vol;
559 lowest_vol_osp = osp;
563 Assert(lowest_vol_osp != NULL);
564 objp = &Objects[lowest_vol_osp->objnum];
566 if ( (lowest_vol < new_vol) && (objp != NULL) ) {
567 // determine what index in this guy the sound is
568 for(idx=0; idx<MAX_OBJECT_SOUNDS; idx++){
569 if(objp->objsnd_num[idx] == (lowest_vol_osp - Objsnds)){
575 if((obj_snd_index == -1) || (obj_snd_index >= MAX_OBJECT_SOUNDS)){
578 obj_snd_stop(objp, obj_snd_index);
587 //int Debug_1 = 0, Debug_2 = 0;
589 // ---------------------------------------------------------------------------------------
590 // maybe_play_flyby_snd()
592 // Based on how close the object is to the player ship (and relative speed), maybe
593 // play a flyby sound. Only play flyby sound for OBJ_SHIP objects.
595 // NOTE: global data Flyby_last_objp, Flyby_next_sound, Flyby_next_repeat are
598 void maybe_play_flyby_snd(float closest_dist, object *closest_objp)
600 if ( closest_objp == NULL || closest_objp->type != OBJ_SHIP ) {
601 goto play_no_flyby_sound;
604 if ( closest_dist < FLYBY_MIN_DISTANCE ) {
605 float relative_speed;
607 vm_vec_sub(&diff, &Player_obj->phys_info.vel, &closest_objp->phys_info.vel);
610 relative_speed = vm_vec_mag_quick(&diff);
611 if ( relative_speed > FLYBY_MIN_RELATIVE_SPEED ) {
612 if ( timestamp_elapsed(Flyby_next_sound) ) {
614 if ( closest_objp == Flyby_last_objp ) {
615 if ( timestamp_elapsed(Flyby_next_repeat) ) {
616 Flyby_next_repeat = timestamp(FLYBY_MIN_REPEAT_TIME);
619 goto play_no_flyby_sound;
622 Assert(closest_objp->type == OBJ_SHIP);
623 if(closest_objp->type != OBJ_SHIP){
627 // pick a random species-based sound
628 ship_info *sip = &Ship_info[Ships[closest_objp->instance].ship_info_index];
629 int species = SPECIES_TERRAN;
630 if((sip->species >= 0) && (sip->species < MAX_SPECIES_NAMES)){
631 species = sip->species;
633 int ship_size = 0; // fighter
634 if(sip->flags & SIF_BOMBER){
639 snd_play_3d(&Snds_flyby[species][ship_size], &closest_objp->pos, &View_position);
640 //snd_play_3d(&Snds_flyby[Debug_1][Debug_2], &closest_objp->pos, &View_position);
642 //float dist = vm_vec_dist(&closest_objp->pos, &View_position);
643 //nprintf(("AI", "Frame %i: Playing flyby sound, species = %i, size = %i, dist = %7.3f\n", Framecount, species, ship_size, dist));
644 // nprintf(("AI", "Frame %i: Playing flyby sound, species = %i, size = %i, dist = %7.3f\n", Framecount, Debug_1, Debug_2, dist));
645 //Debug_1 = (Debug_1+1)%3;
646 //Debug_2 = (Debug_2+1)%2;
648 joy_ff_fly_by(100 - (int) (100.0f * closest_dist / FLYBY_MIN_DISTANCE));
650 Flyby_next_sound = timestamp(FLYBY_MIN_NEXT_TIME);
651 Flyby_last_objp = closest_objp;
660 // ---------------------------------------------------------------------------------------
661 // obj_snd_do_frame()
663 // Called once per frame to process the persistant sound objects
665 void obj_snd_do_frame()
667 float closest_dist, distance, speed_vol_multiplier, percent_max;
669 object *objp, *closest_objp;
672 int channel, go_ahead_flag;
676 if ( Obj_snd_enabled == FALSE )
679 int now = timer_get_milliseconds();
680 if ( (now - Obj_snd_last_update) > 100 ) {
681 Obj_snd_last_update=now;
686 closest_dist = 1000000.0f;
689 for ( osp = GET_FIRST(&obj_snd_list); osp !=END_OF_LIST(&obj_snd_list); osp = GET_NEXT(osp) ) {
691 objp = &Objects[osp->objnum];
692 if ( Player_obj == objp ) {
698 obj_snd_source_pos(&source_pos, osp);
699 distance = vm_vec_dist_quick( &source_pos, &View_position );
701 // how much extra distance do we add before attentuation?
703 if(osp->flags & OS_MAIN){
704 add_distance = objp->radius;
707 distance -= add_distance;
708 if ( distance < 0 ) {
712 // save closest distance (used for flyby sound) if this is a small ship
713 if ( (objp->type == OBJ_SHIP) && (distance < closest_dist) ) {
714 if ( Ship_info[Ships[objp->instance].ship_info_index].flags & SIF_SMALL_SHIP ) {
715 closest_dist = distance;
720 // If the object is a ship, we don't want to start the engine sound unless the ship is
721 // moving (unless flag SIF_BIG_SHIP is set)
722 speed_vol_multiplier = 1.0f;
723 if ( objp->type == OBJ_SHIP ) {
724 if ( !(Ship_info[Ships[objp->instance].ship_info_index].flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)) ) {
725 if ( objp->phys_info.max_vel.z <= 0 ) {
729 percent_max = objp->phys_info.fspeed / objp->phys_info.max_vel.z;
731 if ( percent_max >= 0.5 )
732 speed_vol_multiplier = 1.0f;
734 speed_vol_multiplier = 0.5f + (percent_max); // linear interp: 0.5->1.0 when 0.0->0.5
739 go_ahead_flag = TRUE;
740 float max_vol,new_vol;
741 if ( osp->instance == -1 ) {
742 if ( distance < Snds[osp->id].max ) {
743 max_vol = Snds[osp->id].default_volume;
744 if ( distance <= Snds[osp->id].min ) {
748 new_vol = max_vol - (distance - Snds[osp->id].min) * max_vol / (Snds[osp->id].max - Snds[osp->id].min);
751 if ( new_vol < 0.1 ) {
755 switch( objp->type ) {
759 if ( Num_obj_sounds_playing >= MAX_OBJ_SOUNDS_PLAYING ) {
760 go_ahead_flag = obj_snd_stop_lowest_vol(new_vol);
769 if ( go_ahead_flag ) {
773 if ( ds_using_ds3d() ) {
774 osp->instance = snd_play_3d(gs, &source_pos, &View_position, add_distance, &objp->phys_info.vel, 1, 1.0f, SND_PRIORITY_TRIPLE_INSTANCE);
775 if ( osp->instance != -1 ) {
776 Num_obj_sounds_playing++;
780 snd_get_3d_vol_and_pan(gs, &source_pos, &osp->vol, &osp->pan, add_distance);
781 osp->instance = snd_play_looping( gs, osp->pan, 0, 0, (osp->vol*speed_vol_multiplier)/gs->default_volume, SND_PRIORITY_TRIPLE_INSTANCE );
782 if ( osp->instance != -1 ) {
783 osp->freq = snd_get_pitch(osp->instance);
784 Num_obj_sounds_playing++;
789 Assert(Num_obj_sounds_playing <= MAX_OBJ_SOUNDS_PLAYING);
791 } // end if ( distance < Snds[osp->id].max )
792 } // if ( osp->instance == -1 )
794 if ( distance > Snds[osp->id].max ) {
795 int sound_index = -1;
798 // determine which sound index it is for this guy
799 for(idx=0; idx<MAX_OBJECT_SOUNDS; idx++){
800 if(objp->objsnd_num[idx] == (osp - Objsnds)){
806 Assert(sound_index != -1);
807 obj_snd_stop(objp, sound_index); // currently playing sound has gone past maximum
811 if ( osp->instance == -1 )
815 if ( objp->type == OBJ_SHIP )
816 sp = &Ships[objp->instance];
822 if (ds_using_ds3d()) {
823 channel = ds_get_channel(osp->instance);
824 // for DirectSound3D sounds, re-establish the maximum speed based on the
825 // speed_vol_multiplier
826 if ( sp == NULL || ( (sp != NULL) && (sp->flags & SF_ENGINES_ON) ) ) {
827 snd_set_volume( osp->instance, gs->default_volume*speed_vol_multiplier );
830 // engine sound is disabled
831 snd_set_volume( osp->instance, 0.0f );
835 vel = &objp->phys_info.vel;
837 // Don't play doppler effect for cruisers or captials
839 if ( ship_get_SIF(sp) & (SIF_BIG_SHIP | SIF_HUGE_SHIP) ) {
844 ds3d_update_buffer(channel, i2fl(gs->min), i2fl(gs->max), &source_pos, vel);
845 snd_get_3d_vol_and_pan(gs, &source_pos, &osp->vol, &osp->pan, add_distance);
848 if ( sp == NULL || (sp != NULL && (sp->flags & SF_ENGINES_ON) ) ) {
849 snd_get_3d_vol_and_pan(gs, &source_pos, &osp->vol, &osp->pan, add_distance);
850 snd_set_volume( osp->instance, osp->vol*speed_vol_multiplier );
851 snd_set_pan( osp->instance, osp->pan );
852 // Don't play doppler effect for cruisers or captials
853 if ( objp->type == OBJ_SHIP && Doppler_enabled == TRUE ) {
854 if ( !(ship_get_SIF(sp) & (SIF_BIG_SHIP | SIF_HUGE_SHIP)) ) {
856 // calc doppler effect
857 new_freq = obj_snd_get_freq(osp->freq, objp, Player_obj, &source_pos);
858 if ( abs(new_freq - osp->freq) > OBJSND_CHANGE_FREQUENCY_THRESHOLD ) {
859 snd_set_pitch( osp->instance, new_freq);
865 snd_set_volume( osp->instance, 0.0f );
870 // see if we want to play a flyby sound
871 maybe_play_flyby_snd(closest_dist, closest_objp);
874 // ---------------------------------------------------------------------------------------
877 // Assign a persistant sound to an object.
879 // parameters: objnum => index of object that sound is being assigned to
880 // i => Index into Snds[] array
881 // fname => filename of sound to play ( so DS3D can load the sound )
883 // returns: -1 => sound could not be assigned (possible, since only MAX_OBJECT_SOUNDS persistant
884 // sound can be assigned per object).
885 // 0 => sound was successfully assigned
887 int obj_snd_assign(int objnum, int i, vector *pos, int main)
891 int idx, sound_index;
893 objp = &Objects[objnum];
895 if ( Obj_snd_enabled == FALSE )
898 // try and find a valid objsound index
900 for(idx=0; idx<MAX_OBJECT_SOUNDS; idx++){
901 if(objp->objsnd_num[idx] == -1){
908 if ( sound_index == -1 ){
912 objp->objsnd_num[sound_index] = (short)obj_snd_get_slot();
913 if ( objp->objsnd_num[sound_index] == -1 ) {
914 nprintf(("Sound", "SOUND ==> No free object-linked sounds left\n"));
917 snd = &Objsnds[objp->objsnd_num[sound_index]];
918 snd->flags = OS_USED;
921 snd->flags |= OS_MAIN;
931 snd->objnum = OBJ_INDEX(objp);
932 snd->next_update = 1;
934 // vm_vec_sub(&snd->offset, pos, &objp->pos);
936 // add objp to the obj_snd_list
937 list_append( &obj_snd_list, snd );
943 // ---------------------------------------------------------------------------------------
946 // Remove a persistant sound that has been assigned to an object.
948 // parameters: objnum => index of object that sound is being removed from.
951 void obj_snd_delete(int objnum, int sndnum)
957 Assert(objnum >= 0 && objnum < MAX_OBJECTS);
958 objp = &Objects[objnum];
960 // delete all object sounds for this guy
961 for(idx=0; idx<MAX_OBJECT_SOUNDS; idx++){
963 if ( objp->objsnd_num[idx] == -1 ){
967 osp = &Objsnds[objp->objsnd_num[idx]];
969 // if we're just deleting a specific sound type
970 // and this is not one of them. skip it.
971 if((sndnum != -1) && (osp->id != sndnum)){
975 obj_snd_stop(objp, -1);
977 // remove objp from the obj_snd_list
978 list_remove( &obj_snd_list, osp );
982 objp->objsnd_num[idx] = -1;
986 // ---------------------------------------------------------------------------------------
987 // obj_snd_delete_all()
989 // Remove all persistant sounds
991 void obj_snd_delete_all()
996 osp = GET_FIRST(&obj_snd_list);
997 while( (osp != NULL) && (osp !=END_OF_LIST(&obj_snd_list)) ) {
998 temp = GET_NEXT(osp);
999 Assert( osp->objnum != -1 );
1001 obj_snd_delete( osp->objnum );
1008 for(idx=0; idx<MAX_OBJ_SNDS; idx++){
1009 if(Objsnds[idx].flags & OS_USED){
1010 obj_snd_delete(Objsnds[idx].objnum);
1015 // ---------------------------------------------------------------------------------------
1018 // Called once at game close to de-initialize the persistant object sound system
1020 void obj_snd_level_close()
1022 if ( !Obj_snd_level_inited ) {
1025 obj_snd_delete_all();
1026 Obj_snd_level_inited=0;
1029 // ---------------------------------------------------------------------------------------
1030 // obj_snd_is_playing()
1032 // Determines if a given object-linked sound is currently playing
1034 int obj_snd_is_playing(int index)
1041 Assert( index >= 0 && index < MAX_OBJ_SNDS );
1043 osp = &Objsnds[index];
1044 if ( osp->instance == -1 )
1050 // ---------------------------------------------------------------------------------------
1051 // obj_snd_return_instance()
1053 // Returns the sound instance for a given object-linked sound
1055 int obj_snd_return_instance(int index)
1060 Assert( index >= 0 && index < MAX_OBJ_SNDS );
1062 return Objsnds[index].instance;