Mark Harmstone : dsound: Do not use panning to set sound position.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed Jan 7 17:15:37 CST 2015
Module: wine
Branch: master
Commit: 02f9edfd77302eabc0a8a6e45a9423ebe2b1acef
URL: http://source.winehq.org/git/wine.git/?a=commit;h=02f9edfd77302eabc0a8a6e45a9423ebe2b1acef
Author: Mark Harmstone <hellas at burntcomma.com>
Date: Tue Jan 6 19:27:00 2015 +0000
dsound: Do not use panning to set sound position.
---
dlls/dsound/sound3d.c | 52 +++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 44 insertions(+), 8 deletions(-)
diff --git a/dlls/dsound/sound3d.c b/dlls/dsound/sound3d.c
index 604d19b..329de94 100644
--- a/dlls/dsound/sound3d.c
+++ b/dlls/dsound/sound3d.c
@@ -114,6 +114,7 @@ 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;
@@ -159,8 +160,10 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb)
D3DVECTOR vDistance;
D3DVALUE flDistance = 0;
/* panning related stuff */
- D3DVALUE flAngle;
+ D3DVALUE flAngle, flAngle2;
D3DVECTOR vLeft;
+ int i;
+ float a, ingain;
/* doppler shift related stuff */
TRACE("(%p)\n",dsb);
@@ -241,21 +244,35 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb)
flAngle, dsb->ds3db_ds3db.dwInsideConeAngle/2, dsb->ds3db_ds3db.dwOutsideConeAngle/2, dsb->ds3db_ds3db.lConeOutsideVolume, lVolume);
}
dsb->volpan.lVolume = lVolume;
+
+ ingain = pow(2.0, dsb->volpan.lVolume / 600.0) * 0xffff;
+
+ if (dsb->device->pwfx->nChannels == 1)
+ {
+ dsb->volpan.dwTotalAmpFactor[0] = ingain;
+ return;
+ }
/* panning */
if (dsb->device->ds3dl.vPosition.x == dsb->ds3db_ds3db.vPosition.x &&
dsb->device->ds3dl.vPosition.y == dsb->ds3db_ds3db.vPosition.y &&
dsb->device->ds3dl.vPosition.z == dsb->ds3db_ds3db.vPosition.z) {
- dsb->volpan.lPan = 0;
flAngle = 0.0;
}
else
{
vDistance = VectorBetweenTwoPoints(&dsb->device->ds3dl.vPosition, &dsb->ds3db_ds3db.vPosition);
vLeft = VectorProduct(&dsb->device->ds3dl.vOrientFront, &dsb->device->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 */
- dsb->volpan.lPan = 10000*2*flAngle/M_PI - 10000;
+ 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; }
}
TRACE("panning: Angle = %f rad, lPan = %d\n", flAngle, dsb->volpan.lPan);
@@ -290,9 +307,28 @@ if(0)
DSOUND_RecalcFormat(dsb);
}
}
-
- /* time for remix */
- DSOUND_RecalcVolPan(&dsb->volpan);
+
+ for (i = 0; i < dsb->device->pwfx->nChannels; i++)
+ dsb->volpan.dwTotalAmpFactor[i] = 0;
+
+ /* adapted from OpenAL's Alc/panning.c */
+ for (i = 0; i < dsb->device->pwfx->nChannels - 1; i++)
+ {
+ if(flAngle >= dsb->device->speaker_angles[i] && flAngle < dsb->device->speaker_angles[i+1])
+ {
+ /* Sound is between speakers i and i+1 */
+ a = (flAngle-dsb->device->speaker_angles[i]) / (dsb->device->speaker_angles[i+1]-dsb->device->speaker_angles[i]);
+ dsb->volpan.dwTotalAmpFactor[dsb->device->speaker_num[i]] = sqrtf(1.0f-a) * ingain;
+ dsb->volpan.dwTotalAmpFactor[dsb->device->speaker_num[i+1]] = sqrtf(a) * ingain;
+ return;
+ }
+ }
+
+ /* Sound is between last and first speakers */
+ if (flAngle < dsb->device->speaker_angles[0]) { flAngle += M_PI*2.0f; }
+ a = (flAngle-dsb->device->speaker_angles[i]) / (M_PI*2.0f + dsb->device->speaker_angles[0]-dsb->device->speaker_angles[i]);
+ dsb->volpan.dwTotalAmpFactor[dsb->device->speaker_num[i]] = sqrtf(1.0f-a) * ingain;
+ dsb->volpan.dwTotalAmpFactor[dsb->device->speaker_num[0]] = sqrtf(a) * ingain;
}
static void DSOUND_Mix3DBuffer(IDirectSoundBufferImpl *dsb)
More information about the wine-cvs
mailing list