dsound: Fix angle to sound source calculation.

Andrew Eikum aeikum at codeweavers.com
Mon Mar 23 09:39:26 CDT 2015


This seems sane to me, but I never had a good grasp on this to begin
with. Does it look OK to you, Mark?

Andrew

On Sun, Mar 22, 2015 at 08:59:15PM +0300, Стас Цымбалов wrote:
> 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(-)

> From 1ebe3761b0d6acfca58cec17472336a05b7f2679 Mon Sep 17 00:00:00 2001
> From: Stas Cymbalov <dummyunit at gmail.com>
> Date: Sun, 22 Mar 2015 18:22:49 +0300
> Subject: dsound: Fix angle to sound source calculation.
> 
> ---
>  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.0.5
> 

> 




More information about the wine-devel mailing list