- implemented panning
- implemented coning - many minor fixes
This commit is contained in:
parent
e658ee5503
commit
7da6e5c9a5
|
@ -85,14 +85,14 @@ static inline D3DVALUE ScalarProduct (LPD3DVECTOR a, LPD3DVECTOR b)
|
|||
}
|
||||
|
||||
/* vector product (i believe it's called cross product in english */
|
||||
static inline LPD3DVECTOR VectorProduct (LPD3DVECTOR a, LPD3DVECTOR b)
|
||||
static inline D3DVECTOR VectorProduct (LPD3DVECTOR a, LPD3DVECTOR b)
|
||||
{
|
||||
LPD3DVECTOR c;
|
||||
c->u1.x = (a->u2.y*b->u3.z) - (a->u3.z*b->u2.y);
|
||||
c->u2.y = (a->u3.z*b->u1.x) - (a->u1.x*b->u3.z);
|
||||
c->u3.z = (a->u1.x*b->u2.y) - (a->u2.y*b->u1.x);
|
||||
D3DVECTOR c;
|
||||
c.u1.x = (a->u2.y*b->u3.z) - (a->u3.z*b->u2.y);
|
||||
c.u2.y = (a->u3.z*b->u1.x) - (a->u1.x*b->u3.z);
|
||||
c.u3.z = (a->u1.x*b->u2.y) - (a->u2.y*b->u1.x);
|
||||
TRACE("(%f,%f,%f) x (%f,%f,%f) = (%f,%f,%f)\n", a->u1.x, a->u2.y, a->u3.z, b->u1.x, b->u2.y, \
|
||||
b->u3.z, c->u1.x, c->u2.y, c->u3.z);
|
||||
b->u3.z, c.u1.x, c.u2.y, c.u3.z);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -106,36 +106,51 @@ static inline D3DVALUE VectorMagnitude (LPD3DVECTOR a)
|
|||
}
|
||||
|
||||
/* conversion between radians and degrees */
|
||||
static inline DWORD RadToDeg (DWORD angle)
|
||||
static inline D3DVALUE RadToDeg (D3DVALUE angle)
|
||||
{
|
||||
DWORD newangle;
|
||||
D3DVALUE newangle;
|
||||
newangle = angle * (360/(2*M_PI));
|
||||
TRACE("%ld rad = %ld deg\n", angle, newangle);
|
||||
TRACE("%f rad = %f deg\n", angle, newangle);
|
||||
return newangle;
|
||||
}
|
||||
|
||||
/* conversion between degrees and radians */
|
||||
static inline DWORD DegToRad (DWORD angle)
|
||||
static inline D3DVALUE DegToRad (D3DVALUE angle)
|
||||
{
|
||||
DWORD newangle;
|
||||
D3DVALUE newangle;
|
||||
newangle = angle * (2*M_PI/360);
|
||||
TRACE("%ld deg = %ld rad\n", angle, newangle);
|
||||
TRACE("%f deg = %f rad\n", angle, newangle);
|
||||
return newangle;
|
||||
}
|
||||
|
||||
/* angle between vectors */
|
||||
static inline DWORD AngleBetweenVectorsDeg (LPD3DVECTOR a, LPD3DVECTOR b)
|
||||
/* angle between vectors - deg version */
|
||||
static inline D3DVALUE AngleBetweenVectorsDeg (LPD3DVECTOR a, LPD3DVECTOR b)
|
||||
{
|
||||
DWORD angle, cos;
|
||||
D3DVALUE la, lb, product;
|
||||
D3DVALUE la, lb, product, angle, cos;
|
||||
/* definition of scalar product: a*b = |a|*|b|*cos...therefore: */
|
||||
product = ScalarProduct (a,b);
|
||||
la = VectorMagnitude (a);
|
||||
lb = VectorMagnitude (b);
|
||||
cos = product/(la*lb);
|
||||
angle = acos(cos);
|
||||
/* we now have angle in radians */
|
||||
angle = RadToDeg(cos);
|
||||
TRACE("angle between (%f,%f,%f) and (%f,%f,%f) = %ld degrees\n", a->u1.x, a->u2.y, a->u3.z, b->u1.x, \
|
||||
angle = RadToDeg(angle);
|
||||
TRACE("angle between (%f,%f,%f) and (%f,%f,%f) = %f degrees\n", a->u1.x, a->u2.y, a->u3.z, b->u1.x, \
|
||||
b->u2.y, b->u3.z, angle);
|
||||
return angle;
|
||||
}
|
||||
|
||||
/* angle between vectors - rad version */
|
||||
static inline D3DVALUE AngleBetweenVectorsRad (LPD3DVECTOR a, LPD3DVECTOR b)
|
||||
{
|
||||
D3DVALUE la, lb, product, angle, cos;
|
||||
/* definition of scalar product: a*b = |a|*|b|*cos...therefore: */
|
||||
product = ScalarProduct (a,b);
|
||||
la = VectorMagnitude (a);
|
||||
lb = VectorMagnitude (b);
|
||||
cos = product/(la*lb);
|
||||
angle = acos(cos);
|
||||
TRACE("angle between (%f,%f,%f) and (%f,%f,%f) = %f radians\n", a->u1.x, a->u2.y, a->u3.z, b->u1.x, \
|
||||
b->u2.y, b->u3.z, angle);
|
||||
return angle;
|
||||
}
|
||||
|
@ -161,28 +176,29 @@ static void WINAPI DSOUND_Mix3DBuffer(IDirectSound3DBufferImpl *ds3db)
|
|||
IDirectSound3DListenerImpl *dsl;
|
||||
|
||||
/* volume, at which the sound will be played after all calcs. */
|
||||
LONG lVolume = 0;
|
||||
D3DVALUE lVolume = 0;
|
||||
/* intensity (used for distance related stuff) */
|
||||
double flIntensity;
|
||||
double flTemp;
|
||||
/* stuff for distance related stuff calc. */
|
||||
D3DVECTOR vDistance;
|
||||
D3DVALUE flDistance;
|
||||
D3DVALUE flDistance = 0;
|
||||
/* panning related stuff */
|
||||
D3DVALUE flAngle;
|
||||
D3DVECTOR vLeft;
|
||||
|
||||
if (ds3db->dsb->dsound->listener == NULL)
|
||||
return;
|
||||
|
||||
dsl = ds3db->dsb->dsound->listener;
|
||||
|
||||
/* FIXME: i guess initial volume should be that, but if it's set, sounds get too quiet.
|
||||
It makes sense, though: at min. distance we hear sound with practically no
|
||||
attuneation. If someone has idea, please do it.*/
|
||||
/* lVolume = ds3db->lVolume; */
|
||||
/* initial buffer volume */
|
||||
lVolume = ds3db->lVolume;
|
||||
|
||||
switch (ds3db->ds3db.dwMode)
|
||||
{
|
||||
case DS3DMODE_DISABLE:
|
||||
TRACE("3D processing disabled\n");
|
||||
/* this one is here only to eliminate annoying warning message */
|
||||
DSOUND_RecalcVolPan (&ds3db->dsb->volpan);
|
||||
DSOUND_ForceRemix (ds3db->dsb);
|
||||
break;
|
||||
|
@ -196,7 +212,7 @@ static void WINAPI DSOUND_Mix3DBuffer(IDirectSound3DBufferImpl *ds3db)
|
|||
TRACE("Head-relative 3D processing mode\n");
|
||||
/* distance between buffer and listener is same as buffer's position */
|
||||
flDistance = VectorMagnitude (&ds3db->ds3db.vPosition);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
if (flDistance > ds3db->ds3db.flMaxDistance)
|
||||
|
@ -213,22 +229,62 @@ static void WINAPI DSOUND_Mix3DBuffer(IDirectSound3DBufferImpl *ds3db)
|
|||
flDistance = ds3db->ds3db.flMaxDistance;
|
||||
}
|
||||
if (flDistance < ds3db->ds3db.flMinDistance)
|
||||
flDistance = ds3db->ds3db.flMinDistance;
|
||||
flDistance = ds3db->ds3db.flMinDistance;
|
||||
|
||||
/* the following formula is taken from my physics book. I think it's ok for the *real* world...i hope m$ does it that way */
|
||||
lVolume += 10000; /* ms likes working with negative volume...i don't */
|
||||
lVolume /= 1000; /* convert hundreths of dB into B */
|
||||
/* intensity level (loudness) = log10(Intensity/DefaultIntensity)...therefore */
|
||||
flIntensity = pow(10,lVolume)/DEFAULT_INTENSITY;
|
||||
flIntensity = pow(10,lVolume)*DEFAULT_INTENSITY;
|
||||
flTemp = (flDistance/ds3db->ds3db.flMinDistance)*(flDistance/ds3db->ds3db.flMinDistance);
|
||||
flIntensity /= flTemp;
|
||||
lVolume = log10(flIntensity*DEFAULT_INTENSITY);
|
||||
lVolume = log10(flIntensity/DEFAULT_INTENSITY);
|
||||
lVolume *= 1000; /* convert back to hundreths of dB */
|
||||
lVolume -= 10000; /* we need to do it in ms way */
|
||||
TRACE("dist. att: Distance = %f, MinDistance = %f => adjusting volume %ld to %ld\n", flDistance, ds3db->ds3db.flMinDistance, ds3db->lVolume, lVolume);
|
||||
/* add correct conning here */
|
||||
TRACE("dist. att: Distance = %f, MinDistance = %f => adjusting volume %ld to %f\n", flDistance, ds3db->ds3db.flMinDistance, ds3db->lVolume, lVolume);
|
||||
|
||||
/* conning */
|
||||
/* sometimes it happens that vConeOrientation vector = (0,0,0); in this case angle is "nan" and it's useless*/
|
||||
if (ds3db->ds3db.vConeOrientation.u1.x == 0 && ds3db->ds3db.vConeOrientation.u2.y == 0 && ds3db->ds3db.vConeOrientation.u3.z == 0)
|
||||
{
|
||||
TRACE("conning: cones not set\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* calculate angle */
|
||||
flAngle = AngleBetweenVectorsDeg(&ds3db->ds3db.vConeOrientation, &vDistance);
|
||||
/* if by any chance it happens that OutsideConeAngle = InsideConeAngle (that means that conning has no effect) */
|
||||
if (ds3db->ds3db.dwInsideConeAngle != ds3db->ds3db.dwOutsideConeAngle)
|
||||
{
|
||||
/* my test show that for my way of calc., we need only half of angles */
|
||||
DWORD dwInsideConeAngle = ds3db->ds3db.dwInsideConeAngle/2;
|
||||
DWORD dwOutsideConeAngle = ds3db->ds3db.dwOutsideConeAngle/2;
|
||||
/* full volume */
|
||||
if (flAngle < dwInsideConeAngle)
|
||||
flAngle = dwInsideConeAngle;
|
||||
/* min (app defined) volume */
|
||||
if (flAngle > dwOutsideConeAngle)
|
||||
flAngle = dwOutsideConeAngle;
|
||||
/* this probably isn't the right thing, but it's ok for the time being */
|
||||
lVolume += ((ds3db->ds3db.lConeOutsideVolume)/((dwOutsideConeAngle) - (dwInsideConeAngle))) * flAngle;
|
||||
}
|
||||
TRACE("conning: Angle = %f deg; InsideConeAngle(/2) = %ld deg; OutsideConeAngle(/2) = %ld deg; ConeOutsideVolume = %ld => adjusting volume to %f\n",
|
||||
flAngle, ds3db->ds3db.dwInsideConeAngle/2, ds3db->ds3db.dwOutsideConeAngle/2, ds3db->ds3db.lConeOutsideVolume, lVolume);
|
||||
}
|
||||
|
||||
/* panning */
|
||||
vDistance = VectorBetweenTwoPoints(&dsl->ds3dl.vPosition, &ds3db->ds3db.vPosition);
|
||||
vLeft = VectorProduct(&dsl->ds3dl.vOrientFront, &dsl->ds3dl.vOrientTop);
|
||||
flAngle = AngleBetweenVectorsRad(&vLeft, &vDistance);
|
||||
/* for now, we'll use "linear formula" (which is probably incorrect); if someone has it in book, correct it */
|
||||
ds3db->dsb->volpan.lPan = 10000*2*flAngle/M_PI - 10000;
|
||||
TRACE("panning: Angle = %f rad, lPan = %ld\n", flAngle, ds3db->dsb->volpan.lPan);
|
||||
|
||||
/* doppler shift*/
|
||||
|
||||
/* at last, we got the desired volume */
|
||||
ds3db->dsb->volpan.lVolume = lVolume;
|
||||
ds3db->dsb->dsound->volpan.lVolume = lVolume;
|
||||
DSOUND_RecalcVolPan (&ds3db->dsb->volpan);
|
||||
DSOUND_ForceRemix (ds3db->dsb);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue