Module: wine Branch: master Commit: 02f9edfd77302eabc0a8a6e45a9423ebe2b1acef URL: http://source.winehq.org/git/wine.git/?a=commit;h=02f9edfd77302eabc0a8a6e45a...
Author: Mark Harmstone hellas@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)