/* ////////////////////////////////////////////////////////////////////// // Module SNDSPACE.CXX: converions API3D -> API2D // ////////////////////////////////////////////////////////////////////// */ #include "SND\snddef.h" #include "sndinc.h" #include "snd.h" #include "sndspace.h" #include "sndvect.h" #if defined(_DLL_COMPILATION_MODE) #include "snddll.h" #endif #define CELERITE_SON 300 /*int exprime en m/s*/ static long g_lSoundSpeed=CELERITE_SON;/*m/s*/ static SndReal g_rDistSatur=0x80000; static SndReal g_rDistFade=8*0x80000; static SndReal g_rDistBackGround=C_ROLLOFFPARAM_INFINITE; static unsigned char ucVolumeBackGround=0; /* Cas A Cas B*/ /*^ ^*/ /*! !*/ /*!---+\ !----+\ .*/ /*! . \ ! . \ .*/ /*! . \ ! . \ .*/ /*! . \ ! . \+----------*/ /*! . \ ! . \ .*/ /*+---------+--> +---------------+-------*/ /* . . . . .*/ /*DistSatur . DistSatur . DistFade*/ /* DistFade DistBackGround*/ /*------------------------------------------------------------------------------*/ /* SetDistanceForVolumae:regle les par. permettant de convertir une distance en volume*/ /* Entrees:dist_satur=distance jusqu'à laquelle le volume est maxi*/ /* dist_back=distance à partir de laquelle le volume est constant apres le fade*/ /* constante particuliere:C_ROLLOFFPARAM_INFINITE pour l'infini*/ /* Sortie: neant*/ /* Noat: entre dist_satur et dist_fade, le volume decroit lineairement*/ /*--------------------------------------------------------------------------------*/ void SND_CALL SND_fn_vSetDistanceForVolume(SndReal dist_satur,SndReal dist_back) { g_rDistSatur=dist_satur; g_rDistFade=8*g_rDistSatur; g_rDistBackGround=dist_back; if (g_rDistBackGround=g_rDistFade) ucVolumeBackGround=C_SOUNDVOL_MINI; else ucVolumeBackGround=(unsigned char)SND_fn_rMulRealRealSnd(C_SOUNDVOL_MAXI,SND_fn_rDivRealRealSnd(g_rDistFade-g_rDistBackGround,g_rDistFade-g_rDistSatur)); } void SND_CALL SND_fn_vSetDefaultRollOff(RollOffParam* rolloff) { RollOffParam roll; if (rolloff->rDistSatur!=C_ROLLOFFPARAM_DEFAULT) roll.rDistSatur=rolloff->rDistSatur; else roll.rDistSatur=g_rDistSatur; if (rolloff->rDistBackGround!=C_ROLLOFFPARAM_DEFAULT) roll.rDistBackGround=rolloff->rDistBackGround; else roll.rDistBackGround=g_rDistBackGround; SND_fn_vSetDistanceForVolume(rolloff->rDistSatur,rolloff->rDistBackGround); } void SND_CALL SND_fn_vGetDefaultRollOff(RollOffParam* rolloff) { rolloff->rDistSatur=g_rDistSatur; rolloff->rDistBackGround=g_rDistBackGround; } /*-----------------------------------------------------------------------------*/ /* DistanceToVolume:obtenir le volume d'une source en fonction d'une distance*/ /* pour le valeurs de RollOff par defaut*/ /* Entree: dist=distance en m*/ /* Sortie: volume midi*/ /*----------------------------------------------------------------------------*/ unsigned char SND_CALL SND_fn_ucDistanceToVolume(SndReal dist) { if (distg_rDistBackGround) { return ucVolumeBackGround; } else { if (dist>g_rDistFade) return C_SOUNDVOL_MINI; else return (unsigned char)SND_fn_rMulRealRealSnd(C_SOUNDVOL_MAXI,SND_fn_rDivRealRealSnd(g_rDistFade-dist,g_rDistFade-g_rDistSatur)); } } /*-----------------------------------------------------------------------------*/ /* DistanceToVolumeEx:obtenir le volume d'une source en fonction d'une distance*/ /* pour le valeurs de RollOff par defaut*/ /* Entree: dist=distance en m*/ /* Sortie: volume midi*/ /*----------------------------------------------------------------------------*/ unsigned char SND_CALL SND_fn_ucDistanceToVolumeEx(SndReal dist,RollOffParam* rolloff) { if (rolloff) { if (rolloff->rDistBackGroundrDistSatur) rolloff->rDistBackGround=C_ROLLOFFPARAM_INFINITE; if (distrDistSatur) return C_SOUNDVOL_MAXI; if (dist>rolloff->rDistBackGround) { if (rolloff->rDistBackGround>8*rolloff->rDistSatur) return C_SOUNDVOL_MINI; else return (unsigned char)SND_fn_rMulRealRealSnd(C_SOUNDVOL_MAXI,SND_fn_rDivRealRealSnd(8*rolloff->rDistSatur-rolloff->rDistBackGround,(8-1)*rolloff->rDistSatur)); } else { if (dist>8*rolloff->rDistSatur) return C_SOUNDVOL_MINI; else return (unsigned char)SND_fn_rMulRealRealSnd(C_SOUNDVOL_MAXI,SND_fn_rDivRealRealSnd(8*rolloff->rDistSatur-dist,(8-1)*rolloff->rDistSatur)); } } else return SND_fn_ucDistanceToVolume(dist); } /*----------------------------------------------------------------------------*/ /* DopplerPitch:obtenir le rapport de frequence du à l'effet doppler*/ /* Entrees:src_pos=position de la source*/ /* src_vit=vitesse de la source*/ /* mic_pos=position du micro*/ /* mic_vit=vitesse du micro*/ /* Sortie:rapport de frequence (>1.0 -> plus aigu; <1.0 ->plus grave)*/ /**/ /* Si Fo=frequence effective de la source, Fd=frequence subjective au micro*/ /* __ -> ->*/ /* Vo=projetee de la vitesse de la source sur la drite OS = Vo.OS/OS*/ /* __ */ /* Vm=projetee de la vitesse du micro sur la drite OS*/ /**/ /* D=OS distance entre la source et le micro*/ /* __ __*/ /* On a: Fd = Fo * ( C - Vm ) / ( C - Vo ) */ /* -> -> -> ->*/ /* soit : Fd = Fo * ( C*D - Vm.OS ) / ( C*D - Vo.OS)*/ /*----------------------------------------------------------------------------*/ SndReal SND_CALL SND_fn_rDopplerPitch(SndVector *src_pos,SndVector *src_vit,SndVector *mic_pos,SndVector *mic_vit) { SndVector dir;/*OS/2^8 (division par 256 pour empecher la saturation)*/ SndReal nor;/*dist(OS)/2^8*/ SndReal retour; if (g_lSoundSpeed) { dir.x=(src_pos->x-mic_pos->x)>>8; dir.y=(src_pos->y-mic_pos->y)>>8; dir.z=(src_pos->z-mic_pos->z)>>8; nor=SND_fn_rPseudoNormeVectorSnd(&dir); if (nor==0) return 0x10000; if (nor>0x400000) return 0x10000; retour=nor*g_lSoundSpeed; /*if retour==0, this may mean that DopplerEffect is too low; set id to No_DOPPLER*/ snd_assert(retour); retour=SND_fn_rDivRealRealSnd(retour-SND_fn_rScalaireVectorSnd(src_vit,&dir) ,retour-SND_fn_rScalaireVectorSnd(mic_vit,&dir)); return retour; } else { return C_SNDREAL_1; } } /*------------------------------------------------------------*/ /* SetDopplerFactorSnd:change Doppler effect range*/ /* Entree:new factor for Doppler effect (1.0=normal effect=physicallly realistic*/ /* 0.0=no doppler effect*/ /* Sortie:neant*/ /*------------------------------------------------------------*/ void SND_CALL SND_fn_vSetDopplerFactor(SndReal factor) { if (factor) g_lSoundSpeed=M_RealToIntSnd( SND_fn_rDivRealRealSnd( M_IntToRealSnd(CELERITE_SON), factor) ); else g_lSoundSpeed=0; } /*------------------------------------------------------------*/ /* GetDopplerFactorSnd: retrieve the global Doppler factor /* Entree: None /* /* Sortie: Factor /*------------------------------------------------------------*/ SndReal SND_CALL SND_fn_rGetDopplerFactor() { //If gl_SoundSpeed == 0, we dont want to divide by 0 if(g_lSoundSpeed) return SND_fn_rDivRealRealSnd(M_IntToRealSnd(CELERITE_SON), M_IntToRealSnd(g_lSoundSpeed)); else return C_SNDREAL_0; } /*#define VALID_POSITIONTOPAN*/ #ifdef VALID_POSITIONTOPAN #include void _valid_PositionToPan(void) { SndVector src,mic,mic_nor,mic_tan; int i; int d=0x20000; mic.x=0; mic.y=0; mic.z=0; mic_nor.x=0; mic_nor.y=0x10000; mic_nor.z=0; mic_tan.x=0x10000; mic_tan.y=0; mic_tan.z=0; for (i=0;i<360;i+=10) { src.x=d*cos(3.1415*i/180);src.y=d*sin(3.1415*i/180);src.z=0; _RPT2(_CRT_WARN,"angle:%d pan:%d\n",i,(long)SND_fn_ucPositionToPan(&src,&mic,&mic_nor,&mic_tan)); } } #endif /*VALID_POSITIONTOPAN*/ /*----------------------------------------------------------------------------*/ /* PositionToPan: obtenir le pan à partie de la position d'une source*/ /* Entrees:src=position de la source*/ /* mic=position du micro*/ /* mic_nor=direction normale du micro (vers l'avant de l'ecran)*/ /* mic_tan=direction horizontale du icro (tangent à l'ecran)*/ /* Sortie:pan midi (0 tout à gauche,127 tout à droite)*/ /*----------------------------------------------------------------------------*/ /* mic_nor*/ /* ^ */ /* s'!......+ o=Objet ->*/ /* ! n /. n=norme du vect mo*/ /* !_b / . ------> ------> -> _______*/ /* ! /)a . s=proj. de o sur (m,mic_tan)=scal(mic_tan,mo)=n*mic_tan*cos(a)*/ /* m *------+-> mic_tan*/ /* micro s pan=MAX en dehors de +/-45° _______*/ /* pan prop à sin(b) = prop à cos(a) = prop à s/n (si mic_tan=1)*/ unsigned char SND_CALL SND_fn_ucPositionToPan(SndVector *src,SndVector *mic,SndVector *mic_nor,SndVector *mic_tan) { SndReal s,n; SndVector diro; long pp; snd_assert((mic_nor->x!=0)||(mic_nor->y!=0)||(mic_nor->z!=0)); snd_assert((mic_tan->x!=0)||(mic_tan->y!=0)||(mic_tan->z!=0)); /*diro=vecteur allant de Micro à projete(Source) dans plan (Micro,x,y)*/ diro.x=src->x-mic->x; diro.y=src->y-mic->y; diro.z=src->z-mic->z; n=SND_fn_rPseudoNormeVectorSnd(&diro); /*s=n_diro*cos(tan,diro)*/ s=SND_fn_rPseudoScalaireNormeVectorSnd(&diro,mic_tan); if (2*n/256==0) return C_SOUNDPAN_MEDIAN; if (s<=-n) return C_SOUNDPAN_LEFT; if (s>=n) return C_SOUNDPAN_RIGHT; /*if ((s>-n) && (sC_SOUNDPAN_RIGHT) pp=C_SOUNDPAN_RIGHT; return (unsigned char)pp; } /*#define VALID_POSITIONTODOLBY*/ #ifdef VALID_POSITIONTODOLBY #include void _valid_PositionToDolby(void) { SndVector src,mic,mic_nor; int i; int d=0x20000; mic.x=0; mic.y=0; mic.z=0; mic_nor.x=0; mic_nor.y=0x10000; mic_nor.z=0; for (i=0;i<360;i+=10) { src.x=d*cos(3.1415*i/180);src.y=d*sin(3.1415*i/180);src.z=0; _RPT2(_CRT_WARN,"angle:%d dolby:%d\n",i,(long)SND_fn_ucPositionToDolby(&src,&mic,&mic_nor)); } } #endif /*VALID_POSITIONTODOLBY*/ /*------------------------------------------------------------------------------*/ /* PositionToDolby: obtenir le parametre dolby à partir de la position*/ /* Entrees:src=position de la source*/ /* mic=position du micro*/ /* mic_nor=direction normale au micro*/ /* Sortie:parametre Dolby (0 tout devant, 127 tout derriere)*/ /*----------------------------------------------------------------------------*/ /* mic_nor*/ /* ^ */ /* s'!......+ o=Objet ->*/ /* ! n /. n=norme du vect mo*/ /* !_b / . ------> ------> -> _______*/ /* ! /)a . s'=proj. de o sur (m,mic_nor)=scal(mic_nor,mo)=n*mic_nor*cos(b)*/ /* m *------+-> mic_tan*/ /* micro s _______*/ /* pan prop à sin(a) = prop à cos(b) = prop à s'/n (si mic_tan=1)*/ unsigned char SND_CALL SND_fn_ucPositionToDolby(SndVector *src,SndVector *mic,SndVector *mic_nor) { SndReal s,n; SndVector diro; long pp; snd_assert((mic_nor->x!=0)||(mic_nor->y!=0)||(mic_nor->z!=0)); /*diro=vecteur allant de Micro à projete(Source) dans plan (Micro,x,y)*/ diro.x=src->x-mic->x; diro.y=src->y-mic->y; diro.z=src->z-mic->z; n=SND_fn_rPseudoNormeVectorSnd(&diro); /*s=n_diro*cos(tan,diro)*/ s=SND_fn_rPseudoScalaireNormeVectorSnd(&diro,mic_nor); if (2*n/256==0) return (C_SOUNDSPACE_FRONT+C_SOUNDSPACE_BACK)/2; if (s<=-n) return C_SOUNDSPACE_BACK; if (s>=n) return C_SOUNDSPACE_FRONT; /*if ((s>-n) && (sC_SOUNDSPACE_BACK) pp=C_SOUNDSPACE_BACK; return (unsigned char)pp; }