From a0b63f4c0c9695606fe8466cb9574ebfb9230d7b Mon Sep 17 00:00:00 2001 From: Stas Cymbalov Date: Sun, 22 Mar 2015 18:22:49 +0300 Subject: dsound: Fix angle to sound source calculation. This patch fixes incorrect sound positioning in dsound. As of now, angle to sound source is calculated as angle between vDistance and vOrientFront. This leads to incorrect results for all sources that are not in the same plane as speakers. In extreme case: for sources directly above or below origin, angle is calculated to -90 degrees, and they are played in the left speaker. This patch changes angle calculation: angle to sound source is calculated as angle between vDistance and plane given by vectors vOrientFront and vOrientTop. --- dlls/dsound/sound3d.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/dlls/dsound/sound3d.c b/dlls/dsound/sound3d.c index 9a0226a..ffd4d45 100644 --- a/dlls/dsound/sound3d.c +++ b/dlls/dsound/sound3d.c @@ -112,7 +112,6 @@ static inline D3DVALUE AngleBetweenVectorsRad (const D3DVECTOR *a, const D3DVECT cos = product/(la*lb); angle = acos(cos); - if (cos < 0.0f) { angle -= M_PI; } TRACE("angle between (%f,%f,%f) and (%f,%f,%f) = %f radians (%f degrees)\n", a->x, a->y, a->z, b->x, b->y, b->z, angle, RadToDeg(angle)); return angle; @@ -264,16 +263,20 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb) else { vLeft = VectorProduct(&dsb->device->ds3dl.vOrientFront, &dsb->device->ds3dl.vOrientTop); - flAngle = AngleBetweenVectorsRad(&dsb->device->ds3dl.vOrientFront, &vDistance); - flAngle2 = AngleBetweenVectorsRad(&vLeft, &vDistance); - - /* AngleBetweenVectorsRad performs a dot product, which gives us the cosine of the angle - * between two vectors. Unfortunately, because cos(theta) = cos(-theta), we've no idea from - * this whether the sound is to our left or to our right. We have to perform another dot - * product, with a vector at right angles to the initial one, to get the correct angle. - * The angle should be between -180 degrees and 180 degrees. */ - if (flAngle < 0.0f) { flAngle += M_PI; } - if (flAngle2 > 0.0f) { flAngle = -flAngle; } + /* To calculate angle to sound source we need to: + * 1) Get angle between vDistance and a plane on which angle to sound source should be 0. + * Such a plane is given by vectors vOrientFront and vOrientTop, and angle between vector + * and a plane equals to M_PI_2 - angle between vector and normal to this plane (vLeft in this case). + * 2) Determine if the source is behind or in front of us by calculating angle between vDistance + * and vOrientFront. + */ + flAngle = AngleBetweenVectorsRad(&vLeft, &vDistance); + flAngle2 = AngleBetweenVectorsRad(&dsb->device->ds3dl.vOrientFront, &vDistance); + if (flAngle2 > M_PI_2) + flAngle = -flAngle; + flAngle -= M_PI_2; + if (flAngle < -M_PI) + flAngle += 2*M_PI; } TRACE("panning: Angle = %f rad, lPan = %d\n", flAngle, dsb->volpan.lPan); -- 2.3.3