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