/* 3DSound Plugin - DMS2 - November 99 - by Sébastien DENEUX */ /*to do : - _SETListenerPosition3D -> creer objet 3D lors de la première pos du listener - revoir init et release directSound - supprimer list soundBuffers ou la passez par buffers par ob et non liste globale de buffers - si pause, pas enable pour depause mais repause typages des fonctions non documentés "fun [P] S", // _GETwaveData "fun [P] [I I I I]", // _GETwaveInfo "fun [P] Wave", // _OPENwave "fun [Wave] I", // _CLOSEwave "fun [Wave I I I] S", // _READwave "fun [Wave I I] I", // _SEEKwave */ typeof class=S;; typeof configFile=S;; /*used to keep sound enable/disable state*/ var soundEnabled=1;; var pause=0;; var maxDownloadSize=204800;; typeof soundBuffers=[[S DSBuffer I I I I Wave Timer I I] r1];; /*obName buffer3D loop autostart streaming byteslice wave timerStreaming streamPlaying wavSize*/ typeof listener=DSListener3D;; typeof coeffMult=F;; var defaultMinDistance=1000;; var defaultMaxDistance=10000;; var RollOffFactor="1";; var DopplerFactor="1";; var ListenerVelocity3D_X="1";; var ListenerVelocity3D_Y="1";; var ListenerVelocity3D_Z="1";; /* 44100 ech/sec *16 bits /8 -> octets 44100*2 = 88200 octets/sec * 2 buffers = 176400 ko by buffer in streaming mode */ /*var sampleslice=44100;; var timeslice=1000;; var nbuffers=2;;*/ var sampleslice=22050;; /*ech*/ var timeslice=10;; var nbuffers=5;; /*----------------*/ fun _SoundTimer(t,a)= /*_showconsole;*/ /*_fooS "**plugin 3DSOUND : SoundTimer";*/ let a -> [elt oldplay readSize] in let elt -> [_ sbuf loop _ _ byteslice wave _ _ wavSize] in let _GETPlayPosition sbuf -> pos in ( /* _fooS strcat "*** readSize = " itoa readSize; _fooS strcat "*** wawSize = " itoa wavSize;*/ if (readSize>=wavSize)&&!loop then (/*_fooS "### STOP";*/ _deltimer t; _STOPSoundBuffer sbuf; _SETPlayPosition sbuf 0; _SEEKwave wave 0 0; mutate elt <- [_ sbuf _ _ _ _ wave nil 0 _]; set readSize=0) else nil; if (oldplaytolock in (_SETSoundBufferFromWave sbuf oldplay wave tolock nil loop; /*!!!*/ set readSize=readSize+tolock) else nil; if (oldplay>pos) then ( let (nbuffers*byteslice)-oldplay -> tolock in (_SETSoundBufferFromWave sbuf oldplay wave tolock nil loop; /*!!!*/ set readSize=readSize+tolock); let pos -> tolock in (_SETSoundBufferFromWave sbuf 0 wave tolock nil loop; /*!!!*/ set readSize=readSize+tolock); 0 ) else nil; mutate a<-[_ pos readSize]; 0 );; /*----------------*/ /*fun _SoundTimer2 (t,a)= _fooS "**plugin 3DSOUND : SoundTimer"; let a->[sbuf wave size oldplay streaming loop] in let _GETPlayPosition sbuf -> pos in ( if (oldplaytolock in _SETSoundBufferFromWave sbuf oldplay wave tolock nil nil else nil; if (oldplay>pos) then ( let size-oldplay -> tolock in _SETSoundBufferFromWave sbuf oldplay wave tolock nil nil; let pos -> tolock in _SETSoundBufferFromWave sbuf 0 wave tolock nil nil; 0 ) else nil; mutate a<-[_ _ _ pos _ _]; 0 );;*/ /*----------------*/ /*play the 3D sound buffers contained in the buffers list that have the same name as the name of the ob o*/ fun applyPLAYOnBuffers(SBlist,o)= if SBlist==nil then nil else let SBlist -> [elt queue] in let elt -> [name buffer3D loop autoStart streaming byteslice wave myTimer streamPlaying size] in ( if (!strcmp name (ObName o)) && !(streamPlaying&&streaming) && !pause then /*do not start sound if already started in streaming mode only or if paused*/ ( _fooS "***PLAY"; _SETSoundBufferFromWave buffer3D 0 wave (if streaming then nbuffers*byteslice else byteslice) nil loop; /*!!!!*/ _SETPlayPosition buffer3D 0; /*modif pb*/ _SEEKwave wave 0 0; /*modif pb*/ if loop || streaming then _PLAYSoundBuffer buffer3D 1 /*start playing the sound (loop mode)*/ else _PLAYSoundBuffer buffer3D 0; /*start playing the sound (once mode)*/ if streaming then ( mutate elt <- [_ buffer3D _ _ _ _ _ (_rfltimer _starttimer _channel timeslice @_SoundTimer [elt 0 0]) streaming _]; 0 ) else nil; ) else nil; applyPLAYOnBuffers queue o; 0 );; /*----------------*/ /*stop the 3D sound buffers contained in the buffers list that have the same name as the name of the ob o*/ fun applySTOPOnBuffers(SBlist,o)= if SBlist==nil then nil else let SBlist -> [elt queue] in let elt -> [name buffer3D _ _ streaming _ wave myTimer streamPlaying _] in ( if (!strcmp name (ObName o)) then ( _fooS "***STOP"; if streaming then (_deltimer myTimer;0) else nil; _STOPSoundBuffer buffer3D; _SETPlayPosition buffer3D 0; _SEEKwave wave 0 0; mutate elt <- [_ buffer3D _ _ _ _ wave nil 0 _]; 0 ) else nil; applySTOPOnBuffers queue o; 0 );; /*----------------*/ fun destroyAllBuffers(SBlist)= if SBlist==nil then nil else let SBlist -> [elt queue] in let elt -> [_ buffer3D _ _ streaming _ _ myTimer _ _] in ( if streaming then _deltimer myTimer else nil; _STOPSoundBuffer buffer3D; _DSSoundBuffer buffer3D; destroyAllBuffers queue; 0 );; /*----------------*/ fun pauseAllBuffers(SBlist)= if SBlist==nil then nil else let SBlist -> [elt queue] in let elt -> [_ buffer3D loop autoStart streaming _ _ _ _ _] in ( if pause then (_fooS "** PLUGIN 3DSOUND : play";_PLAYSoundBuffer buffer3D loop||streaming) else (_fooS "** PLUGIN 3DSOUND : stop";_STOPSoundBuffer buffer3D;); pauseAllBuffers queue; 0 );; /*----------------*/ fun stopAllBuffers(SBlist)= if SBlist==nil then nil else let SBlist -> [elt queue] in let elt -> [_ buffer3D _ _ streaming _ wave myTimer _ _] in ( if streaming then _deltimer myTimer else nil; _STOPSoundBuffer buffer3D; _SETPlayPosition buffer3D 0; _SEEKwave wave 0 0; mutate elt <- [_ buffer3D _ _ _ _ wave nil 0 _]; stopAllBuffers queue; 0 );; /*----------------*/ fun playAllBuffers(SBlist)= if SBlist==nil then nil else let SBlist -> [elt queue] in ( let elt -> [_ buffer3D loop autoStart streaming byteslice wave myTimer streamPlaying size] in if autoStart then if !(streamPlaying&&streaming) then /*do not start sound if already started in streaming mode only*/ ( _SETSoundBufferFromWave buffer3D 0 wave (if streaming then nbuffers*byteslice else byteslice) nil loop ; /*!!!!*/ if loop || streaming then _PLAYSoundBuffer buffer3D 1 /*start playing the sound (loop mode)*/ else _PLAYSoundBuffer buffer3D 0; /*start playing the sound (once mode)*/ if streaming then mutate elt <- [_ buffer3D _ _ _ _ _ (_rfltimer _starttimer _channel timeslice @_SoundTimer [elt 0 0]) streaming _] else nil; 0 ) else nil else ( 0 ); playAllBuffers queue; 0 );; /*----------------*/ /*apply parameters on the 3D sound buffers contained in the buffers list that have the same name as the name of the ob o*/ fun applyPARAMETERSOnBuffers(SBlist,o,volume,pan,frequency,minDistance,maxDistance,velocityX,velocityY,velocityZ,bufferType3D)= if SBlist==nil then nil else let SBlist -> [elt queue] in let elt -> [name buffer3D loop autoStart streaming byteslice wave _ _ size] in ( if !strcmp name (ObName o) then ( if volume!=nil then (_SETVolume buffer3D (atoi volume);0) else 0; if pan!=nil then _SETPan buffer3D (atoi pan) else nil; if frequency!=nil then _SETFrequency buffer3D (atoi frequency) else nil; if (velocityX!=nil) && (velocityY!=nil) && (velocityZ!=nil) then _SETVelocity3D buffer3D (atof velocityX) (atof velocityY) (atof velocityZ) else nil; if minDistance!=nil then _SETMinDistance buffer3D (atof minDistance) else _SETMinDistance buffer3D (itof defaultMinDistance); if maxDistance!=nil then _SETMaxDistance buffer3D (atof maxDistance) else _SETMaxDistance buffer3D (itof defaultMaxDistance); if bufferType3D then _SETOperationMode buffer3D 0 /*0 -> 3d parameter are applied // center (0,0,0)*/ else _SETOperationMode buffer3D 0+2; /*2 -> 3D buffer not calculated*/ _COMMITSoundSettings listener; /*A enlever !!!! QUAND CREATION DES BUFFERS dans cbanim*/ let strextr _getpack _checkpack configFile -> l in let getInfo l "soundState" -> tmp in if !strcmp tmp "0" then set soundEnabled = 0 else nil; if autoStart&&soundEnabled then ( _SETSoundBuffer buffer3D (_READwave wave (if streaming then nbuffers*byteslice else byteslice) nil loop) 0; /*!!!*/ if loop || streaming then _PLAYSoundBuffer buffer3D 1 /*start playing the sound (loop mode)*/ else _PLAYSoundBuffer buffer3D 0 /*start playing the sound (once mode)*/ ) else nil; if streaming && autoStart && soundEnabled then ( mutate elt <- [_ _ _ _ _ _ _ (_rfltimer _starttimer _channel timeslice @_SoundTimer [elt 0 0]) autoStart _]; 0 ) else ( mutate elt <- [_ _ _ _ _ _ _ nil autoStart&&soundEnabled _]; 0 ); ) else nil; applyPARAMETERSOnBuffers queue o volume pan frequency minDistance maxDistance velocityX velocityY velocityZ bufferType3D; 0 );; /*----------------*/ fun activate(o,from,action,param,reply)= if (!strcmp action (strcat (ObName o) ".start")) && soundEnabled then applyPLAYOnBuffers soundBuffers o else if (!strcmp action (strcat (ObName o) ".stop")) && soundEnabled then applySTOPOnBuffers soundBuffers o else if (!strcmp action "Enable3DSound") && (strcmp param "0") && (strcmp param "-1") && !soundEnabled && !pause then ( _fooS "*** PLUGIN 3DSOUND : ENABLE"; _storepack strbuild ("soundState"::"1"::nil)::nil configFile; set soundEnabled=1; set pause=0; playAllBuffers soundBuffers ) else if ((!strcmp action "Disable3DSound")||((!strcmp action "Enable3DSound") && (!strcmp param "0"))) && soundEnabled then ( _fooS "*** PLUGIN 3DSOUND : DISABLE"; _storepack strbuild ("soundState"::"0"::nil)::nil configFile; set soundEnabled=0; set pause=0; stopAllBuffers soundBuffers ) else if ((!strcmp action "Pause3DSound")||((!strcmp action "Enable3DSound") && (!strcmp param "-1"))) && soundEnabled && !pause then ( _fooS "*** PLUGIN 3DSOUND : PAUSE"; pauseAllBuffers soundBuffers; set pause=1; 0 ) else if (!strcmp action "Enable3DSound") && (strcmp param "0") && (strcmp param "-1") && pause && soundEnabled then ( _fooS "*** PLUGIN 3DSOUND : UNPAUSE"; pauseAllBuffers soundBuffers; set pause=0 ) else nil;; /*----------------*/ /*get the player pos and orientation and set the 3D camera*/ fun getListenerPos(o)= let M3getObjVec session (M3getFather session ObGetMain owner) -> [player_x player_y player_z] in let M3getObjAng session (M3getFather session ObGetMain owner) -> [player_a player_b player_c] in if player_x==nil then nil else /*at nil at the beginning*/ ( _SETListenerPosition3D listener (itof player_x) (itof player_y) (itof (player_z)); let (itof player_a) *. coeffMult -> a in let (itof player_b) *. coeffMult -> b in let (itof player_c) *. coeffMult -> c in _SETListenerOrientation listener (-.sin a) (sin b) ((cos a)) ((sin a)*.(sin c)) ((cos b)*.(cos c)) (-.cos a); _COMMITSoundSettings listener );; /*----------------*/ fun setObjPos2(x,b)= let b -> [[streaming wave channels freq reso size volume pan frequency minDistance maxDistance velocityX velocityY velocityZ loop autoStart byteslice] o] in ( match x with (objAnchor [h _ _ _] -> /*H3D*/ (_fooS "**plugin 3DSOUND : creation buffer 3D"; let M3getObjVec session h -> [x y z] in let _CRSoundBuffer3D DMSds channels freq reso (if streaming then nbuffers*sampleslice else (size*8/reso/channels)) 4+2 -> newBuf3D in (set soundBuffers=[(ObName o) newBuf3D loop autoStart streaming byteslice wave nil 0 size]::soundBuffers;/*create 3D buffer*/ _SETPosition3D newBuf3D (itof x) (itof y) (itof z)))) |(posAnchor[_ [x y z] _] -> /*pos*/ ( _fooS "**plugin 3DSOUND : creation buffer 3D"; let _CRSoundBuffer3D DMSds channels freq reso (if streaming then nbuffers*sampleslice else (size*8/reso/channels)) 4+2 -> newBuf3D in (set soundBuffers=[(ObName o) newBuf3D loop autoStart streaming byteslice wave nil 0 size]::soundBuffers;/*create 3D buffer*/ _SETPosition3D newBuf3D (itof x) (itof y) (itof z)))); applyPARAMETERSOnBuffers soundBuffers o volume pan frequency minDistance maxDistance velocityX velocityY velocityZ 1; 0 );; /*----------------*/ fun setObjPos(o,b)= apply_on_list ObAnchor o @setObjPos2 [b o]; 0;; /*----------------*/ /*wav file has been downloaded*/ fun DownloadedWavFile(wavFileName,o)= let hd UgetParam ObUi o "volume" -> volume in let hd UgetParam ObUi o "pan" -> pan in let hd UgetParam ObUi o "frequency" -> frequency in let hd UgetParam ObUi o "minDistance" -> minDistance in let hd UgetParam ObUi o "maxDistance" -> maxDistance in let UgetParam ObUi o "velocity" -> [velocityX[velocityY[velocityZ _]]] in let hd UgetParam ObUi o "loop" -> Ploop in let hd UgetParam ObUi o "autoStart" -> PautoStart in let hd UgetParam ObUi o "streaming" -> Pstreaming in let hd UgetParam ObUi o "bufferType" -> PbufferType in let if !strcmp Pstreaming "1" then 1 else 0 -> streaming in let if !strcmp Ploop "0" then 0 else 1 -> loop in let if !strcmp PautoStart "0" then 0 else 1 -> autoStart in let _checkpack wavFileName->p in if p==nil then (_fooS "**plugin 3DSOUND : error : file not found";0) else let _GETwaveInfo p->[size channels freq reso] in let if ((sampleslice*channels)*(reso/8) > size) && streaming then 0 else streaming -> streaming in /*in case of size < streaming read size*/ let if streaming then (sampleslice*channels)*(reso/8) else size -> byteslice in let _OPENwave p->wave in ( _fooS strcatn "**plugin 3DSOUND : wav file infos --> size:"::(itoa size)::" freq:"::(itoa freq)::" reso:"::(itoa reso)::" nchn:"::(itoa channels)::nil; if listener==nil then ( set listener=_CRListener3D DMSds; ObCbAnim o @getListenerPos; /*provisoire*/ _SETListenerPosition3D listener (itof 5000) (itof 5000) (itof 5000); /*listener position before CB anim where player_x!=nil (before player H3D is present)*/ /*provisoire*/ _SETRollOffFactor listener atof RollOffFactor; _SETDopplerFactor listener atof DopplerFactor; _SETListenerVelocity3D listener atof ListenerVelocity3D_X atof ListenerVelocity3D_Y atof ListenerVelocity3D_Y; 0 ) else nil; if !strcmp PbufferType "2D" then ( _fooS "**plugin 3DSOUND : creation buffer 2D"; let _CRSoundBuffer3D DMSds channels freq reso (if streaming then nbuffers*sampleslice else (size*8/reso/channels)) 1+4+2 -> newBuf2D in ( set soundBuffers=[(ObName o) newBuf2D loop autoStart streaming byteslice wave nil 0 size]::soundBuffers; applyPARAMETERSOnBuffers soundBuffers o volume pan frequency minDistance maxDistance velocityX velocityY velocityZ 0; 0 ) ) else setObjPos o [streaming wave channels freq reso size volume pan frequency minDistance maxDistance velocityX velocityY velocityZ loop autoStart byteslice]; ObRegisterAction o (strcatn (ObName o)::".start"::nil) @activate; ObRegisterAction o (strcatn (ObName o)::".stop"::nil) @activate; ObRegisterAction o "Enable3DSound" @activate; ObRegisterAction o "Disable3DSound" @activate; ObRegisterAction o "Pause3DSound" @activate; 0; );; /*----------------*/ fun cbcomm(ui,action,param,o)= if !strcmp action "setSound" then let lineextr param -> [name[long _]] in if (atoi long) <= maxDownloadSize then (_fooS strcat "**plugin 3DSOUND : ObName = " ObName o;_fooS "**plugin 3DSOUND : we download";_RSCdownload this name name mkfun2 @DownloadedWavFile o 1;0) else (_fooS strcat "**plugin 3DSOUND : ObName = " ObName o;_fooS "**plugin 3DSOUND : we do not download";DownloadedWavFile name o;0) else nil;; /*----------------*/ fun newOb(o)= _fooS "**plugin 3DSOUND : new ob"; UcbComm this ObUi o mkfun4 @cbcomm o; UsendSrv this ObUi o "getSound" nil; 0;; /*----------------*/ fun destroyPlug()= _fooS "**plugin 3DSOUND : destroy plug"; destroyAllBuffers soundBuffers; _DSListener3D listener; _fooS "** end destroy buffers 3D and listener"; 0;; /*----------------*/ fun IniPlug(file)= _fooS "**plugin 3DSOUND : init plug"; DMSinitDirectSound 2 44100 16 DSSCL_PRIORITY; set configFile = strcatn "locked/conf/plugin3dsound/"::DMSname::".conf"::nil; set coeffMult = (itof 2) *. (atof "3.1416") /. itof(65535); set class=getInfo strextr _getpack _checkpack file "name"; PlugRegister class @newOb @destroyPlug; 0;;