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));
77void fwCloseAL(
void *alctx)
87 device = alcGetContextsDevice(ctx);
89 alcMakeContextCurrent(NULL);
90 alcDestroyContext(ctx);
91 alcCloseDevice(device);
100 int SoundSourceNumber;
105 float AC_LastDuration[50];
107void *Component_Sound_constructor(){
112void 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;
139void Sound_toserver(
char *message)
143float ListenerPos[] = { 0.0, 0.0, 0.0 };
145float ListenerVel[] = { 0.0, 0.0, 0.0 };
147float ListenerOri[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 };
149int 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;
198void waitformessage(
void)
201void SoundEngineDestroy(
void)
204int SoundSourceRegistered(
int num)
206 if(num > -1)
return TRUE;
210float SoundSourceInit(
int num,
int loop,
double pitch,
double start_time,
double stop_time,
char *url)
213void SetAudioActive(
int num,
int stat)
217int 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;
230OLDCODEvoid render_AudioControl (
struct X3D_AudioControl *node) {
231OLDCODE GLDOUBLE mod[16];
232OLDCODE GLDOUBLE proj[16];
233OLDCODE
struct point_XYZ vec, direction, location;
236OLDCODE
float midmin, midmax;
243OLDCODE
if (!node)
return;
244OLDCODE
if (node->__oldEnabled != node->enabled) {
245OLDCODE node->__oldEnabled = node->enabled;
246OLDCODE MARK_EVENT(X3D_NODE(node),offsetof (
struct X3D_AudioControl, enabled));
248OLDCODE
if (!node->enabled)
return;
250OLDCODE direction.x = node->direction.c[0];
251OLDCODE direction.y = node->direction.c[1];
252OLDCODE direction.z = node->direction.c[2];
254OLDCODE location.x = node->location.c[0];
255OLDCODE location.y = node->location.c[1];
256OLDCODE location.z = node->location.c[2];
258OLDCODE midmin = (node->minFront - node->minBack) / (
float) 2.0;
259OLDCODE midmax = (node->maxFront - node->maxBack) / (
float) 2.0;
262OLDCODE FW_GL_PUSH_MATRIX();
272OLDCODE FW_GL_TRANSLATE_D (location.x + midmax*direction.x,
273OLDCODE location.y + midmax*direction.y,
274OLDCODE location.z + midmax * direction.z);
280OLDCODE
if ((fabs(node->minFront - node->minBack) > 0.5) ||
281OLDCODE (fabs(node->maxFront - node->maxBack) > 0.5)) {
282OLDCODE
if (!soundWarned) {
283OLDCODE printf (
"FreeWRL:Sound: Warning - minBack and maxBack ignored in this version\n");
284OLDCODE soundWarned = TRUE;
290OLDCODE FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mod);
291OLDCODE FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX, proj);
292OLDCODE FW_GLU_UNPROJECT(viewport[2]/2,viewport[3]/2,0.0,
293OLDCODE mod,proj,viewport, &vec.x,&vec.y,&vec.z);
297OLDCODE len = sqrt(VECSQ(vec));
304OLDCODE
if (len < 0.001) angle = 0;
306OLDCODE
if (APPROX (mod[12],0)) {
308OLDCODE mod[12] = 0.001;
310OLDCODE angle = fabs(atan2(mod[14],mod[12])) - (PI/2.0);
311OLDCODE angle = angle/(PI/2.0);
318OLDCODE angle = angle / 1.5;
321OLDCODE angle = angle + 0.5;
324OLDCODE angle = 1.0 - angle;
327OLDCODE
if (angle > 1.0) angle = 1.0;
328OLDCODE
if (angle < 0.0) angle = 0.0;
330OLDCODE #ifdef SOUNDVERBOSE
331OLDCODE printf (
"angle: %f\n",angle);
336OLDCODE node->panFloatVal = (float) angle;
337OLDCODE node->panInt32Val = (int) (angle * 128);
338OLDCODE
if (node->panInt32Val < 0) node->panInt32Val = 0;
if (node->panInt32Val > 127) node->panInt32Val = 127;
341OLDCODE node->volumeFloatVal = (float) 0.0;
345OLDCODE
if (len < node->maxFront) {
347OLDCODE
if (!node->isActive) {
348OLDCODE node->isActive = TRUE;
349OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, isActive));
350OLDCODE #ifdef SOUNDVERBOSE
351OLDCODE printf (
"AudioControl node is now ACTIVE\n");
356OLDCODE node->__oldLen = len;
361OLDCODE
if (len < 0.0) {
362OLDCODE
if (len < node->minBack) {node->volumeFloatVal = (float) 1.0;}
363OLDCODE
else { node->volumeFloatVal = ((float) len - node->maxBack) / (node->maxBack - node->minBack); }
365OLDCODE
if (len < node->minFront) {node->volumeFloatVal = (float) 1.0;}
366OLDCODE
else { node->volumeFloatVal = (node->maxFront - (float) len) / (node->maxFront - node->minFront); }
370OLDCODE
if (APPROX(node->maxDelta, 0.0)) {
371OLDCODE printf (
"AudioControl: maxDelta approaches zero!\n");
372OLDCODE node->deltaFloatVal = (float) 0.0;
374OLDCODE #ifdef SOUNDVERBOSE
375OLDCODE printf (
"maxM/S %f \n",(node->__oldLen - len)/ (TickTime()- lastTime));
381OLDCODE node->deltaFloatVal = (float) ((node->__oldLen - len)/(TickTime()-lastTime()))/node->maxDelta;
382OLDCODE
if (node->deltaFloatVal < (
float) -1.0) node->deltaFloatVal = (
float) -1.0;
if (node->deltaFloatVal > (
float) 1.0) node->deltaFloatVal = (
float) 1.0;
383OLDCODE node->__oldLen = len;
388OLDCODE node->volumeFloatVal = node->volumeFloatVal*node->intensity;
389OLDCODE node->volumeInt32Val = (int) (node->volumeFloatVal * 128.0);
390OLDCODE
if (node->volumeInt32Val < 0) node->volumeInt32Val = 0;
if (node->volumeInt32Val > 127) node->volumeInt32Val = 127;
392OLDCODE node->deltaInt32Val = (int) (node->deltaFloatVal * 64.0) + 64;
393OLDCODE
if (node->deltaInt32Val < 0) node->deltaInt32Val = 0;
if (node->deltaInt32Val > 127) node->deltaInt32Val = 127;
395OLDCODE #ifdef SOUNDVERBOSE
396OLDCODE printf (
"AudioControl: amp: %f (%d) angle: %f (%d) delta: %f (%d)\n",node->volumeFloatVal,node->volumeInt32Val,
397OLDCODE node->panFloatVal, node->panInt32Val ,node->deltaFloatVal,node->deltaInt32Val);
400OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, volumeInt32Val));
401OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, volumeFloatVal));
402OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, panInt32Val));
403OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, panFloatVal));
404OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, deltaInt32Val));
405OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, deltaFloatVal));
409OLDCODE
if (node->isActive) {
410OLDCODE node->isActive = FALSE;
411OLDCODE MARK_EVENT (X3D_NODE(node), offsetof (
struct X3D_AudioControl, isActive));
412OLDCODE #ifdef SOUNDVERBOSE
413OLDCODE printf (
"AudioControl node is now INACTIVE\n");
418OLDCODE 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;
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);
558void 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, (ALuint *)&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);
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);
856int 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;
872double 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];