4 #include "snd_3dras_typedefs.h"
7 cvar_t bgmvolume = {CVAR_SAVE, "bgmvolume", "1", "volume of background music (such as CD music or replacement files such as sound/cdtracks/track002.ogg)"};
8 cvar_t mastervolume = {CVAR_SAVE, "mastervolume", "1", "master volume"};
9 cvar_t volume = {CVAR_SAVE, "volume", "0.7", "volume of sound effects"};
10 cvar_t snd_staticvolume = {CVAR_SAVE, "snd_staticvolume", "1", "volume of ambient sound effects (such as swampy sounds at the start of e1m2)"};
11 cvar_t snd_initialized = { CVAR_READONLY, "snd_initialized", "0", "indicates the sound subsystem is active"};
12 cvar_t snd_mutewhenidle = {CVAR_SAVE, "snd_mutewhenidle", "1", "whether to disable sound output when game window is inactive"};
13 static cvar_t snd_precache = {0, "snd_precache", "1", "loads sounds before they are used"};
15 static dllhandle_t ras_dll = NULL;
16 // This values is used as a multiple version support check AND to check if the lib has been loaded with success (its 0 if it failed)
19 static mempool_t *snd_mempool;
20 static sfx_t sfx_list ={//This is a header, never contains only useful data, only the first next (makes the code less complex, later)
22 "", //name[MAX_QPATH];
29 static unsigned int channel_id_count=0;
30 static channel_t channel_list={
37 static entnum_t entnum_list={
40 {0.0,0.0,0.0}, //lastloc
41 NULL,// *soundsource;// This is also used to indicate a unused slot (when it's pointing to 0)
49 float listener_location [3];
51 //1 qu = 0.0381 meter aka 38.1 mm
52 //2^17 qu's is the max map size in DP
53 //3DRAS uses atleast 32 bit to store it's locations.
54 //So the smallest possible step is 0.0381*2^17/2^(32)
55 // =~ 1.16 nm so let's pick 2 to be safe
56 static float DP_Ras_UnitSize=(float)2/1000/1000; //2 nm
57 static float DP_Ras_VolumeScale=0.075;
58 //static float QU_Size = 0.0381; //meter
59 //static float DP_QU_Ras_Scale=QU_Size/DP_Ras_UnitSize;
60 static float DP_QU_Ras_Scale=19050;
61 static void* (*ras_delete )(void*);
62 static int (*ras_getversion )();
63 static void* (*ras_soundworld_new )(SampleRate, WaveLength);
64 static void (*ras_soundworld_destroy )(void*);
65 static void (*ras_soundworld_endframe )(void*);
66 static int (*ras_soundworld_beginframe )(void*);
67 static void (*ras_soundworld_setmainlistener )(void*,void*);
68 static void (*ras_soundworld_setscale )(void*,const Scale);
69 static void* (*ras_fileinputwhole_new )(unsigned char*, Index);
70 static void* (*ras_audiodecoderwav_new )(void*, int);
71 static void* (*ras_audiodecoderogg_new )(void*);
72 static void* (*ras_sounddataoneshot_new )(void*,WaveLength,Amount);
73 static void* (*ras_sounddataloop_new )(void*,WaveLength,Amount);
74 static void* (*ras_listener_new )(void*,Location*,Scalar*);
75 static void* (*ras_listener_setlocation )(void*,Location*);
76 static void* (*ras_listener_setrotation )(void*,Scalar *,Scalar*,Scalar*);
77 static void* (*ras_soundsource_new )(void*,SoundVolume,Location*);
78 static int (*ras_soundsource_ended )(void*);
79 static void (*ras_soundsource_setlocation )(void*,Location*);
80 static void* (*ras_soundevent_new )(void*,void*,void*,SoundPower,Ratio);
81 static void (*ras_soundevent_setsoundpower )(void*,SoundPower);
82 static int (*ras_soundevent_ended )(void*);
83 static int (*ras_setcoordinatesystem )(Location*,Location*,Location*);
84 static int (*ras_testrotation )(Scalar *,Scalar *,Scalar *);
86 // #define RAS_PRINT //Comment out for to not print extra crap.
88 static dllfunction_t ras_funcs[] =
90 {"Delete" ,(void**) &ras_delete },
91 {"SetCoordinateSystem" ,(void**) &ras_setcoordinatesystem },
92 {"TestRotation" ,(void**) &ras_testrotation },
93 {"GetVersion" ,(void**) &ras_getversion },
94 {"SoundWorld_New" ,(void**) &ras_soundworld_new },
95 {"SoundWorld_Destroy" ,(void**) &ras_soundworld_destroy },
96 {"SoundWorld_EndFrame" ,(void**) &ras_soundworld_endframe },
97 {"SoundWorld_BeginFrame" ,(void**) &ras_soundworld_beginframe },
98 {"FileInputWhile_New" ,(void**) &ras_fileinputwhole_new },
99 {"AudioDecoderFileWav_New" ,(void**) &ras_audiodecoderwav_new },
100 {"AudioDecoderFileOgg_New" ,(void**) &ras_audiodecoderogg_new },
101 {"SoundDataAudioDecoderOneShot_New" ,(void**) &ras_sounddataoneshot_new },
102 //{"SoundDataAudioDecoderFileLoop_New" ,(void**) &ras_sounddataloop_new },
103 {"SoundWorld_SetMainListener" ,(void**) &ras_soundworld_setmainlistener },
104 {"SoundWorld_SetScale" ,(void**) &ras_soundworld_setscale },
105 {"ListenerPlayer_New" ,(void**) &ras_listener_new },
106 {"ListenerPlayer_SetLocation" ,(void**) &ras_listener_setlocation },
107 {"ListenerPlayer_SetRotation_InVectors" ,(void**) &ras_listener_setrotation },
108 {"SoundSource_Ended" ,(void**) &ras_soundsource_ended },
109 {"SoundSourcePoint_New" ,(void**) &ras_soundsource_new },
110 {"SoundSourcePoint_SetLocation" ,(void**) &ras_soundsource_setlocation },
111 {"SoundEvent_New" ,(void**) &ras_soundevent_new },
112 {"SoundEvent_Ended" ,(void**) &ras_soundevent_ended },
113 {"SoundEvent_SetSoundPower" ,(void**) &ras_soundevent_setsoundpower },
116 static const char* ras_dllname [] =
120 #elif defined(MACOSX)
128 // --- entnum_t List functions ----
129 void entnum_new(entnum_t** prev, entnum_t** new){ //Adds a new item to the start of the list and sets the pointers.
130 (*new)=Mem_Alloc(snd_mempool,sizeof(entnum_t));
132 (*new)->next=entnum_list.next;
133 entnum_list.next=(*new);
134 (*prev)=&entnum_list;
136 Con_Printf("Could not allocate memory for a new entnum_t");
139 void entnum_begin(entnum_t** prev, entnum_t** now){ //Goes to the beginning of the list and sets the pointers.
140 (*prev)=&entnum_list;
141 (*now )=entnum_list.next;
143 void entnum_next(entnum_t** prev, entnum_t** now){ //Goes to the next element
145 (*now )=(*now)->next;
147 void entnum_delete_and_next(entnum_t** prev, entnum_t** now){ //Deletes the element and goes to the next element
150 if((*now)->rasptr) ras_delete((*now)->rasptr);
153 (*prev)->next=(*now);
155 // --- End Of entnum_t List functions ----
157 // --- channel_t List functions ----
158 void channel_new(channel_t** prev, channel_t** new){ //Adds a new item to the start of the list and sets the pointers.
159 (*new)=Mem_Alloc(snd_mempool,sizeof(channel_t));
161 (*new)->next=channel_list.next;
162 channel_list.next=(*new);
163 (*prev)=&channel_list;
165 Con_Printf("Could not allocate memory for a new channel_t");
168 void channel_begin(channel_t** prev, channel_t** now){ //Goes to the beginning of the list and sets the pointers.
169 (*prev)=&channel_list;
170 (*now )=channel_list.next;
172 void channel_next(channel_t** prev, channel_t** now){ //Goes to the next element
174 (*now )=(*now)->next;
176 void channel_delete_and_next(channel_t** prev, channel_t** now){ //Deletes the element and goes to the next element
179 if((*now)->rasptr) ras_delete((*now)->rasptr);
182 (*prev)->next=(*now);
184 // --- End Of channel_t List functions ----
186 // --- sfx_t List functions ----
187 void sfx_new(sfx_t** prev, sfx_t** new){ //Adds a new item to the start of the list and sets the pointers.
188 (*new)=Mem_Alloc(snd_mempool,sizeof(sfx_t));
190 (*new)->next=sfx_list.next;
191 sfx_list.next=(*new);
194 Con_Printf("Could not allocate memory for a new sfx_t");
197 void sfx_begin(sfx_t** prev, sfx_t** now){ //Goes to the beginning of the list and sets the pointers.
199 (*now )=sfx_list.next;
201 void sfx_next(sfx_t** prev, sfx_t** now){ //Goes to the next element
203 (*now )=(*now)->next;
205 void sfx_delete_and_next(sfx_t** prev, sfx_t** now){ //Deletes the element and goes to the next element
208 if((*now)->rasptr) ras_delete((*now)->rasptr);
211 (*prev)->next=(*now);
213 // --- End Of sfx_t List functions ----
215 void channel_new_smart(channel_t** prev, channel_t** now){
216 channel_new(prev,now);
218 (*now)->id=channel_id_count;
220 void Free_Unlocked_Sfx(void){
222 sfx_begin(&prev,&now);
225 !(now->flags & SFXFLAG_SERVERSOUND) &&
228 sfx_delete_and_next(&prev,&now);
230 sfx_next(&prev,&now);
234 void DP_To_Ras_Location(const float in[3],Location out[3]){
235 out[0]=(Location)(in[0]*DP_QU_Ras_Scale );
236 out[1]=(Location)(in[1]*DP_QU_Ras_Scale );
237 out[2]=(Location)(in[2]*DP_QU_Ras_Scale );
239 void S_Restart_f(void){
243 static void S_Play_Common (float fvol, float attenuation){
245 char name [MAX_QPATH];
247 if(ras_version>0 && ras_dll){
249 Con_Printf("Called S_Play_Common\n");
250 Con_Printf("Does this need to be location in depend channel ?\n");
254 while (i < Cmd_Argc ())
256 // Get the name, and appends ".wav" as an extension if there's none
257 strlcpy (name, Cmd_Argv (i), sizeof (name));
258 if (!strrchr (name, '.'))
259 strlcat (name, ".wav", sizeof (name));
262 // If we need to get the volume from the command line
265 fvol = atof (Cmd_Argv (i));
269 sfx = S_PrecacheSound (name, true, true);
271 S_StartSound (-1, 0, sfx, listener_location, fvol, attenuation);
275 static void S_Play_f(void){
276 S_Play_Common (1.0f, 1.0f);
278 static void S_Play2_f(void){
279 S_Play_Common (1.0f, 0.0f);
281 static void S_PlayVol_f(void){
282 S_Play_Common (-1.0f, 0.0f);
284 static void S_SoundList_f(void){
285 channel_t *prev_c, *now_c;
286 sfx_t *prev_s, *now_s;
287 entnum_t *prev_e, *now_e;
288 int count_c,count_s,count_e;
290 if(ras_version>0 && ras_dll){
292 Con_Printf("Sfx (SoundDatas) :\n"
293 "------------------\n"
294 "Locks\tflags\tpointer\tName\n");
296 sfx_begin(&prev_s,&now_s);
299 Con_Printf("%i\t%i\t%i\t%s\n",
300 now_s->locks, now_s->flags, now_s->rasptr!=NULL, now_s->name
302 sfx_next(&prev_s,&now_s);
305 Con_Printf("Entnum (SoundSources) :\n"
306 "-----------------------\n"
309 entnum_begin(&prev_e,&now_e);
312 Con_Printf("%i\t%i\n",
313 now_e->entnum, now_e->rasptr!=NULL
315 entnum_next(&prev_e,&now_e);
318 Con_Printf("Channels (SoundEvents) :\n"
319 "------------------------\n"
320 "Ent\tChannel\tID\tpointer\n");
322 channel_begin(&prev_c,&now_c);
325 Con_Printf("%i\t%i\t%i\t%i\n",
326 now_c->entnum, now_c->entchannel, now_c->id, now_c->rasptr!=NULL
328 channel_next(&prev_c,&now_c);
337 count_c,count_s,count_e
343 sfx_begin(&prev,&now);
344 while(now) sfx_delete_and_next(&prev,&now);
346 void Free_All_channel(){
347 channel_t *prev, *now;
348 channel_begin(&prev,&now);
349 while(now) channel_delete_and_next(&prev,&now);
351 void Free_All_entnum(){
352 entnum_t *prev, *now;
353 entnum_begin(&prev,&now);
354 while(now) entnum_delete_and_next(&prev,&now);
357 Location up[3],right[3],front[3];
359 snd_mempool = Mem_AllocPool("sound", 0, NULL);
360 if(ras_dll) Con_Printf( "3D RAS already loaded ... (this indicates a bug)\n");
361 if (Sys_LoadLibrary (ras_dllname, &ras_dll, ras_funcs))
363 Con_Printf ("Loading 3D RAS succeeded\n");
364 Con_Printf ("Checking the lib version\n");
365 ras_version=ras_getversion();
368 Con_Printf ("Version %i found\n",ras_version);
369 Cvar_RegisterVariable(&volume);
370 Cvar_RegisterVariable(&bgmvolume);
371 Cvar_RegisterVariable(&mastervolume);
372 Cvar_RegisterVariable(&snd_staticvolume);
373 Cvar_RegisterVariable(&snd_precache);
375 Cmd_AddCommand("play", S_Play_f, "play a sound at your current location (not heard by anyone else)");
376 Cmd_AddCommand("snd_play", S_Play_f, "play a sound at your current location (not heard by anyone else)");
377 Cmd_AddCommand("play2", S_Play2_f, "play a sound globally throughout the level (not heard by anyone else)");
378 Cmd_AddCommand("snd_play2", S_Play2_f, "play a sound globally throughout the level (not heard by anyone else)");
379 Cmd_AddCommand("playvol", S_PlayVol_f, "play a sound at the specified volume level at your current location (not heard by anyone else)");
380 Cmd_AddCommand("snd_playvol", S_PlayVol_f, "play a sound at the specified volume level at your current location (not heard by anyone else)");
381 Cmd_AddCommand("stopsound", S_StopAllSounds, "silence");
382 Cmd_AddCommand("soundlist", S_SoundList_f, "list loaded sounds");
383 Cmd_AddCommand("snd_stopsound", S_StopAllSounds, "silence");
384 Cmd_AddCommand("snd_soundlist", S_SoundList_f, "list loaded sounds");
385 Cmd_AddCommand("snd_restart", S_Restart_f, "restart sound system");
386 Cmd_AddCommand("snd_shutdown", S_Shutdown, "shutdown the sound system keeping the dll loaded");
387 Cmd_AddCommand("snd_startup", S_Startup, "start the sound system");
388 Cmd_AddCommand("snd_unloadallsounds", S_UnloadAllSounds_f, "unload all sound files");
390 //Set the coordinate system inside the lib equal to the one inside dp:
391 up[0]= 0 , up[1]= 0 , up[2]=1;
392 right[0]= 0 ,right[1]=-1 , right[2]=0;
393 front[0]= 1 ,front[1]= 0 , front[2]=0;
394 if(ras_setcoordinatesystem(right,up,front)==0){
395 Con_Printf("Failed to set the Coordinate System\n");
399 Con_Printf ("Failed to get the lib version\n");
400 Sys_UnloadLibrary (&ras_dll);
405 Con_Printf ("Loading 3D RAS failed\n");
406 Sys_UnloadLibrary (&ras_dll);
409 void S_Terminate (void){
412 Free_All_sfx(); // <= The only valid place to free the sfx.
413 Sys_UnloadLibrary(&ras_dll);
419 void S_Startup (void){
420 Location loc[3]={0, 0, 0};
421 Scalar rot[4]={1.0, 0, 0, 0};
422 if(ras_version>0 && ras_dll){
424 soundworld= ras_soundworld_new(48000,0.1);
426 Con_Printf("Failed to start a SoundWorld\n");
428 Con_Printf("Succeeded in starting a new SoundWorld\n");
429 listener=ras_listener_new(soundworld,loc,rot);
430 ras_soundworld_setmainlistener(soundworld,listener);
431 openframe = ras_soundworld_beginframe(soundworld);
432 ras_soundworld_setscale(soundworld,DP_Ras_UnitSize);
436 void S_Shutdown (void){
437 if(ras_version>0 && ras_dll && soundworld){
438 if(openframe) ras_soundworld_endframe(soundworld);
440 //Order doesn't really matter because the lib takes care of the references
441 //Free_All_sfx(); <= DO NOT FREE SFX ... they just keep sending in the old sfx causing havoc.
445 ras_soundworld_destroy(soundworld);
446 soundworld=ras_delete(soundworld);
448 Con_Printf("Failed to stop the SoundWorld\n");
450 Con_Printf("Succeeded in stopping the SoundWorld\n");
454 void S_UnloadAllSounds_f(void){
455 if(ras_version>0 && ras_dll){
460 void S_Update(const matrix4x4_t *listener_matrix){
465 Location location3 [3];
466 entnum_t *prev_e, *now_e;
467 channel_t *prev_c, *now_c;
468 if(ras_version>0 && ras_dll && soundworld){
469 Matrix4x4_ToVectors(listener_matrix,forward,left,up,listener_location); //Add the new player location.
471 VectorNegate(left,left);
472 DP_To_Ras_Location(listener_location,location3);
473 ras_listener_setlocation(listener,location3);
474 ras_listener_setrotation(listener,left,up,forward);
477 "DP: Left={%f|%f|%f} Up={%f|%f|%f} Front={%f|%f|%f}\n",
478 left[0], left[1], left[2],
480 forward[0],forward[1],forward[2]
482 ras_testrotation(left,up,forward);
484 "RAS: Left={%f|%f|%f} Up={%f|%f|%f} Front={%f|%f|%f}\n",
485 left[0], left[1], left[2],
487 forward[0],forward[1],forward[2]
493 Con_Printf("S_Update: Add a callback to SCR_CaptureVideo_SoundFrame.\n");
494 Con_Printf("S_Update: Add Slomo.\n");
495 Con_Printf("S_Update: Add BlockedSoundCheck.\n");
496 Con_Printf("S_Update: Add Slomo(as a cvar) and pauze.\n");
501 //(15:20:31) div0: (at the moment, you can extend it to multichannel)
502 //(15:20:40) div0: see S_CaptureAVISound()
503 if(cl.entities){ //if there is a list of ents
504 //Update all entities there position into the sound sources.
505 entnum_begin(&prev_e,&now_e);
508 Con_Printf("S_Update: Found an entnum_t without a valid RAS-ptr... This indicates a bug.\n");
509 entnum_delete_and_next(&prev_e,&now_e);
510 }else{ //Look for unused ent and drop them.
511 if(now_e->entnum!=-1){ //Talking about an ent ? Or a static sound source ?
512 if(ras_soundsource_ended(now_e->rasptr)){
513 VectorCopy(cl.entities[now_e->entnum].state_current.origin,float3);
514 VectorCopy(now_e->lastloc,float3);
515 DP_To_Ras_Location(float3,location3);
516 ras_soundsource_setlocation(now_e->rasptr,location3);
517 entnum_next(&prev_e,&now_e);
519 entnum_delete_and_next(&prev_e,&now_e);
522 if(ras_soundsource_ended(now_e->rasptr)){
523 entnum_delete_and_next(&prev_e,&now_e);
525 entnum_next(&prev_e,&now_e);
533 channel_begin(&prev_c,&now_c);
536 Con_Printf("S_Update: Found an channel_t without a valid RAS-ptr... This indicates a bug.\n");
537 channel_delete_and_next(&prev_c,&now_c);
538 }else{ //Look for stopped sound channels and free them
539 if(ras_soundevent_ended(now_c->rasptr)){
540 channel_delete_and_next(&prev_c,&now_c);
542 channel_next(&prev_c,&now_c);
546 ras_soundworld_endframe (soundworld);
548 openframe =ras_soundworld_beginframe(soundworld);
551 void S_ExtraUpdate (void){
552 // This lib is unable to use any extra updates.
553 //if(ras_version>0 && ras_dll){
556 sfx_t* S_FindName (const char *name){
558 if(ras_version>0 && ras_dll){
560 Con_Printf("Called S_FindName %s\n",name);
563 if (strlen (name) >= sizeof (now->name))
565 Con_Printf ("S_FindName: sound name too long (%s)\n", name);
569 sfx_begin(&prev,&now);
572 if(strcmp (now->name, name)==0) return now;
573 sfx_next(&prev,&now);
576 // None found in the list,
577 // Add a sfx_t struct for this sound
583 //sfx->total_length=0;
584 strlcpy (now->name, name, sizeof (now->name));
589 int S_LoadSound(sfx_t *sfx, int complain){
590 // TODO add SCR_PushLoadingScreen, SCR_PopLoadingScreen calls to this
591 fs_offset_t filesize;
592 char namebuffer[MAX_QPATH +16 ];
593 char filename [MAX_QPATH +16+4];
596 unsigned char *data=NULL;
598 void* decoder_ptr=NULL;
599 if(ras_version>0 && ras_dll){
601 fileext[4]=0; //Terminator
602 // See if already loaded
603 if (sfx->rasptr) return true;
605 // LordHavoc: if the sound filename does not begin with sound/, try adding it
606 if (!data && strncasecmp(sfx->name, "sound/", 6))
608 len = dpsnprintf (namebuffer, sizeof(namebuffer), "sound/%s", sfx->name);
609 if (len < 0){ // name too long
610 Con_DPrintf("S_LoadSound: name \"%s\" is too long\n", sfx->name);
614 data = FS_LoadFile(namebuffer, snd_mempool, false, &filesize);
615 if(data) memcpy(fileext,namebuffer+len-3,3); //Copy the extention
617 if(!data){ //Stick .wav to the end and try again
618 memcpy(filename,namebuffer,len);
619 memcpy(filename+len-4,".wav",5);
620 data = FS_LoadFile(filename, snd_mempool, false, &filesize);
621 if(data) memcpy(fileext,"wav",3);
623 if(!data){ //Stick .ogg to the end and try again
624 memcpy(filename,namebuffer,len);
625 memcpy(filename+len-4,".ogg",5);
626 data = FS_LoadFile(filename, snd_mempool, false, &filesize);
627 if(data) memcpy(fileext,"ogg",3);
631 // LordHavoc: then try without the added sound/ as wav and ogg
632 len = dpsnprintf (namebuffer, sizeof(namebuffer), "%s", sfx->name);
633 if (len < 0){ // name too long
634 Con_DPrintf("S_LoadSound: name \"%s\" is too long\n", sfx->name);
638 data = FS_LoadFile(namebuffer, snd_mempool, false, &filesize);
639 if(data) memcpy(fileext,namebuffer+len-3,3); //Copy the file extention
641 if(!data){ //Stick .wav to the end
642 memcpy(filename,namebuffer,len);
643 memcpy(filename+len-4,".wav",5);
644 data = FS_LoadFile(filename, snd_mempool, false, &filesize);
645 if(data) memcpy(fileext,"wav",3);
647 if(!data){ //Stick .ogg to the end
648 memcpy(filename,namebuffer,len);
649 memcpy(filename+len-4,".ogg",5);
650 data = FS_LoadFile(filename, snd_mempool, false, &filesize);
651 if(data) memcpy(fileext,"ogg",3);
655 if(complain) Con_Printf("Failed attempt load file '%s'\n",namebuffer);
656 }else{ //if the file loaded: pass to RAS 3D
657 file_ptr=ras_fileinputwhole_new(data,filesize);
658 // There we transfered to file to RAS 3D
659 // So lets free up data shall we ?
663 Con_Printf("Failed to upload file to audio lib\n");
665 if(0==strncasecmp(fileext,"wav",3)){
666 decoder_ptr=ras_audiodecoderwav_new(file_ptr,true); //(true)use seek mode: some quake files are broken.
668 if(0==strncasecmp(fileext,"ogg",3)){
669 decoder_ptr=ras_audiodecoderogg_new(file_ptr);
672 Con_Printf("File succeeded to load, but no decoder available for '%s'\n",fileext);
675 Con_Printf("ToDo: Add a cvar to configure the cache size and number of cache blocks.\n");
676 Con_Printf("ToDo: Add support for looping sounds.\n");
678 sfx->rasptr=ras_sounddataoneshot_new(decoder_ptr,0.05,8);
680 file_ptr=ras_delete(file_ptr);
682 return !(sfx->rasptr);
688 sfx_t *S_PrecacheSound (const char *name, qboolean complain, qboolean serversound){
690 if(ras_version>0 && ras_dll){
692 Con_Printf("Called S_PrecacheSound %s, %i, %i\n",name,complain,serversound);
694 if (name == NULL || name[0] == 0)
696 sfx = S_FindName (name);
697 if (sfx == NULL) return NULL;
698 if (lock) ++(sfx->locks);
699 if (snd_precache.integer) S_LoadSound(sfx, complain);
704 void S_ClearUsed (void){
705 sfx_t *prev_s, *now_s;
708 if(ras_version>0 && ras_dll){
709 Con_Printf("Called S_ClearUsed\n");
710 for(i=0;i<numsounds;++i){
711 Con_Printf("Loading :'%s'\n",serversound[i]);
712 // Load the ambient sounds
714 Con_Printf("ToDo: Load abmient sounds (Need geometry).\n");
716 // Remove the SFXFLAG_SERVERSOUND flag
717 sfx_begin(&prev_s,&now_s);
719 if (now_s->flags & SFXFLAG_SERVERSOUND) now_s->flags &= ~SFXFLAG_SERVERSOUND;
720 sfx_next(&prev_s,&now_s);
725 void S_PurgeUnused(void){
728 qboolean S_IsSoundPrecached (const sfx_t *sfx){
729 if(ras_version>0 && ras_dll){
735 void S_KillChannel (channel_t *now){ //Silences a SoundEvent
737 ras_soundevent_setsoundpower(now->rasptr,0);
738 ras_delete(now->rasptr);
741 Con_Printf("S_KillChannel: Warning pointer was 0 ... this indicates a bug.\n");
745 int S_StartSound_OnEnt (int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation){
746 entnum_t *prev_e, *now_e;
747 channel_t *prev_c, *now_c;
748 Location tmp_location[3];
750 //If there is a game world
752 Con_Printf("S_StartSound_OnEnt: no entity list exists\n");
756 // Look for the correct ent_t
757 entnum_begin(&prev_e,&now_e);
759 if(now_e->entnum==entnum) break;
760 entnum_next(&prev_e,&now_e);
762 //We found no ent ... lets make one...
764 entnum_new(&prev_e,&now_e);
766 Con_Printf("S_StartSound_OnEnt: could not make new entnum_t\n");
769 VectorCopy(cl.entities[entnum].state_current.origin, now_e->lastloc);
770 DP_To_Ras_Location(now_e->lastloc,tmp_location);
771 now_e->rasptr=ras_soundsource_new(soundworld,1.0,tmp_location);
773 Con_Printf("S_StartSound_OnEnt: could not create a new sound source\n");
778 //Ok now lets look for the channel.
779 channel_begin(&prev_c,&now_c);
782 now_c->entnum==entnum &&
783 now_c->entchannel==entchannel
785 channel_next(&prev_c,&now_c);
788 if(now_c){ //O dear the channel excists ....
789 S_KillChannel(now_c);
790 }else{ //We found no channel .... So we need to make a new one ...
791 channel_new_smart(&prev_c,&now_c);
792 now_c->entnum =entnum;
793 now_c->entchannel=entchannel;
795 Con_Printf("S_StartSound_OnEnt: could not make new channel_t\n");
796 channel_delete_and_next(&prev_c,&now_c);
801 //Lets start the sound on the acquired sound source and channel
802 now_c->rasptr=ras_soundevent_new(
803 soundworld,now_e->rasptr,sfx->rasptr,fvol*DP_Ras_VolumeScale,1.0
805 if(!now_c->rasptr){ //Whoops, failed, lets delete this channel then.
806 channel_delete_and_next(&prev_c,&now_c);
807 Con_Printf("S_StartSound_OnEnt: could not make a new soundevent.\n");
812 int S_StartSound_OnLocation (sfx_t *sfx, vec3_t origin, float fvol, float attenuation){
813 entnum_t *prev_e, *now_e;
814 channel_t *prev_c, *now_c;
815 Location tmp_location[3];
816 DP_To_Ras_Location(origin,tmp_location);
818 entnum_new (&prev_e,&now_e);
819 VectorCopy(now_e->lastloc,origin);
821 now_e->rasptr=ras_soundsource_new(soundworld,1.0,tmp_location);
823 Con_Printf("S_StartSound_OnLocation: Could not make a new soundsource.\n");
824 entnum_delete_and_next(&prev_e,&now_e);
827 channel_new_smart(&prev_c,&now_c);
829 now_c->entchannel=-1;
830 now_c->rasptr =ras_soundevent_new(soundworld,now_e->rasptr,sfx->rasptr,fvol*DP_Ras_VolumeScale,1.0);
832 entnum_delete_and_next(&prev_e,&now_e);
833 channel_delete_and_next(&prev_c,&now_c);
834 Con_Printf("S_StartSound_OnLocation: Could not make a new soundevent.\n");
841 // Qantourisc on the wicked-quake-sound-system:
842 // --------------------------------------------
843 // entnum can be Zero or lower => This means "use the origin" so it's not tracked.
844 // entnum -1 is a "world" containing more then 1 soundsource.
845 // If channel != 0 try to overwrite the requested channel. Otherwise play it on some random channel.
846 // If channel == -1 overwrite the first track of the ent.
847 // If a channel replacement is requested, only allow overwriting if it's owned by the same channel.
848 // If no channel can be replaced, pick a new one.
849 // Also when you overwrite a channel, that one has to stop dead.
850 // This function returns the channel it was played on (so it can be stopped later)
851 // This starts CD-music: S_StartSound (-1, 0, sfx, vec3_origin, cdvolume, 0);
852 // The channel you return then, can later be requested to be stopped.
854 int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation){
855 sfx_t *prev_s,*now_s;
857 if(ras_version>0 && ras_dll && soundworld){
859 Con_Printf("Called S_StartSound %i, %i, %f, %f\n",entnum,entchannel,fvol,attenuation);
861 if(sfx==NULL){ // They pass this to me ... but WHY ? it makes no sense !
863 Con_Printf("S_StartSound: forgot to mention a sfx!\n");
869 sfx_begin(&prev_s,&now_s);
875 sfx_next(&prev_s,&now_s);
878 Con_Printf("S_StartSound: passed illegal sfx_t!\n");
881 if (!S_LoadSound(sfx,true)) return -1;
884 if(entnum!=-1){ //If we are talking about an ent
885 return S_StartSound_OnEnt(entnum,entchannel,sfx,fvol,attenuation);
887 return S_StartSound_OnLocation( sfx,origin,fvol,attenuation);
890 Con_Printf("S_StartSound: engine not stated\n");
893 qboolean S_LocalSound (const char *s){
896 if(ras_version>0 && ras_dll){
898 Con_Printf("Called S_LocalSound %s\n",s);
901 sfx = S_PrecacheSound (s, true, true);
904 Con_Printf("S_LocalSound: can't precache %s\n", s);
908 // Local sounds must not be freed
909 sfx->flags |= SFXFLAG_PERMANENTLOCK;
911 Con_Printf("S_LocalSound: this is still a small hack\n");
913 ch_ind = S_StartSound (cl.viewentity, 0, sfx, listener_location, 1, 0);
917 //channels[ch_ind].flags |= CHANNELFLAG_LOCALSOUND;
922 void S_StaticSound (sfx_t *sfx, vec3_t origin, float fvol, float attenuation){
923 //Static sounds should not be looped
924 if(ras_version>0 && ras_dll){
926 Con_Printf("Called S_StaticSound\n");
927 Con_Printf("Waiting on Qantourisc to add Static sounds in his lib.\n");
929 //Static sounds are sounds that are not pauzed, and or played locally.
932 void S_StopSound (int entnum, int entchannel){
933 channel_t *prev, *now;
934 if(ras_version>0 && ras_dll){
935 //Con_Printf("Called S_StopSound %i, %i\n",entnum,entchannel);
936 channel_begin(&prev,&now);
938 if(now->entnum==entnum && now->entchannel==entchannel) break;
939 channel_next(&prev,&now);
941 if(now){ //If we found our to delete sound.
943 channel_delete_and_next(&prev,&now);
945 Con_Printf("S_StopSound: Could not find the requested entnum-entchannel sound\n");
949 void S_StopAllSounds (void){
950 channel_t *prev, *now;
951 if(ras_version>0 && ras_dll){
952 //Con_Printf("Called S_StopAllSounds\n");
953 channel_begin(&prev,&now);
956 channel_next(&prev,&now);
960 void S_PauseGameSounds (qboolean toggle){
961 if(ras_version>0 && ras_dll){
962 Con_Printf("Called S_PauseGameSounds %i\n",toggle);
963 //Localsounds should not be pauzed
966 void S_StopChannel (unsigned int channel_ind){
967 channel_t *prev,*now;
968 if(ras_version>0 && ras_dll){
969 channel_begin(&prev,&now);
971 if(now->id==channel_ind){
973 channel_delete_and_next(&prev,&now);
975 channel_next(&prev,&now);
980 qboolean S_SetChannelFlag (unsigned int ch_ind, unsigned int flag, qboolean value){
981 if(ras_version>0 && ras_dll){
982 Con_Printf("Called S_SetChannelFlag %u, %u, %i\n",ch_ind, flag, value);
986 void S_SetChannelVolume (unsigned int ch_ind, float fvol){
987 channel_t *prev,*now;
988 if(ras_version>0 && ras_dll){
989 Con_Printf("Called S_SetChannelVolume %u, %f\n",ch_ind, fvol);
990 channel_begin(&prev,&now);
994 ras_soundevent_setsoundpower(now->rasptr,fvol*DP_Ras_VolumeScale);
996 Con_Printf("S_StopChannel: Warning pointer was 0 ... this indicates a bug.\n");
999 channel_next(&prev,&now);
1004 float S_GetChannelPosition (unsigned int ch_ind)
1006 // FIXME unsupported
1010 void S_BlockSound (void){
1013 void S_UnblockSound (void){
1016 Con_Printf("S_UnblockSound: Requested more S_UnblockSound then S_BlockSound.\n");
1020 int S_GetSoundRate (void){
1021 Con_Printf("Inside 3DRAS, the soundrate of the end-user is NONE of the dev's concern.\n");
1022 Con_Printf("So let's assume 44100.\n");
1026 int S_GetSoundChannels (void){
1027 Con_Printf("Inside 3DRAS, the soundrate of the end-user is NONE of the dev's concern.\n");
1028 Con_Printf("So let's assume 2.\n");
1033 ====================
1034 SndSys_SendKeyEvents
1036 Send keyboard events originating from the sound system (e.g. MIDI)
1037 ====================
1039 void SndSys_SendKeyEvents(void)