reman3/Rayman_X/cpa/tempgrp/SND_OLD/src/sndspace.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;
}