]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - snd_3dras.c
DP_QC_GETTIME_CDTRACK: extension to query the playing time of the current cd track.
[xonotic/darkplaces.git] / snd_3dras.c
1 // BSD
2
3 #include "quakedef.h"
4 #include "snd_3dras_typedefs.h"
5 #include "snd_3dras.h"
6
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 volume = {CVAR_SAVE, "volume", "0.7", "volume of sound effects"};
9 cvar_t snd_staticvolume = {CVAR_SAVE, "snd_staticvolume", "1", "volume of ambient sound effects (such as swampy sounds at the start of e1m2)"};
10 cvar_t snd_initialized = { CVAR_READONLY, "snd_initialized", "0", "indicates the sound subsystem is active"};
11 cvar_t snd_mutewhenidle = {CVAR_SAVE, "snd_mutewhenidle", "1", "whether to disable sound output when game window is inactive"};
12 cvar_t snd_streaming = { CVAR_SAVE, "snd_streaming", "1", "enables keeping compressed ogg sound files compressed, decompressing them only as needed, otherwise they will be decompressed completely at load (may use a lot of memory)"};
13 static cvar_t snd_precache = {0, "snd_precache", "1", "loads sounds before they are used"};
14
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)
17 int ras_version;
18
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)
21         NULL, //next
22         "",  //name[MAX_QPATH];
23         NULL, //sounddata
24         0,    //locks
25         0    //flags
26         //0,    //loopstart,
27         //0     //total_length
28 };
29 static unsigned int channel_id_count=0;
30 static channel_t channel_list={
31         NULL, //next
32         NULL, //soundevent
33         0, //entnum
34         0, //entchannel
35         0 //id
36 };
37 static entnum_t  entnum_list={
38         NULL,// *next;
39         0,   //  entnum;
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)
42 };
43
44 int   updatecount=0;
45 int   soundblocked=0;
46 int   openframe;
47 void* soundworld;
48 void* listener;
49 float listener_location   [3];
50
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  *);
85
86 // #define RAS_PRINT //Comment out for to not print extra crap.
87
88 static dllfunction_t ras_funcs[] =
89 {
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   },
114         { NULL                                         , NULL                                      }
115 };
116 static const char* ras_dllname [] =
117 {
118         #if defined(WIN64)
119                 "3dras64.dll",
120         #elif defined(WIN32)
121                 "3dras32.dll",
122         #elif defined(MACOSX)
123                 "3dras.dylib",
124         #else
125                 "3dras.so",
126         #endif
127                 NULL
128 };
129
130 // --- entnum_t List functions ----
131 void entnum_new(entnum_t** prev, entnum_t** new){ //Adds a new item to the start of the list and sets the pointers.
132         (*new)=Mem_Alloc(snd_mempool,sizeof(entnum_t));
133         if(&new){
134                 (*new)->next=entnum_list.next;
135                 entnum_list.next=(*new);
136                 (*prev)=&entnum_list;
137         }else{
138                 Con_Printf("Could not allocate memory for a new entnum_t");
139         }
140 }
141 void entnum_begin(entnum_t** prev, entnum_t** now){ //Goes to the beginning of the list and sets the pointers.
142         (*prev)=&entnum_list;
143         (*now )=entnum_list.next;
144 }
145 void entnum_next(entnum_t** prev, entnum_t** now){ //Goes to the next element
146         (*prev)=(*now);
147         (*now )=(*now)->next;
148 }
149 void entnum_delete_and_next(entnum_t** prev, entnum_t** now){ //Deletes the element and goes to the next element
150         entnum_t* next;
151         next=(*now)->next;
152         if((*now)->rasptr) ras_delete((*now)->rasptr);
153         Mem_Free(*now);
154         (*now)=next;
155         (*prev)->next=(*now);
156 }
157 // --- End Of entnum_t List functions ----
158
159 // --- channel_t List functions ----
160 void channel_new(channel_t** prev, channel_t** new){ //Adds a new item to the start of the list and sets the pointers.
161         (*new)=Mem_Alloc(snd_mempool,sizeof(channel_t));
162         if(&new){
163                 (*new)->next=channel_list.next;
164                 channel_list.next=(*new);
165                 (*prev)=&channel_list;
166         }else{
167                 Con_Printf("Could not allocate memory for a new channel_t");
168         }
169 }
170 void channel_begin(channel_t** prev, channel_t** now){ //Goes to the beginning of the list and sets the pointers.
171         (*prev)=&channel_list;
172         (*now )=channel_list.next;
173 }
174 void channel_next(channel_t** prev, channel_t** now){ //Goes to the next element
175         (*prev)=(*now );
176         (*now )=(*now)->next;
177 }
178 void channel_delete_and_next(channel_t** prev, channel_t** now){ //Deletes the element and goes to the next element
179         channel_t* next;
180         next=(*now)->next;
181         if((*now)->rasptr) ras_delete((*now)->rasptr);
182         Mem_Free(*now);
183         (*now)=next;
184         (*prev)->next=(*now);
185 }
186 // --- End Of channel_t List functions ----
187
188 // --- sfx_t List functions ----
189 void sfx_new(sfx_t** prev, sfx_t** new){ //Adds a new item to the start of the list and sets the pointers.
190         (*new)=Mem_Alloc(snd_mempool,sizeof(sfx_t));
191         if(&new){
192                 (*new)->next=sfx_list.next;
193                 sfx_list.next=(*new);
194                 (*prev)=&sfx_list;
195         }else{
196                 Con_Printf("Could not allocate memory for a new sfx_t");
197         }
198 }
199 void sfx_begin(sfx_t** prev, sfx_t** now){ //Goes to the beginning of the list and sets the pointers.
200         (*prev)=&sfx_list;
201         (*now )=sfx_list.next;
202 }
203 void sfx_next(sfx_t** prev, sfx_t** now){ //Goes to the next element
204         (*prev)=(*now );
205         (*now )=(*now)->next;
206 }
207 void sfx_delete_and_next(sfx_t** prev, sfx_t** now){ //Deletes the element and goes to the next element
208         sfx_t* next;
209         next=(*now)->next;
210         if((*now)->rasptr) ras_delete((*now)->rasptr);
211         Mem_Free(*now);
212         (*now)=next;
213         (*prev)->next=(*now);
214 }
215 // --- End Of sfx_t List functions ----
216
217 void channel_new_smart(channel_t** prev, channel_t** now){
218         channel_new(prev,now);
219         ++channel_id_count;
220         (*now)->id=channel_id_count;
221 }
222 void Free_Unlocked_Sfx(void){
223         sfx_t *prev, *now;
224         sfx_begin(&prev,&now);
225         while(now){
226                 if(
227                         !(now->flags & SFXFLAG_SERVERSOUND) &&
228                         now->locks<=0
229                 ){
230                         sfx_delete_and_next(&prev,&now);
231                 }else{
232                         sfx_next(&prev,&now);
233                 }
234         }
235 }
236 void DP_To_Ras_Location(const float in[3],Location out[3]){
237         out[0]=(Location)(in[0]*DP_QU_Ras_Scale );
238         out[1]=(Location)(in[1]*DP_QU_Ras_Scale );
239         out[2]=(Location)(in[2]*DP_QU_Ras_Scale );
240 }
241 void S_Restart_f(void){
242         S_Shutdown();
243         S_Startup();
244 }
245 static void S_Play_Common (float fvol, float attenuation){
246         int i;
247         char name [MAX_QPATH];
248         sfx_t *sfx;
249         if(ras_version>0 && ras_dll){
250                 #ifdef RAS_PRINT
251                         Con_Printf("Called S_Play_Common\n");
252                         Con_Printf("Does this need to be location in depend channel ?\n");
253                 #endif
254
255                 i = 1;
256                 while (i < Cmd_Argc ())
257                 {
258                         // Get the name, and appends ".wav" as an extension if there's none
259                         strlcpy (name, Cmd_Argv (i), sizeof (name));
260                         if (!strrchr (name, '.'))
261                                 strlcat (name, ".wav", sizeof (name));
262                         i++;
263
264                         // If we need to get the volume from the command line
265                         if (fvol == -1.0f)
266                         {
267                                 fvol = atof (Cmd_Argv (i));
268                                 i++;
269                         }
270
271                         sfx = S_PrecacheSound (name, true, true);
272                         if (sfx)
273                                 S_StartSound (-1, 0, sfx, listener_location, fvol, attenuation);
274                 }
275         }
276 }
277 static void S_Play_f(void){
278         S_Play_Common (1.0f, 1.0f);
279 }
280 static void S_Play2_f(void){
281         S_Play_Common (1.0f, 0.0f);
282 }
283 static void S_PlayVol_f(void){
284         S_Play_Common (-1.0f, 0.0f);
285 }
286 static void S_SoundList_f(void){
287         channel_t *prev_c, *now_c;
288             sfx_t *prev_s, *now_s;
289          entnum_t *prev_e, *now_e;
290          int count_c,count_s,count_e;
291         
292         if(ras_version>0 && ras_dll){
293
294                 Con_Printf("Sfx (SoundDatas) :\n"
295                                  "------------------\n"
296                                  "Locks\tflags\tpointer\tName\n");
297                 count_s=0;
298                 sfx_begin(&prev_s,&now_s);
299                 while(now_s){
300                         ++count_s;
301                         Con_Printf("%i\t%i\t%i\t%s\n",
302                                 now_s->locks, now_s->flags, now_s->rasptr!=NULL, now_s->name
303                         );
304                         sfx_next(&prev_s,&now_s);
305                 }
306
307                 Con_Printf("Entnum (SoundSources) :\n"
308                                  "-----------------------\n"
309                                  "Ent\tpointer\n");
310                 count_e=0;
311                 entnum_begin(&prev_e,&now_e);
312                 while(now_e){
313                         ++count_e;
314                         Con_Printf("%i\t%i\n",
315                                 now_e->entnum, now_e->rasptr!=NULL
316                         );
317                         entnum_next(&prev_e,&now_e);
318                 }
319
320                 Con_Printf("Channels (SoundEvents) :\n"
321                                  "------------------------\n"
322                                  "Ent\tChannel\tID\tpointer\n");
323                 count_c=0;
324                 channel_begin(&prev_c,&now_c);
325                 while(now_c){
326                         ++count_c;
327                         Con_Printf("%i\t%i\t%i\t%i\n",
328                                 now_c->entnum, now_c->entchannel, now_c->id, now_c->rasptr!=NULL
329                         );
330                         channel_next(&prev_c,&now_c);
331                 }
332
333                 Con_Printf(
334                         "Count:\n"
335                         "------\n"
336                         "Channels: %i\n"
337                         "Sfx's:    %i\n"
338                         "Entities: %i\n",
339                         count_c,count_s,count_e
340                 );
341         }
342 }
343 void Free_All_sfx(){
344         sfx_t *prev, *now;
345         sfx_begin(&prev,&now);
346         while(now) sfx_delete_and_next(&prev,&now);
347 }
348 void Free_All_channel(){
349         channel_t *prev, *now;
350         channel_begin(&prev,&now);
351         while(now) channel_delete_and_next(&prev,&now);
352 }
353 void Free_All_entnum(){
354         entnum_t *prev, *now;
355         entnum_begin(&prev,&now);
356         while(now) entnum_delete_and_next(&prev,&now);
357 }
358 void S_Init (void){
359         Location up[3],right[3],front[3];
360         ras_version=0;
361         snd_mempool = Mem_AllocPool("sound", 0, NULL);
362         if(ras_dll) Con_Printf( "3D RAS already loaded ... (this indicates a bug)\n");
363         if (Sys_LoadLibrary (ras_dllname, &ras_dll, ras_funcs))
364         {
365                 Con_Printf ("Loading 3D RAS succeeded\n");
366                 Con_Printf ("Checking the lib version\n");
367                 ras_version=ras_getversion();
368                 if (ras_version>0){
369                         
370                         Con_Printf ("Version %i found\n",ras_version);
371                         Cvar_RegisterVariable(&volume);
372                         Cvar_RegisterVariable(&bgmvolume);
373                         Cvar_RegisterVariable(&snd_staticvolume);
374                         Cvar_RegisterVariable(&snd_precache);
375
376                         Cmd_AddCommand("play", S_Play_f, "play a sound at your current location (not heard by anyone else)");
377                         Cmd_AddCommand("snd_play", S_Play_f, "play a sound at your current location (not heard by anyone else)");
378                         Cmd_AddCommand("play2", S_Play2_f, "play a sound globally throughout the level (not heard by anyone else)");
379                         Cmd_AddCommand("snd_play2", S_Play2_f, "play a sound globally throughout the level (not heard by anyone else)");
380                         Cmd_AddCommand("playvol", S_PlayVol_f, "play a sound at the specified volume level at your current location (not heard by anyone else)");
381                         Cmd_AddCommand("snd_playvol", S_PlayVol_f, "play a sound at the specified volume level at your current location (not heard by anyone else)");
382                         Cmd_AddCommand("stopsound", S_StopAllSounds, "silence");
383                         Cmd_AddCommand("soundlist", S_SoundList_f, "list loaded sounds");
384                         Cmd_AddCommand("snd_stopsound", S_StopAllSounds, "silence");
385                         Cmd_AddCommand("snd_soundlist", S_SoundList_f, "list loaded sounds");
386                         Cmd_AddCommand("snd_restart", S_Restart_f, "restart sound system");
387                         Cmd_AddCommand("snd_shutdown", S_Shutdown, "shutdown the sound system keeping the dll loaded");
388                         Cmd_AddCommand("snd_startup", S_Startup, "start the sound system");
389                         Cmd_AddCommand("snd_unloadallsounds", S_UnloadAllSounds_f, "unload all sound files");
390
391                         //Set the coordinate system inside the lib equal to the one inside dp:
392                            up[0]= 0 ,   up[1]= 0 ,    up[2]=1;
393                         right[0]= 0 ,right[1]=-1 , right[2]=0;
394                         front[0]= 1 ,front[1]= 0 , front[2]=0;
395                         if(ras_setcoordinatesystem(right,up,front)==0){
396                                 Con_Printf("Failed to set the Coordinate System\n");
397                                 ras_version=0;
398                         }
399                 }else{
400                         Con_Printf ("Failed to get the lib version\n");
401                         Sys_UnloadLibrary (&ras_dll);
402                         ras_dll=0;
403                 }
404         }else{
405                 ras_dll=0;
406                 Con_Printf ("Loading 3D RAS failed\n");
407                 Sys_UnloadLibrary (&ras_dll);
408         }
409 }
410 void S_Terminate (void){
411         if(ras_dll){
412                 S_Shutdown();
413                 Free_All_sfx(); // <= The only valid place to free the sfx.
414                 Sys_UnloadLibrary(&ras_dll);
415                 ras_dll=0;
416                 ras_version=0;
417         }
418 }
419
420 void S_Startup (void){
421         Location loc[3]={0, 0, 0};
422         Scalar   rot[4]={1.0, 0, 0, 0};
423         if(ras_version>0 && ras_dll){
424                 channel_id_count=1;
425                 soundworld= ras_soundworld_new(48000,0.1);
426                 if(soundworld==0){
427                         Con_Printf("Failed to start a SoundWorld\n");
428                 }else{
429                         Con_Printf("Succeeded in starting a new SoundWorld\n");
430                         listener=ras_listener_new(soundworld,loc,rot);
431                         ras_soundworld_setmainlistener(soundworld,listener);
432                         openframe = ras_soundworld_beginframe(soundworld);
433                         ras_soundworld_setscale(soundworld,DP_Ras_UnitSize);
434                 }
435         }
436 }
437 void S_Shutdown (void){
438         if(ras_version>0 && ras_dll && soundworld){
439                 if(openframe) ras_soundworld_endframe(soundworld);
440                 
441                 //Order doesn't really matter because the lib takes care of the references
442                 //Free_All_sfx(); <= DO NOT FREE SFX ... they just keep sending in the old sfx causing havoc.
443                 Free_All_channel();
444                 Free_All_entnum();
445                 
446                 ras_soundworld_destroy(soundworld);
447                 soundworld=ras_delete(soundworld);
448                 if(soundworld){
449                         Con_Printf("Failed to stop the SoundWorld\n");
450                 }else{
451                         Con_Printf("Succeeded in stopping the SoundWorld\n");
452                 }
453         }
454 }
455 void S_UnloadAllSounds_f(void){
456         if(ras_version>0 && ras_dll){
457                 Free_All_sfx();
458         }
459 }
460
461 void S_Update(const matrix4x4_t *listener_matrix){
462         float forward   [3];
463         float left      [3];
464         float up        [3];
465         float float3    [3];
466         Location location3 [3];
467         entnum_t  *prev_e, *now_e;
468         channel_t *prev_c, *now_c;
469         if(ras_version>0 && ras_dll && soundworld){
470                 Matrix4x4_ToVectors(listener_matrix,forward,left,up,listener_location); //Add the new player location.
471                 if(openframe){
472                         VectorNegate(left,left);
473                         DP_To_Ras_Location(listener_location,location3);
474                         ras_listener_setlocation(listener,location3);
475                         ras_listener_setrotation(listener,left,up,forward);
476                         /*
477                         Con_Printf(
478                                 "DP:  Left={%f|%f|%f} Up={%f|%f|%f} Front={%f|%f|%f}\n",
479                                    left[0],   left[1],   left[2],
480                                      up[0],     up[1],     up[2],
481                                 forward[0],forward[1],forward[2]
482                         );
483                         ras_testrotation(left,up,forward);
484                         Con_Printf(
485                                 "RAS: Left={%f|%f|%f} Up={%f|%f|%f} Front={%f|%f|%f}\n",
486                                    left[0],   left[1],   left[2],
487                                      up[0],     up[1],     up[2],
488                                 forward[0],forward[1],forward[2]
489                         );
490                         */
491                         if(updatecount>100){
492                                 updatecount=0;
493                                 #ifdef RAS_PRINT
494                                 Con_Printf("S_Update: Add a callback to SCR_CaptureVideo_SoundFrame.\n");
495                                 Con_Printf("S_Update: Add Slomo.\n");
496                                 Con_Printf("S_Update: Add BlockedSoundCheck.\n");
497                                 Con_Printf("S_Update: Add Slomo(as a cvar) and pauze.\n");
498                                 #endif
499                         }else{
500                                 ++updatecount;
501                         }
502                         //(15:20:31) div0: (at the moment, you can extend it to multichannel)
503                         //(15:20:40) div0: see S_CaptureAVISound()
504                         if(cl.entities){ //if there is a list of ents
505                                 //Update all entities there position into the sound sources.
506                                 entnum_begin(&prev_e,&now_e);
507                                 while(now_e){
508                                         if(!now_e->rasptr){
509                                                 Con_Printf("S_Update: Found an entnum_t without a valid RAS-ptr... This indicates a bug.\n");
510                                                 entnum_delete_and_next(&prev_e,&now_e);
511                                         }else{ //Look for unused ent and drop them.
512                                                 if(now_e->entnum!=-1){ //Talking about an ent ? Or a static sound source ?
513                                                         if(ras_soundsource_ended(now_e->rasptr)){
514                                                                         VectorCopy(cl.entities[now_e->entnum].state_current.origin,float3);
515                                                                         VectorCopy(now_e->lastloc,float3);
516                                                                         DP_To_Ras_Location(float3,location3);
517                                                                         ras_soundsource_setlocation(now_e->rasptr,location3);
518                                                                         entnum_next(&prev_e,&now_e);
519                                                         }else{
520                                                                 entnum_delete_and_next(&prev_e,&now_e);
521                                                         }
522                                                 }else{
523                                                         if(ras_soundsource_ended(now_e->rasptr)){
524                                                                 entnum_delete_and_next(&prev_e,&now_e);
525                                                         }else{
526                                                                 entnum_next(&prev_e,&now_e);
527                                                         }
528                                                 }
529                                         }
530                                 }
531                         }else{
532                                 Free_All_entnum();
533                         }
534                         channel_begin(&prev_c,&now_c);
535                         while(now_c){
536                                 if(!now_c->rasptr){
537                                         Con_Printf("S_Update: Found an channel_t without a valid RAS-ptr... This indicates a bug.\n");
538                                         channel_delete_and_next(&prev_c,&now_c);
539                                 }else{ //Look for stopped sound channels and free them
540                                         if(ras_soundevent_ended(now_c->rasptr)){
541                                                 channel_delete_and_next(&prev_c,&now_c);
542                                         }else{
543                                                 channel_next(&prev_c,&now_c);
544                                         }
545                                 }
546                         }
547                         ras_soundworld_endframe  (soundworld);
548                 }
549                 openframe =ras_soundworld_beginframe(soundworld);
550         }
551 }
552 void S_ExtraUpdate (void){
553         // This lib is unable to use any extra updates.
554         //if(ras_version>0 && ras_dll){
555         //}
556 }
557 sfx_t* S_FindName (const char *name){
558         sfx_t *prev,*now;
559         if(ras_version>0 && ras_dll){
560                 #ifdef RAS_PRINT
561                 Con_Printf("Called S_FindName %s\n",name);
562                 #endif
563
564                 if (strlen (name) >= sizeof (now->name))
565                 {
566                         Con_Printf ("S_FindName: sound name too long (%s)\n", name);
567                         return NULL;
568                 }
569                 
570                 sfx_begin(&prev,&now);
571                 // Seek in list
572                 while (now){
573                         if(strcmp (now->name, name)==0) return now;
574                         sfx_next(&prev,&now);
575                 }
576                 
577                 // None found in the list,
578                 // Add a sfx_t struct for this sound
579                 sfx_new(&prev,&now);
580                 now->locks=0;
581                 now->flags=0;
582                 now->rasptr=0;
583                 //sfx->looptstart=0;
584                 //sfx->total_length=0;
585                 strlcpy (now->name, name, sizeof (now->name));
586                 return now;
587         }
588         return NULL;
589 }
590 int S_LoadSound(sfx_t *sfx, int complain){
591         // TODO add SCR_PushLoadingScreen, SCR_PopLoadingScreen calls to this
592         fs_offset_t filesize;
593         char namebuffer[MAX_QPATH +16  ];
594         char filename  [MAX_QPATH +16+4];
595         char fileext   [4];
596         size_t len;
597         unsigned char *data=NULL;
598         void* file_ptr=NULL;
599         void* decoder_ptr=NULL;
600         if(ras_version>0 && ras_dll){
601
602                 fileext[4]=0; //Terminator
603                 // See if already loaded
604                 if (sfx->rasptr) return true;
605
606                 // LordHavoc: if the sound filename does not begin with sound/, try adding it
607                 if (!data && strncasecmp(sfx->name, "sound/", 6))
608                 {
609                         len = dpsnprintf (namebuffer, sizeof(namebuffer), "sound/%s", sfx->name);
610                         if (len < 0){ // name too long
611                                 Con_DPrintf("S_LoadSound: name \"%s\" is too long\n", sfx->name);
612                                 return false;
613                         }
614                         if(!data){
615                                 data = FS_LoadFile(namebuffer, snd_mempool, false, &filesize);
616                                 if(data) memcpy(fileext,namebuffer+len-3,3); //Copy the extention
617                         }
618                         if(!data){ //Stick .wav to the end and try again
619                                 memcpy(filename,namebuffer,len);
620                                 memcpy(filename+len-4,".wav",5);
621                                 data = FS_LoadFile(filename, snd_mempool, false, &filesize);
622                                 if(data) memcpy(fileext,"wav",3);
623                         }
624                         if(!data){ //Stick .ogg to the end and try again
625                                 memcpy(filename,namebuffer,len);
626                                 memcpy(filename+len-4,".ogg",5);
627                                 data = FS_LoadFile(filename, snd_mempool, false, &filesize);
628                                 if(data) memcpy(fileext,"ogg",3);
629                         }
630                 }
631                 if(!data){
632                         // LordHavoc: then try without the added sound/ as wav and ogg
633                         len = dpsnprintf (namebuffer, sizeof(namebuffer), "%s", sfx->name);
634                         if (len < 0){ // name too long
635                                 Con_DPrintf("S_LoadSound: name \"%s\" is too long\n", sfx->name);
636                                 return false;
637                         }
638                         if(!data){
639                                 data = FS_LoadFile(namebuffer, snd_mempool, false, &filesize);
640                                 if(data) memcpy(fileext,namebuffer+len-3,3); //Copy the file extention
641                         }
642                         if(!data){ //Stick .wav to the end
643                                 memcpy(filename,namebuffer,len);
644                                 memcpy(filename+len-4,".wav",5);
645                                 data = FS_LoadFile(filename, snd_mempool, false, &filesize);
646                                 if(data) memcpy(fileext,"wav",3);
647                         }
648                         if(!data){ //Stick .ogg to the end
649                                 memcpy(filename,namebuffer,len);
650                                 memcpy(filename+len-4,".ogg",5);
651                                 data = FS_LoadFile(filename, snd_mempool, false, &filesize);
652                                 if(data) memcpy(fileext,"ogg",3);
653                         }
654                 }
655                 if (!data){
656                         if(complain) Con_Printf("Failed attempt load file '%s'\n",namebuffer);
657                 }else{ //if the file loaded: pass to RAS 3D
658                         file_ptr=ras_fileinputwhole_new(data,filesize);
659                         // There we transfered to file to RAS 3D
660                         // So lets free up data shall we ?
661                         FS_Close(data);
662
663                         if(!file_ptr){
664                                 Con_Printf("Failed to upload file to audio lib\n");
665                         }else{
666                                 if(0==strncasecmp(fileext,"wav",3)){
667                                         decoder_ptr=ras_audiodecoderwav_new(file_ptr,true); //(true)use seek mode: some quake files are broken.
668                                 }
669                                 if(0==strncasecmp(fileext,"ogg",3)){
670                                         decoder_ptr=ras_audiodecoderogg_new(file_ptr);
671                                 }
672                                 if(!decoder_ptr){
673                                         Con_Printf("File succeeded to load, but no decoder available for '%s'\n",fileext);
674                                 }else{
675                                         #ifdef RAS_PRINT
676                                         Con_Printf("ToDo: Add a cvar to configure the cache size and number of cache blocks.\n");
677                                         Con_Printf("ToDo: Add support for looping sounds.\n");
678                                         #endif
679                                         sfx->rasptr=ras_sounddataoneshot_new(decoder_ptr,0.05,8);
680                                 }
681                                 file_ptr=ras_delete(file_ptr);
682                         }
683                         return !(sfx->rasptr);
684                 }
685                 return false;
686         }
687         return false;
688 }
689 sfx_t *S_PrecacheSound (const char *name, qboolean complain, qboolean serversound){
690         sfx_t *sfx;
691         if(ras_version>0 && ras_dll){
692                 #ifdef RAS_PRINT
693                 Con_Printf("Called S_PrecacheSound %s, %i, %i\n",name,complain,serversound);
694                 #endif
695                 if (name == NULL || name[0] == 0)
696                         return NULL;
697                 sfx = S_FindName (name);
698                 if (sfx == NULL) return NULL;
699                 if (lock) ++(sfx->locks);
700                 if (snd_precache.integer) S_LoadSound(sfx, complain);
701                 return sfx;
702         }
703         return NULL;
704 }
705 void S_ClearUsed (void){
706         sfx_t *prev_s, *now_s;
707         unsigned int i;
708
709         if(ras_version>0 && ras_dll){
710                 Con_Printf("Called S_ClearUsed\n");
711                 for(i=0;i<numsounds;++i){
712                         Con_Printf("Loading :'%s'\n",serversound[i]);
713                         // Load the ambient sounds
714
715                         Con_Printf("ToDo: Load abmient sounds (Need geometry).\n");
716
717                         // Remove the SFXFLAG_SERVERSOUND flag
718                         sfx_begin(&prev_s,&now_s);
719                         while(now_s){
720                                 if (now_s->flags & SFXFLAG_SERVERSOUND) now_s->flags &= ~SFXFLAG_SERVERSOUND;
721                                 sfx_next(&prev_s,&now_s);
722                         }
723                 }
724         }
725 }
726 void S_PurgeUnused(void){
727         Free_Unlocked_Sfx();
728 }
729 qboolean S_IsSoundPrecached (const sfx_t *sfx){
730         if(ras_version>0 && ras_dll){
731                 return !sfx->rasptr;
732         }
733         return 0;
734 }
735
736 void S_KillChannel (channel_t *now){ //Silences a SoundEvent
737         if(now->rasptr){
738                 ras_soundevent_setsoundpower(now->rasptr,0);
739                 ras_delete(now->rasptr);
740                 now->rasptr=0;
741         }else{
742                 Con_Printf("S_KillChannel: Warning pointer was 0 ... this indicates a bug.\n");
743         }
744 }
745
746 int S_StartSound_OnEnt (int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation){
747          entnum_t *prev_e, *now_e;
748         channel_t *prev_c, *now_c;
749         Location tmp_location[3];
750
751         //If there is a game world
752         if(!cl.entities){
753                 Con_Printf("S_StartSound_OnEnt: no entity list exists\n");
754                 return -1;
755         }
756
757         // Look for the correct ent_t
758         entnum_begin(&prev_e,&now_e);
759         while(now_e){
760                 if(now_e->entnum==entnum) break;
761                 entnum_next(&prev_e,&now_e);
762         }
763         //We found no ent ...  lets make one...
764         if(!now_e){
765                 entnum_new(&prev_e,&now_e);
766                 if(!now_e){
767                         Con_Printf("S_StartSound_OnEnt: could not make new entnum_t\n");
768                         return -1;
769                 }
770                 VectorCopy(cl.entities[entnum].state_current.origin, now_e->lastloc);
771                 DP_To_Ras_Location(now_e->lastloc,tmp_location);
772                 now_e->rasptr=ras_soundsource_new(soundworld,1.0,tmp_location);
773                 if(!now_e->rasptr){
774                         Con_Printf("S_StartSound_OnEnt: could not create a new sound source\n");
775                         return -1;
776                 }
777         }
778
779         //Ok now lets look for the channel.
780         channel_begin(&prev_c,&now_c);
781         while(now_c){
782                 if(
783                         now_c->entnum==entnum &&
784                         now_c->entchannel==entchannel
785                 ) break;
786                 channel_next(&prev_c,&now_c);
787         }
788         
789         if(now_c){ //O dear the channel excists ....
790                 S_KillChannel(now_c);
791         }else{ //We found no channel .... So we need to make a new one ...
792                 channel_new_smart(&prev_c,&now_c);
793                 now_c->entnum    =entnum;
794                 now_c->entchannel=entchannel;
795                 if(!now_c){
796                         Con_Printf("S_StartSound_OnEnt: could not make new channel_t\n");
797                         channel_delete_and_next(&prev_c,&now_c);
798                         return -1;
799                 }
800         }
801
802         //Lets start the sound on the acquired sound source and channel
803         now_c->rasptr=ras_soundevent_new(
804                 soundworld,now_e->rasptr,sfx->rasptr,fvol*DP_Ras_VolumeScale,1.0
805         );
806         if(!now_c->rasptr){ //Whoops, failed, lets delete this channel then.
807                 channel_delete_and_next(&prev_c,&now_c);
808                 Con_Printf("S_StartSound_OnEnt: could not make a new soundevent.\n");
809                 return -1;
810         }
811         return now_c->id;
812 }
813 int S_StartSound_OnLocation (sfx_t *sfx, vec3_t origin, float fvol, float attenuation){
814          entnum_t *prev_e, *now_e;
815         channel_t *prev_c, *now_c;
816         Location tmp_location[3];
817         DP_To_Ras_Location(origin,tmp_location);
818         
819          entnum_new      (&prev_e,&now_e);
820         VectorCopy(now_e->lastloc,origin);
821         now_e->entnum=-1;
822         now_e->rasptr=ras_soundsource_new(soundworld,1.0,tmp_location);
823         if(!now_e->rasptr){
824                 Con_Printf("S_StartSound_OnLocation: Could not make a new soundsource.\n");
825                 entnum_delete_and_next(&prev_e,&now_e);
826                 return -1;
827         }
828         channel_new_smart(&prev_c,&now_c);
829         now_c->entnum=-1;
830         now_c->entchannel=-1;
831         now_c->rasptr =ras_soundevent_new(soundworld,now_e->rasptr,sfx->rasptr,fvol*DP_Ras_VolumeScale,1.0);
832         if(!now_c->rasptr){
833                  entnum_delete_and_next(&prev_e,&now_e);
834                 channel_delete_and_next(&prev_c,&now_c);
835                 Con_Printf("S_StartSound_OnLocation: Could not make a new soundevent.\n");
836                 return -1;
837         }
838         return now_c->id;
839 }
840
841
842 // Qantourisc on the wicked-quake-sound-system:
843 // --------------------------------------------
844 // entnum can be Zero or lower => This means "use the origin" so it's not tracked.
845 // entnum -1 is a "world" containing more then 1 soundsource.
846 // If channel !=  0 try to overwrite the requested channel. Otherwise play it on some random channel.
847 // If channel == -1 overwrite the first track of the ent.
848 // If a channel replacement is requested, only allow overwriting if it's owned by the same channel.
849 // If no channel can be replaced, pick a new one.
850 // Also when you overwrite a channel, that one has to stop dead.
851 // This function returns the channel it was played on (so it can be stopped later)
852 // This starts CD-music: S_StartSound (-1, 0, sfx, vec3_origin, cdvolume, 0);
853 // The channel you return then, can later be requested to be stopped.
854
855 int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation){
856         sfx_t *prev_s,*now_s;
857         int sfx_ok;
858         if(ras_version>0 && ras_dll && soundworld){
859                 #ifdef RAS_PRINT
860                 Con_Printf("Called S_StartSound %i, %i, %f, %f\n",entnum,entchannel,fvol,attenuation);
861                 #endif
862                 if(sfx==NULL){ // They pass this to me ... but WHY ? it makes no sense !
863                         #ifdef RAS_PRINT
864                         Con_Printf("S_StartSound: forgot to mention a sfx!\n");
865                         #endif
866                         return -1;
867                 }
868
869                 sfx_ok=0;
870                 sfx_begin(&prev_s,&now_s);
871                 while(now_s){
872                         if(now_s==sfx){
873                                 sfx_ok=1;
874                                 break;
875                         }
876                         sfx_next(&prev_s,&now_s);
877                 }
878                 if(!sfx_ok){
879                         Con_Printf("S_StartSound: passed illegal sfx_t!\n");
880                         return -1;
881                 }
882                 if (!S_LoadSound(sfx,true)) return -1;
883
884
885                 if(entnum!=-1){ //If we are talking about an ent
886                         return S_StartSound_OnEnt(entnum,entchannel,sfx,fvol,attenuation);
887                 }else{
888                         return S_StartSound_OnLocation(      sfx,origin,fvol,attenuation);
889                 }
890         }
891         Con_Printf("S_StartSound: engine not stated\n");
892         return -1;
893 }
894 qboolean S_LocalSound (const char *s){
895         sfx_t   *sfx;
896         int             ch_ind;
897         if(ras_version>0 && ras_dll){
898                 #ifdef RAS_PRINT
899                 Con_Printf("Called S_LocalSound %s\n",s);
900                 #endif
901
902                 sfx = S_PrecacheSound (s, true, true);
903                 if (!sfx)
904                 {
905                         Con_Printf("S_LocalSound: can't precache %s\n", s);
906                         return false;
907                 }
908
909                 // Local sounds must not be freed
910                 sfx->flags |= SFXFLAG_PERMANENTLOCK;
911                 #ifdef RAS_PRINT
912                 Con_Printf("S_LocalSound: this is still a small hack\n");
913                 #endif
914                 ch_ind = S_StartSound (cl.viewentity, 0, sfx, listener_location, 1, 0);
915                 if (ch_ind < 0)
916                         return false;
917
918                 //channels[ch_ind].flags |= CHANNELFLAG_LOCALSOUND;
919                 return true;
920         }
921         return 0;
922 }
923 void S_StaticSound (sfx_t *sfx, vec3_t origin, float fvol, float attenuation){
924         //Static sounds should not be looped
925         if(ras_version>0 && ras_dll){
926                 #ifdef RAS_PRINT
927                 Con_Printf("Called S_StaticSound\n");
928                 Con_Printf("Waiting on Qantourisc to add Static sounds in his lib.\n");
929                 #endif
930                 //Static sounds are sounds that are not pauzed, and or played locally.
931         }
932 }
933 void S_StopSound (int entnum, int entchannel){
934         channel_t *prev, *now;
935         if(ras_version>0 && ras_dll){
936                 //Con_Printf("Called S_StopSound %i, %i\n",entnum,entchannel);
937                 channel_begin(&prev,&now);
938                 while(now){
939                         if(now->entnum==entnum && now->entchannel==entchannel) break;
940                         channel_next(&prev,&now);
941                 }
942                 if(now){ //If we found our to delete sound.
943                         S_KillChannel(now);
944                         channel_delete_and_next(&prev,&now);
945                 }else{
946                         Con_Printf("S_StopSound: Could not find the requested entnum-entchannel sound\n");
947                 }
948         }
949 }
950 void S_StopAllSounds (void){
951         channel_t *prev, *now;
952         if(ras_version>0 && ras_dll){
953                 //Con_Printf("Called S_StopAllSounds\n");
954                 channel_begin(&prev,&now);
955                 while(now){
956                         S_KillChannel(now);
957                         channel_next(&prev,&now);
958                 }
959         }
960 }
961 void S_PauseGameSounds (qboolean toggle){
962         if(ras_version>0 && ras_dll){
963                 Con_Printf("Called S_PauseGameSounds %i\n",toggle);
964                 //Localsounds should not be pauzed
965         }
966 }
967 void S_StopChannel (unsigned int channel_ind){
968         channel_t *prev,*now;
969         if(ras_version>0 && ras_dll){
970                 channel_begin(&prev,&now);
971                 while(now){
972                         if(now->id==channel_ind){
973                                 S_KillChannel(now);
974                                 channel_delete_and_next(&prev,&now);
975                         }else{
976                                 channel_next(&prev,&now);
977                         }
978                 }
979         }
980 }
981 qboolean S_SetChannelFlag (unsigned int ch_ind, unsigned int flag, qboolean value){
982         if(ras_version>0 && ras_dll){
983                 Con_Printf("Called S_SetChannelFlag %u, %u, %i\n",ch_ind, flag, value);
984         }
985         return 0;
986 }
987 void S_SetChannelVolume (unsigned int ch_ind, float fvol){
988         channel_t *prev,*now;
989         if(ras_version>0 && ras_dll){
990                 Con_Printf("Called S_SetChannelVolume %u, %f\n",ch_ind, fvol);
991                 channel_begin(&prev,&now);
992                 while(now){
993                         if(now->id==ch_ind){
994                                 if(now->rasptr){
995                                         ras_soundevent_setsoundpower(now->rasptr,fvol*DP_Ras_VolumeScale);
996                                 }else{
997                                         Con_Printf("S_StopChannel: Warning pointer was 0 ... this indicates a bug.\n");
998                                 }
999                         }
1000                         channel_next(&prev,&now);
1001                 }
1002         }
1003 }
1004
1005 float S_GetChannelPosition (unsigned int ch_ind)
1006 {
1007         // FIXME unsupported
1008         return -1;
1009 }
1010
1011 void S_BlockSound (void){
1012         soundblocked++;
1013 }
1014 void S_UnblockSound (void){
1015         soundblocked--;
1016         if(soundblocked<0){
1017                 Con_Printf("S_UnblockSound: Requested more S_UnblockSound then S_BlockSound.\n");
1018         }
1019 }
1020
1021 int S_GetSoundRate (void){
1022         Con_Printf("Inside 3DRAS, the soundrate of the end-user is NONE of the dev's concern.\n");
1023         Con_Printf("So let's assume 44100.\n");
1024         return 44100;
1025 }
1026
1027 int S_GetSoundChannels (void){
1028         Con_Printf("Inside 3DRAS, the soundrate of the end-user is NONE of the dev's concern.\n");
1029         Con_Printf("So let's assume 2.\n");
1030         return 2;
1031 }