394 lines
13 KiB
C
394 lines
13 KiB
C
/*
|
|
//////////////////////////////////////////////////////////////////////
|
|
// 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_rDistSatur)
|
|
g_rDistBackGround=C_ROLLOFFPARAM_INFINITE;
|
|
|
|
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 (dist<g_rDistSatur)
|
|
return C_SOUNDVOL_MAXI;
|
|
if (dist>g_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->rDistBackGround<rolloff->rDistSatur)
|
|
rolloff->rDistBackGround=C_ROLLOFFPARAM_INFINITE;
|
|
|
|
if (dist<rolloff->rDistSatur)
|
|
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 <crtdbg.h>
|
|
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) && (s<n))*/
|
|
pp=C_SOUNDPAN_MEDIAN+(s/256)*(C_SOUNDPAN_RIGHT-C_SOUNDPAN_LEFT)/(2*n/256);
|
|
|
|
if (pp<C_SOUNDPAN_LEFT) pp=C_SOUNDPAN_LEFT;
|
|
if (pp>C_SOUNDPAN_RIGHT) pp=C_SOUNDPAN_RIGHT;
|
|
|
|
return (unsigned char)pp;
|
|
}
|
|
|
|
/*#define VALID_POSITIONTODOLBY*/
|
|
#ifdef VALID_POSITIONTODOLBY
|
|
#include <crtdbg.h>
|
|
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) && (s<n))*/
|
|
pp=(C_SOUNDSPACE_FRONT+C_SOUNDSPACE_BACK)/2+(s/256)*(C_SOUNDSPACE_FRONT-C_SOUNDSPACE_BACK)/(2*n/256);
|
|
|
|
if (pp<C_SOUNDSPACE_FRONT) pp=C_SOUNDSPACE_FRONT;
|
|
if (pp>C_SOUNDSPACE_BACK) pp=C_SOUNDSPACE_BACK;
|
|
|
|
return (unsigned char)pp;
|
|
}
|
|
|
|
|