34 #include <libFreeWRL.h>
36 #include "../vrml_parser/Structs.h"
37 #include "../vrml_parser/CRoutes.h"
38 #include "../main/headers.h"
39 #include "../opengl/OpenGL_Utils.h"
41 #include "LinearAlgebra.h"
54 device = alcOpenDevice(NULL);
57 fprintf(stderr,
"Could not open a device!\n");
61 ctx = alcCreateContext(device, NULL);
62 if(ctx == NULL || alcMakeContextCurrent(ctx) == ALC_FALSE)
65 alcDestroyContext(ctx);
66 alcCloseDevice(device);
67 fprintf(stderr,
"Could not set a context!\n");
71 printf(
"Opened \"%s\"\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
77 void fwCloseAL(
void *alctx)
87 device = alcGetContextsDevice(ctx);
89 alcMakeContextCurrent(NULL);
90 alcDestroyContext(ctx);
91 alcCloseDevice(device);
100 int SoundSourceNumber;
105 float AC_LastDuration[50];
107 void *Component_Sound_constructor(){
112 void Component_Sound_init(
struct tComponent_Sound *t){
116 t->sound_from_audioclip= 0;
119 t->SoundEngineStarted = FALSE;
121 t->prv = Component_Sound_constructor();
125 p->soundWarned = FALSE;
126 p->SoundSourceNumber = 0;
134 p->AC_LastDuration[i] = -1.0f;
139 void Sound_toserver(
char *message)
143 float ListenerPos[] = { 0.0, 0.0, 0.0 };
145 float ListenerVel[] = { 0.0, 0.0, 0.0 };
147 float ListenerOri[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 };
149 int SoundEngineInit(
void)
160 ConsoleMessage(
"initAL failed\n");
163 p->alContext = alctx;
165 if(!alutInitWithoutContext(NULL,NULL))
167 ALenum error = alutGetError ();
168 ConsoleMessage(
"%s\n", alutGetErrorString (error));
178 alListenerfv(AL_POSITION, ListenerPos);
179 alListenerfv(AL_VELOCITY, ListenerVel);
180 alListenerfv(AL_ORIENTATION, ListenerOri);
184 alSpeedOfSound(345.0f);
186 alSpeedOfSound(1132.0f);
187 alDopplerFactor(1.0f);
190 alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
194 gglobal()->Component_Sound.SoundEngineStarted = retval;
198 void waitformessage(
void)
201 void SoundEngineDestroy(
void)
204 int SoundSourceRegistered(
int num)
206 if(num > -1)
return TRUE;
210 float SoundSourceInit(
int num,
int loop,
double pitch,
double start_time,
double stop_time,
char *url)
213 void SetAudioActive(
int num,
int stat)
217 int haveSoundEngine(){
220 if (!tg->Component_Sound.SoundEngineStarted) {
222 printf (
"SetAudioActive: initializing SoundEngine\n");
224 tg->Component_Sound.SoundEngineStarted = SoundEngineInit();
226 return tg->Component_Sound.SoundEngineStarted;
230 OLDCODEvoid render_AudioControl (
struct X3D_AudioControl *node) {
231 OLDCODE GLDOUBLE mod[16];
232 OLDCODE GLDOUBLE proj[16];
233 OLDCODE
struct point_XYZ vec, direction, location;
235 OLDCODE
double angle;
236 OLDCODE
float midmin, midmax;
243 OLDCODE
if (!node)
return;
244 OLDCODE
if (node->__oldEnabled != node->enabled) {
245 OLDCODE node->__oldEnabled = node->enabled;
246 OLDCODE MARK_EVENT(X3D_NODE(node),offsetof (
struct X3D_AudioControl, enabled));
248 OLDCODE
if (!node->enabled)
return;
250 OLDCODE direction.x = node->direction.c[0];
251 OLDCODE direction.y = node->direction.c[1];
252 OLDCODE direction.z = node->direction.c[2];
254 OLDCODE location.x = node->location.c[0];
255 OLDCODE location.y = node->location.c[1];
256 OLDCODE location.z = node->location.c[2];
258 OLDCODE midmin = (node->minFront - node->minBack) / (
float) 2.0;
259 OLDCODE midmax = (node->maxFront - node->maxBack) / (
float) 2.0;
262 OLDCODE FW_GL_PUSH_MATRIX();
272 OLDCODE FW_GL_TRANSLATE_D (location.x + midmax*direction.x,
273 OLDCODE location.y + midmax*direction.y,
274 OLDCODE location.z + midmax * direction.z);
280 OLDCODE
if ((fabs(node->minFront - node->minBack) > 0.5) ||
281 OLDCODE (fabs(node->maxFront - node->maxBack) > 0.5)) {
282 OLDCODE
if (!soundWarned) {
283 OLDCODE printf (
"FreeWRL:Sound: Warning - minBack and maxBack ignored in this version\n");
284 OLDCODE soundWarned = TRUE;
290 OLDCODE FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mod);
291 OLDCODE FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX, proj);
292 OLDCODE FW_GLU_UNPROJECT(viewport[2]/2,viewport[3]/2,0.0,
293 OLDCODE mod,proj,viewport, &vec.x,&vec.y,&vec.z);
297 OLDCODE len = sqrt(VECSQ(vec));
304 OLDCODE
if (len < 0.001) angle = 0;
306 OLDCODE
if (APPROX (mod[12],0)) {
308 OLDCODE mod[12] = 0.001;
310 OLDCODE angle = fabs(atan2(mod[14],mod[12])) - (PI/2.0);
311 OLDCODE angle = angle/(PI/2.0);
318 OLDCODE angle = angle / 1.5;
321 OLDCODE angle = angle + 0.5;
324 OLDCODE angle = 1.0 - angle;
327 OLDCODE
if (angle > 1.0) angle = 1.0;
328 OLDCODE
if (angle < 0.0) angle = 0.0;
330 OLDCODE #ifdef SOUNDVERBOSE
331 OLDCODE printf (
"angle: %f\n",angle);
336 OLDCODE node->panFloatVal = (float) angle;
337 OLDCODE node->panInt32Val = (int) (angle * 128);
338 OLDCODE
if (node->panInt32Val < 0) node->panInt32Val = 0;
if (node->panInt32Val > 127) node->panInt32Val = 127;
341 OLDCODE node->volumeFloatVal = (float) 0.0;
345 OLDCODE
if (len < node->maxFront) {
347 OLDCODE
if (!node->isActive) {
348 OLDCODE node->isActive = TRUE;
349 OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, isActive));
350 OLDCODE #ifdef SOUNDVERBOSE
351 OLDCODE printf (
"AudioControl node is now ACTIVE\n");
356 OLDCODE node->__oldLen = len;
361 OLDCODE
if (len < 0.0) {
362 OLDCODE
if (len < node->minBack) {node->volumeFloatVal = (float) 1.0;}
363 OLDCODE
else { node->volumeFloatVal = ((float) len - node->maxBack) / (node->maxBack - node->minBack); }
365 OLDCODE
if (len < node->minFront) {node->volumeFloatVal = (float) 1.0;}
366 OLDCODE
else { node->volumeFloatVal = (node->maxFront - (float) len) / (node->maxFront - node->minFront); }
370 OLDCODE
if (APPROX(node->maxDelta, 0.0)) {
371 OLDCODE printf (
"AudioControl: maxDelta approaches zero!\n");
372 OLDCODE node->deltaFloatVal = (float) 0.0;
374 OLDCODE #ifdef SOUNDVERBOSE
375 OLDCODE printf (
"maxM/S %f \n",(node->__oldLen - len)/ (TickTime()- lastTime));
381 OLDCODE node->deltaFloatVal = (float) ((node->__oldLen - len)/(TickTime()-lastTime()))/node->maxDelta;
382 OLDCODE
if (node->deltaFloatVal < (
float) -1.0) node->deltaFloatVal = (float) -1.0;
if (node->deltaFloatVal > (
float) 1.0) node->deltaFloatVal = (float) 1.0;
383 OLDCODE node->__oldLen = len;
388 OLDCODE node->volumeFloatVal = node->volumeFloatVal*node->intensity;
389 OLDCODE node->volumeInt32Val = (int) (node->volumeFloatVal * 128.0);
390 OLDCODE
if (node->volumeInt32Val < 0) node->volumeInt32Val = 0;
if (node->volumeInt32Val > 127) node->volumeInt32Val = 127;
392 OLDCODE node->deltaInt32Val = (int) (node->deltaFloatVal * 64.0) + 64;
393 OLDCODE
if (node->deltaInt32Val < 0) node->deltaInt32Val = 0;
if (node->deltaInt32Val > 127) node->deltaInt32Val = 127;
395 OLDCODE #ifdef SOUNDVERBOSE
396 OLDCODE printf (
"AudioControl: amp: %f (%d) angle: %f (%d) delta: %f (%d)\n",node->volumeFloatVal,node->volumeInt32Val,
397 OLDCODE node->panFloatVal, node->panInt32Val ,node->deltaFloatVal,node->deltaInt32Val);
400 OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, volumeInt32Val));
401 OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, volumeFloatVal));
402 OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, panInt32Val));
403 OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, panFloatVal));
404 OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, deltaInt32Val));
405 OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, deltaFloatVal));
409 OLDCODE
if (node->isActive) {
410 OLDCODE node->isActive = FALSE;
411 OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, isActive));
412 OLDCODE #ifdef SOUNDVERBOSE
413 OLDCODE printf (
"AudioControl node is now INACTIVE\n");
418 OLDCODE FW_GL_POP_MATRIX();
422 #define LOAD_INITIAL_STATE 0
423 #define LOAD_REQUEST_RESOURCE 1
424 #define LOAD_FETCHING_RESOURCE 2
426 #define LOAD_STABLE 10
433 switch (node->__loadstatus) {
434 case LOAD_INITIAL_STATE:
436 if (node->url.n == 0) {
437 node->__loadstatus = LOAD_STABLE;
440 res = resource_create_multi(&(node->url));
441 if(node->_nodeType == NODE_MovieTexture)
442 res->media_type = resm_movie;
444 res->media_type = resm_audio;
445 node->__loadstatus = LOAD_REQUEST_RESOURCE;
446 node->__loadResource = res;
451 case LOAD_REQUEST_RESOURCE:
452 res = node->__loadResource;
453 resource_identify(node->_parentResource, res);
454 res->actions = resa_download | resa_load;
455 res->ectx = (
void*)node->_executionContext;
456 res->whereToPlaceData = X3D_NODE(node);
458 resitem_enqueue(ml_new(res));
459 node->__loadstatus = LOAD_FETCHING_RESOURCE;
463 case LOAD_FETCHING_RESOURCE:
464 res = node->__loadResource;
468 if (res->status == ress_loaded) {
469 res->actions = resa_process;
470 res->complete = FALSE;
471 resitem_enqueue(ml_new(res));
472 }
else if ((res->status == ress_failed) || (res->status == ress_invalid)) {
474 printf (
"resource failed to load\n");
475 node->__loadstatus = LOAD_STABLE;
476 node->__sourceNumber = BADAUDIOSOURCE;
477 }
else if (res->status == ress_parsed) {
478 node->__loadstatus = LOAD_STABLE;
493 if(node->__loadstatus > LOAD_INITIAL_STATE && node->__loadstatus < LOAD_STABLE)
495 if(node->__loadstatus == LOAD_STABLE)
506 if (node->__loadstatus != LOAD_STABLE) {
507 locateAudioSource (node);
509 if(node->__loadstatus != LOAD_STABLE)
return;
513 if (node->__sourceNumber == BADAUDIOSOURCE)
return;
517 #ifdef HAVE_OLDSOUND //MUST_RE_IMPLEMENT_SOUND_WITH_OPENAL
519 float pitch,stime, sttime;
521 int sound_from_audioclip;
522 unsigned char *filename = (
unsigned char *)node->__localFileName;
526 sound_from_audioclip = TRUE;
530 if(!haveSoundEngine())
return;
533 if (node->isActive == 0)
return;
536 if (!SoundSourceRegistered(node->__sourceNumber)) {
543 stime = node->startTime;
544 sttime = node->stopTime;
547 p->AC_LastDuration[node->__sourceNumber] =
548 SoundSourceInit (node->__sourceNumber, node->loop,
549 (
double) pitch,(
double) stime, (
double) sttime, filename);
558 void render_Sound (
struct X3D_Sound *node) {
565 int sound_from_audioclip;
573 if (node->source == NULL)
579 POSSIBLE_PROTO_EXPANSION(
struct X3D_Node *, node->source,tmpN)
582 if (tmpN == NULL) return;
584 sound_from_audioclip = FALSE;
585 if (tmpN->_nodeType == NODE_AudioClip) {
587 sound_from_audioclip = TRUE;
588 }
else if (tmpN->_nodeType == NODE_MovieTexture){
593 ConsoleMessage (
"Sound node- source type of %s invalid",stringNodeType(tmpN->_nodeType));
607 if(haveSoundEngine()){
608 if( acp->__sourceNumber < 0){
609 render_AudioClip(acp);
611 if( acp->__sourceNumber > -1 ){
614 GLDOUBLE modelMatrix[16];
615 GLDOUBLE SourcePosd[3] = { 0.0f, 0.0f, 0.0f };
616 ALfloat SourcePos[3];
619 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, modelMatrix);
620 transformAFFINEd(SourcePosd,SourcePosd,modelMatrix);
621 for(i=0;i<3;i++) SourcePos[i] = (ALfloat)SourcePosd[i];
623 if( node->__sourceNumber < 0){
627 alGenSources(1, &source);
628 alSourcei(source, AL_BUFFER, acp->__sourceNumber);
629 alSourcef (source, AL_PITCH, acp->pitch);
630 alSourcef (source, AL_GAIN, node->intensity );
631 alSourcei (source, AL_LOOPING, acp->loop);
632 alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE);
634 alSourcef (source, AL_MAX_DISTANCE, node->maxFront);
637 node->__lasttime = TickTime();
638 veccopy3f(node->__lastlocation.c,SourcePos);
640 node->__sourceNumber = source;
642 if(alGetError()!=AL_NO_ERROR) {
645 ConsoleMessage(
"Failed to setup sound source\n");
648 node->__sourceNumber = BADAUDIOSOURCE;
651 if( node->__sourceNumber > -1){
653 ALfloat SourceVel[3] = { 0.0f, 0.0f, 0.0f };
658 alSourcefv(node->__sourceNumber, AL_POSITION, SourcePos);
661 vecdif3f(travelled,node->__lastlocation.c,SourcePos);
662 traveltime = TickTime() - node->__lasttime;
664 vecscale3f(SourceVel,travelled,1.0f/(
float)traveltime);
665 alSourcefv(node->__sourceNumber, AL_VELOCITY, SourceVel);
667 node->__lasttime = TickTime();
668 veccopy3f(node->__lastlocation.c,SourcePos);
674 if(node->spatialize){
678 for(i=0;i<3;i++) dird[i] = node->direction.c[i];
679 transformAFFINEd(dird,dird,modelMatrix);
680 for(i=0;i<3;i++) dirf[i] = (
float)dird[i];
682 alSourcefv(node->__sourceNumber, AL_DIRECTION, dirf);
684 alSource3f(node->__sourceNumber, AL_DIRECTION, dirf[0], dirf[1], dirf[2]);
685 alSourcef(node->__sourceNumber, AL_CONE_OUTER_GAIN, .5f);
686 alSourcef(node->__sourceNumber,AL_CONE_INNER_ANGLE,90.0f);
687 alSourcef(node->__sourceNumber,AL_CONE_OUTER_ANGLE,135.0f);
691 alSourcef (node->__sourceNumber, AL_PITCH, acp->pitch);
692 alSourcef (node->__sourceNumber, AL_GAIN, node->intensity );
693 alSourcei (node->__sourceNumber, AL_LOOPING, acp->loop);
695 if(acp->isPaused) alSourcePause(node->__sourceNumber);
697 alGetSourcei(node->__sourceNumber, AL_SOURCE_STATE,&istate);
699 if(istate != AL_PLAYING && !acp->isPaused){
700 alSourcePlay(node->__sourceNumber);
704 if(istate != AL_STOPPED)
705 alSourceStop(node->__sourceNumber);
713 #ifdef HAVE_OLDSOUND //MUST_RE_IMPLEMENT_SOUND_WITH_OPENAL
722 struct point_XYZ vec, direction, location;
725 float midmin, midmax;
733 render_node(X3D_NODE(acp));
737 if (acp->isActive == 0)
return;
739 direction.x = node->direction.c[0];
740 direction.y = node->direction.c[1];
741 direction.z = node->direction.c[2];
743 location.x = node->location.c[0];
744 location.y = node->location.c[1];
745 location.z = node->location.c[2];
747 midmin = (node->minFront - node->minBack) / 2.0;
748 midmax = (node->maxFront - node->maxBack) / 2.0;
761 FW_GL_TRANSLATE_F (location.x + midmax*direction.x,
762 location.y + midmax*direction.y,
763 location.z + midmax * direction.z);
769 if ((fabs(node->minFront - node->minBack) > 0.5) ||
770 (fabs(node->maxFront - node->maxBack) > 0.5)) {
771 if (!p->soundWarned) {
772 printf (
"FreeWRL:Sound: Warning - minBack and maxBack ignored in this version\n");
773 p->soundWarned = TRUE;
779 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mod);
780 FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX, proj);
781 FW_GLU_UNPROJECT(viewport[2]/2,viewport[3]/2,0.0,
782 mod,proj,viewport, &vec.x,&vec.y,&vec.z);
786 len = sqrt(VECSQ(vec));
793 if (len < 0.001) angle = 0;
795 if (APPROX (mod[12],0)) {
799 angle = fabs(atan2(mod[14],mod[12])) - (PI/2.0);
800 angle = angle/(PI/2.0);
813 if (angle > 1.0) angle = 1.0;
814 if (angle < 0.0) angle = 0.0;
824 if (len < node->maxFront) {
829 if (len < node->minBack) {amp = 1.0;}
831 amp = (len - node->maxBack) / (node->maxBack - node->minBack);
834 if (len < node->minFront) {amp = 1.0;}
836 amp = (node->maxFront - len) / (node->maxFront - node->minFront);
842 amp = amp*node->intensity;
843 if (sound_from_audioclip) {
844 sprintf (mystring,
"AMPL %d %f %f",acp->__sourceNumber,amp,angle);
846 sprintf (mystring,
"MMPL %d %f %f",mcp->__textureTableIndex, amp, angle);
848 Sound_toserver(mystring);
856 int parse_audioclip(
struct X3D_AudioClip *node,
char *bbuffer,
int len){
858 ALint buffer = AL_NONE;
860 buffer = alutCreateBufferFromFileImage (bbuffer, len);
863 if (buffer == AL_NONE)
864 buffer = BADAUDIOSOURCE;
866 int buffer = BADAUDIOSOURCE;
872 double compute_duration(
int ibuffer){
880 double framesizebytes, bytespersecond;
881 alGetBufferi(ibuffer,AL_FREQUENCY,&ifreq);
882 alGetBufferi(ibuffer,AL_BITS,&ibits);
883 alGetBufferi(ibuffer,AL_CHANNELS,&ichannels);
884 alGetBufferi(ibuffer,AL_SIZE,&ibytes);
885 framesizebytes = (double)(ibits * ichannels)/8.0;
886 bytespersecond = framesizebytes * (double)ifreq;
887 if(bytespersecond > 0.0)
888 retval = (double)(ibytes) / bytespersecond;
895 double stime, sttime;
898 stime = node->startTime;
899 sttime = node->stopTime;
902 retval = SoundSourceInit (ibuffer, node->loop,
903 (
double) pitch,(
double) stime, (
double) sttime, filename);
924 buffer = res->URLrequest;
936 of = res->openned_files;
942 buffer = of->fileData;
943 len = of->fileDataSize;
949 node->__sourceNumber = parse_audioclip(node,buffer,len);
950 if(node->__sourceNumber > -1) {
951 node->duration_changed = compute_duration(node->__sourceNumber);
952 MARK_EVENT (X3D_NODE(node), offsetof(
struct X3D_AudioClip, duration_changed));
963 indx = node->__sourceNumber;
964 if (indx < 0) retval = 1.0;
965 else if (indx > 50) retval = 1.0;
969 retval = node->duration_changed;
972 retval = p->AC_LastDuration[indx];