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