From: Anton Baskanov baskanov@gmail.com
--- dlls/dsound/buffer.c | 40 ++++++++++++++++++++++-------------- dlls/dsound/dsound_private.h | 1 + dlls/dsound/sound3d.c | 11 +++++----- 3 files changed, 32 insertions(+), 20 deletions(-)
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c index 7b830604a60..1b724ee775b 100644 --- a/dlls/dsound/buffer.c +++ b/dlls/dsound/buffer.c @@ -287,10 +287,17 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency(IDirectSoundBuffer8 *i
AcquireSRWLockExclusive(&This->lock);
- oldFreq = This->freq; - This->freq = freq; - if (freq != oldFreq) - DSOUND_RecalcFormat(This); + if (This->dsbd.dwFlags & DSBCAPS_CTRL3D) { + oldFreq = This->ds3db_freq; + This->ds3db_freq = freq; + if (freq != oldFreq) + DSOUND_Calc3DBuffer(This); + } else { + oldFreq = This->freq; + This->freq = freq; + if (freq != oldFreq) + DSOUND_RecalcFormat(This); + }
ReleaseSRWLockExclusive(&This->lock);
@@ -700,7 +707,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetFrequency(IDirectSoundBuffer8 *i return DSERR_INVALIDPARAM; }
- *freq = This->freq; + *freq = (This->dsbd.dwFlags & DSBCAPS_CTRL3D) ? This->ds3db_freq : This->freq; TRACE("-> %ld\n", *freq);
return DS_OK; @@ -1100,15 +1107,6 @@ HRESULT secondarybuffer_create(DirectSoundDevice *device, const DSBUFFERDESC *ds dsb->sec_mixpos = 0; dsb->state = STATE_STOPPED;
- /* calculate fragment size and write lead */ - DSOUND_RecalcFormat(dsb); - - dsb->committedbuff = malloc(dsb->maxwritelead); - if(!dsb->committedbuff) { - IDirectSoundBuffer8_Release(&dsb->IDirectSoundBuffer8_iface); - return DSERR_OUTOFMEMORY; - } - if (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D) { dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER); dsb->ds3db_ds3db.vPosition.x = 0.0; @@ -1127,11 +1125,23 @@ HRESULT secondarybuffer_create(DirectSoundDevice *device, const DSBUFFERDESC *ds dsb->ds3db_ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE; dsb->ds3db_ds3db.dwMode = DS3DMODE_NORMAL;
+ dsb->ds3db_freq = dsbd->lpwfxFormat->nSamplesPerSec; + dsb->ds3db_need_recalc = FALSE; DSOUND_Calc3DBuffer(dsb); - } else + } else { DSOUND_RecalcVolPan(&(dsb->volpan));
+ /* calculate fragment size and write lead */ + DSOUND_RecalcFormat(dsb); + } + + dsb->committedbuff = malloc(dsb->maxwritelead); + if(!dsb->committedbuff) { + IDirectSoundBuffer8_Release(&dsb->IDirectSoundBuffer8_iface); + return DSERR_OUTOFMEMORY; + } + InitializeSRWLock(&dsb->lock);
/* register buffer */ diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index d9f488c25b8..e67d474d61d 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -164,6 +164,7 @@ struct IDirectSoundBufferImpl /* DirectSound3DBuffer fields */ DS3DBUFFER ds3db_ds3db; LONG ds3db_lVolume; + DWORD ds3db_freq; BOOL ds3db_need_recalc; /* Used for bit depth conversion */ int mix_channels; diff --git a/dlls/dsound/sound3d.c b/dlls/dsound/sound3d.c index 939e0091815..4e98cdc0b8d 100644 --- a/dlls/dsound/sound3d.c +++ b/dlls/dsound/sound3d.c @@ -288,6 +288,8 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb) } TRACE("panning: Angle = %f rad, lPan = %ld\n", flAngle, dsb->volpan.lPan);
+ dsb->freq = dsb->ds3db_freq; + /* FIXME: Doppler Effect disabled since i have no idea which frequency to change and how to do it */ if(0) { @@ -310,16 +312,15 @@ if(0) if listener moves AWAY from buffer, its velocity component is NEGATIVE */ flListenerVel = ProjectVector(&dsb->device->ds3dl.vVelocity, &vDistance); /* formula taken from Gianicoli D.: Physics, 4th edition: */ - /* FIXME: replace dsb->freq with appropriate frequency ! */ - flFreq = dsb->freq * ((DEFAULT_VELOCITY + flListenerVel)/(DEFAULT_VELOCITY + flBufferVel)); + flFreq = dsb->ds3db_freq * ((DEFAULT_VELOCITY + flListenerVel)/(DEFAULT_VELOCITY + flBufferVel)); TRACE("doppler: Buffer velocity (component) = %f, Listener velocity (component) = %f => Doppler shift: %ld Hz -> %f Hz\n", - flBufferVel, flListenerVel, dsb->freq, flFreq); - /* FIXME: replace following line with correct frequency setting ! */ + flBufferVel, flListenerVel, dsb->ds3db_freq, flFreq); dsb->freq = flFreq; - DSOUND_RecalcFormat(dsb); } }
+ DSOUND_RecalcFormat(dsb); + for (i = 0; i < dsb->device->pwfx->nChannels; i++) dsb->volpan.dwTotalAmpFactor[i] = 0;
From: Anton Baskanov baskanov@gmail.com
--- dlls/dsound/tests/ds3d.c | 201 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+)
diff --git a/dlls/dsound/tests/ds3d.c b/dlls/dsound/tests/ds3d.c index 577c4155e9f..4b70e0cc0ee 100644 --- a/dlls/dsound/tests/ds3d.c +++ b/dlls/dsound/tests/ds3d.c @@ -1249,6 +1249,205 @@ return DSERR_GENERIC; return rc; }
+static void check_doppler(IDirectSound *dsound, IDirectSound3DListener *listener, + BOOL play, DWORD mode, float listener_pos, float listener_velocity, + float buffer_pos, float buffer_velocity, DWORD set_freq, DWORD expected_freq) +{ + IDirectSound3DBuffer *buffer_3d; + IDirectSoundBuffer *ref_buffer; + IDirectSoundBuffer *buffer; + WAVEFORMATEX format; + DSBUFFERDESC desc; + DWORD locked_size; + void *locked_data; + HRESULT hr; + DWORD freq; + DWORD size; + char *data; + LONG ref; + + if (play) + { + const char *mode_str = ""; + if (mode == DS3DMODE_HEADRELATIVE) + mode_str = "in head-relative mode "; + else if (mode == DS3DMODE_DISABLE) + mode_str = "with 3D processing disabled "; + trace(" Testing Doppler shift %swith listener at %g, velocity %g" + " with sound at %g, velocity %g, frequency %luHz\n", + mode_str, listener_pos, listener_velocity, buffer_pos, buffer_velocity, set_freq); + } + + memset(&format, 0, sizeof(format)); + format.wFormatTag = WAVE_FORMAT_PCM; + format.nChannels = 1; + format.nSamplesPerSec = 22050; + format.wBitsPerSample = 16; + format.nAvgBytesPerSec = 2 * 22050; + format.nBlockAlign = 2; + + data = wave_generate_la(&format, 0.6, &size, FALSE); + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = 0; + desc.lpwfxFormat = &format; + desc.dwBufferBytes = size; + + hr = IDirectSound_CreateSoundBuffer(dsound, &desc, &ref_buffer, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirectSoundBuffer_Lock(ref_buffer, 0, 0, &locked_data, &locked_size, NULL, NULL, DSBLOCK_ENTIREBUFFER); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + memcpy(locked_data, data, size); + hr = IDirectSoundBuffer_Unlock(ref_buffer, locked_data, locked_size, NULL, 0); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + HeapFree(GetProcessHeap(), 0, data); + + memset(&format, 0, sizeof(format)); + format.wFormatTag = WAVE_FORMAT_PCM; + format.nChannels = 1; + /* Set the sampling frequency of the generated waveform to the frequency + * that the buffer is expected to be played at. This way a successful + * test will produce a 440Hz tone. */ + format.nSamplesPerSec = expected_freq; + format.wBitsPerSample = 16; + format.nAvgBytesPerSec = 2 * expected_freq; + format.nBlockAlign = 2; + + data = wave_generate_la(&format, 0.6, &size, FALSE); + + memset(&format, 0, sizeof(format)); + format.wFormatTag = WAVE_FORMAT_PCM; + format.nChannels = 1; + format.nSamplesPerSec = 22050; + format.wBitsPerSample = 16; + format.nAvgBytesPerSec = 2 * 22050; + format.nBlockAlign = 2; + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRL3D; + desc.lpwfxFormat = &format; + desc.dwBufferBytes = size; + + hr = IDirectSound_CreateSoundBuffer(dsound, &desc, &buffer, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IDirectSoundBuffer_QueryInterface(buffer, &IID_IDirectSound3DBuffer, (void *)&buffer_3d); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirectSoundBuffer_Lock(buffer, 0, 0, &locked_data, &locked_size, NULL, NULL, DSBLOCK_ENTIREBUFFER); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + memcpy(locked_data, data, size); + hr = IDirectSoundBuffer_Unlock(buffer, locked_data, locked_size, NULL, 0); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + HeapFree(GetProcessHeap(), 0, data); + + /* Set to different values first to test that the frequency is updated. */ + hr = IDirectSound3DListener_SetPosition(listener, 0, 0, 0, DS3D_DEFERRED); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IDirectSound3DListener_SetVelocity(listener, 0, 0, 0, DS3D_DEFERRED); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IDirectSound3DBuffer_SetPosition(buffer_3d, 0, 1, 0, DS3D_DEFERRED); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IDirectSound3DBuffer_SetVelocity(buffer_3d, 0, -60, 0, DS3D_DEFERRED); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IDirectSound3DListener_CommitDeferredSettings(listener); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirectSound3DListener_SetPosition(listener, 0, listener_pos, 0, DS3D_DEFERRED); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IDirectSound3DListener_SetVelocity(listener, 0, listener_velocity, 0, DS3D_DEFERRED); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirectSoundBuffer_SetFrequency(buffer, set_freq); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirectSound3DBuffer_SetMode(buffer_3d, mode, DS3D_DEFERRED); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IDirectSound3DBuffer_SetPosition(buffer_3d, 0, buffer_pos, 0, DS3D_DEFERRED); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IDirectSound3DBuffer_SetVelocity(buffer_3d, 0, buffer_velocity, 0, DS3D_DEFERRED); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirectSound3DListener_CommitDeferredSettings(listener); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + freq = 0xdeadbeef; + hr = IDirectSoundBuffer_GetFrequency(buffer, &freq); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(freq == set_freq, "Got frequency %lu\n", freq); + + if (play) + { + trace(" Playing a reference 440Hz tone\n"); + hr = IDirectSoundBuffer_Play(ref_buffer, 0, 0, DSBPLAY_LOOPING); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + Sleep(500); + hr = IDirectSoundBuffer_Stop(ref_buffer); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + trace(" Playing a test tone (should be 440Hz)\n"); + hr = IDirectSoundBuffer_Play(buffer, 0, 0, DSBPLAY_LOOPING); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + Sleep(500); + hr = IDirectSoundBuffer_Stop(buffer); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + } + + IDirectSound3DBuffer_Release(buffer_3d); + ref = IDirectSoundBuffer_Release(buffer); + ok(!ref, "Got outstanding refcount %ld.\n", ref); + ref = IDirectSoundBuffer_Release(ref_buffer); + ok(!ref, "Got outstanding refcount %ld.\n", ref); +} + +static void test_doppler(GUID *guid, BOOL play) +{ + IDirectSound3DListener *listener; + IDirectSoundBuffer *primary; + IDirectSound *dsound; + DSBUFFERDESC desc; + HRESULT hr; + HWND hwnd; + LONG ref; + + hwnd = get_hwnd(); + + hr = DirectSoundCreate(guid, &dsound, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirectSound_SetCooperativeLevel(dsound, hwnd, DSSCL_PRIORITY); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D; + hr = IDirectSound_CreateSoundBuffer(dsound, &desc, &primary, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSound3DListener, (void *)&listener); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + /* When run in interactive mode, the following tests should produce a series + * of 440Hz tones. Any deviation from 440Hz indicates a test failure. */ + + check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 1, 0, 22050, 22050); + check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, -90, 1, -90, 22050, 22050); + + /* Wine TODO: Doppler shift is missing. */ + check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 1, -90, 22050, 29400); + /* Wine TODO: Doppler shift is missing. */ + check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 1, 90, 22050, 17640); + + IDirectSound3DListener_Release(listener); + ref = IDirectSoundBuffer_Release(primary); + ok(!ref, "Got outstanding refcount %ld.\n", ref); + ref = IDirectSound_Release(dsound); + ok(!ref, "Got outstanding refcount %ld.\n", ref); +} + static unsigned driver_count = 0;
static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, @@ -1295,6 +1494,8 @@ static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,1); test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,1);
+ test_doppler(lpGuid,winetest_interactive); + return TRUE; }
From: Anton Baskanov baskanov@gmail.com
--- dlls/dsound/sound3d.c | 6 +----- dlls/dsound/tests/ds3d.c | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/dlls/dsound/sound3d.c b/dlls/dsound/sound3d.c index 4e98cdc0b8d..3dc563b3579 100644 --- a/dlls/dsound/sound3d.c +++ b/dlls/dsound/sound3d.c @@ -167,6 +167,7 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb) int i, num_main_speakers; float a, ingain; /* doppler shift related stuff */ + D3DVALUE flFreq, flBufferVel, flListenerVel;
TRACE("(%p)\n",dsb);
@@ -290,10 +291,6 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb)
dsb->freq = dsb->ds3db_freq;
- /* FIXME: Doppler Effect disabled since i have no idea which frequency to change and how to do it */ -if(0) -{ - D3DVALUE flFreq, flBufferVel, flListenerVel; /* doppler shift*/ if (!VectorMagnitude(&dsb->ds3db_ds3db.vVelocity) && !VectorMagnitude(&dsb->device->ds3dl.vVelocity)) { @@ -317,7 +314,6 @@ if(0) flBufferVel, flListenerVel, dsb->ds3db_freq, flFreq); dsb->freq = flFreq; } -}
DSOUND_RecalcFormat(dsb);
diff --git a/dlls/dsound/tests/ds3d.c b/dlls/dsound/tests/ds3d.c index 4b70e0cc0ee..e71041e3a00 100644 --- a/dlls/dsound/tests/ds3d.c +++ b/dlls/dsound/tests/ds3d.c @@ -1436,9 +1436,9 @@ static void test_doppler(GUID *guid, BOOL play) check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 1, 0, 22050, 22050); check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, -90, 1, -90, 22050, 22050);
- /* Wine TODO: Doppler shift is missing. */ + /* Wine TODO: The frequency is slightly off. */ check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 1, -90, 22050, 29400); - /* Wine TODO: Doppler shift is missing. */ + /* Wine TODO: The frequency is slightly off. */ check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 1, 90, 22050, 17640);
IDirectSound3DListener_Release(listener);
From: Anton Baskanov baskanov@gmail.com
--- dlls/dsound/sound3d.c | 2 +- dlls/dsound/tests/ds3d.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/dlls/dsound/sound3d.c b/dlls/dsound/sound3d.c index 3dc563b3579..2a45ca239a6 100644 --- a/dlls/dsound/sound3d.c +++ b/dlls/dsound/sound3d.c @@ -50,7 +50,7 @@ #include "dsound_private.h"
/* default velocity of sound in the air */ -#define DEFAULT_VELOCITY 340 +#define DEFAULT_VELOCITY 360
WINE_DEFAULT_DEBUG_CHANNEL(dsound3d);
diff --git a/dlls/dsound/tests/ds3d.c b/dlls/dsound/tests/ds3d.c index e71041e3a00..76269f1fcfe 100644 --- a/dlls/dsound/tests/ds3d.c +++ b/dlls/dsound/tests/ds3d.c @@ -1436,9 +1436,7 @@ static void test_doppler(GUID *guid, BOOL play) check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 1, 0, 22050, 22050); check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, -90, 1, -90, 22050, 22050);
- /* Wine TODO: The frequency is slightly off. */ check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 1, -90, 22050, 29400); - /* Wine TODO: The frequency is slightly off. */ check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 1, 90, 22050, 17640);
IDirectSound3DListener_Release(listener);
From: Anton Baskanov baskanov@gmail.com
--- dlls/dsound/tests/ds3d.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/dlls/dsound/tests/ds3d.c b/dlls/dsound/tests/ds3d.c index 76269f1fcfe..a380b44f1d7 100644 --- a/dlls/dsound/tests/ds3d.c +++ b/dlls/dsound/tests/ds3d.c @@ -1439,6 +1439,9 @@ static void test_doppler(GUID *guid, BOOL play) check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 1, -90, 22050, 29400); check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 1, 90, 22050, 17640);
+ /* Wine TODO: The sound is missing. */ + check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 0, -90, 22050, 22050); + IDirectSound3DListener_Release(listener); ref = IDirectSoundBuffer_Release(primary); ok(!ref, "Got outstanding refcount %ld.\n", ref);
From: Anton Baskanov baskanov@gmail.com
--- dlls/dsound/sound3d.c | 3 ++- dlls/dsound/tests/ds3d.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/dsound/sound3d.c b/dlls/dsound/sound3d.c index 2a45ca239a6..12b92213314 100644 --- a/dlls/dsound/sound3d.c +++ b/dlls/dsound/sound3d.c @@ -298,7 +298,8 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb) } else if (!(dsb->ds3db_ds3db.vVelocity.x == dsb->device->ds3dl.vVelocity.x && dsb->ds3db_ds3db.vVelocity.y == dsb->device->ds3dl.vVelocity.y && - dsb->ds3db_ds3db.vVelocity.z == dsb->device->ds3dl.vVelocity.z)) + dsb->ds3db_ds3db.vVelocity.z == dsb->device->ds3dl.vVelocity.z) && + !(vDistance.x == 0.0f && vDistance.y == 0.0f && vDistance.z == 0.0f)) { /* calculate length of ds3db_ds3db.vVelocity component which causes Doppler Effect NOTE: if buffer moves TOWARDS the listener, its velocity component is NEGATIVE diff --git a/dlls/dsound/tests/ds3d.c b/dlls/dsound/tests/ds3d.c index a380b44f1d7..5e6ba4d204e 100644 --- a/dlls/dsound/tests/ds3d.c +++ b/dlls/dsound/tests/ds3d.c @@ -1439,7 +1439,6 @@ static void test_doppler(GUID *guid, BOOL play) check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 1, -90, 22050, 29400); check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 1, 90, 22050, 17640);
- /* Wine TODO: The sound is missing. */ check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 0, -90, 22050, 22050);
IDirectSound3DListener_Release(listener);
Huw Davies (@huw) commented about dlls/dsound/sound3d.c:
#include "dsound_private.h"
/* default velocity of sound in the air */ -#define DEFAULT_VELOCITY 340 +#define DEFAULT_VELOCITY 360
I've not yet looked into the MR in any great detail, but this seems unfortunate. Although of course the speed of sound in air is temperature and pressure dependent, the commonly accepted value at 20 celsius and 1 atm is around 340 m/s.
On Mon May 1 08:31:19 2023 +0000, Huw Davies wrote:
I've not yet looked into the MR in any great detail, but this seems unfortunate. Although of course the speed of sound in air is temperature and pressure dependent, the commonly accepted value at 20 celsius and 1 atm is around 340 m/s.
You are right, but the tests show that the used value is closer to 360. Maybe I'm missing something.
Thanks Anton! Never noticed doppler effect was missing from wine dsound before seeing this MR, but now I always notice it in Zusi 3.
I don't know a lot about sound programming, but the general approach in this MR might be different from Windows because it changes the pitch by speeding up sound playback, i.e. increasing the buffer sampling frequency.
While wondering about the consequences of changing the freq, I modified the test code a bit: Remove the DSBPLAY_LOOPING flag, increase the sleep duration after starting playback to 1200ms, and change the 3D buffer's velocity to -350 / +350 instead of -90 / +90, so that it's easier to notice the effect. Now this MR results in just a very short "blip" for the high-pitched case and a longer-than-600ms sound for the other case (isn't this similar to what actually happens in the real world, too?). On Windows, the same test appears to result in 600ms sounds in both cases, but with a pitch applied.
So I believe the general approach may need to be changed, so that sound buffers have a higher/lower pitch when doppler effect applies, but the read position should still progress at the same speed as without doppler effect. As I said, I don't really know a lot about sound programming, so I'm not really sure how that is possible, but it appears to happen on Windows. It would be interesting to test this with an actual sound file (like a siren) and see if Windows really doesn't speed it up when applying the doppler effect, maybe something in my test mislead me?
Maybe this isn't an issue in real-world applications at all, in which case this MR would improve the wine status quo.
On Wed May 10 09:58:07 2023 +0000, Florian Will wrote:
Thanks Anton! Never noticed doppler effect was missing from wine dsound before seeing this MR, but now I always notice it in Zusi 3. I don't know a lot about sound programming, but the general approach in this MR might be different from Windows because it changes the pitch by speeding up sound playback, i.e. increasing the buffer sampling frequency. While wondering about the consequences of changing the freq, I modified the test code a bit: Remove the DSBPLAY_LOOPING flag, increase the sleep duration after starting playback to 1200ms, and change the 3D buffer's velocity to -350 / +350 instead of -90 / +90, so that it's easier to notice the effect. Now this MR results in just a very short "blip" for the high-pitched case and a longer-than-600ms sound for the other case (isn't this similar to what actually happens in the real world, too?). On Windows, the same test appears to result in 600ms sounds in both cases, but with a pitch applied. So I believe the general approach may need to be changed, so that sound buffers have a higher/lower pitch when doppler effect applies, but the read position should still progress at the same speed as without doppler effect. As I said, I don't really know a lot about sound programming, so I'm not really sure how that is possible, but it appears to happen on Windows. It would be interesting to test this with an actual sound file (like a siren) and see if Windows really doesn't speed it up when applying the doppler effect, maybe something in my test mislead me? Maybe this isn't an issue in real-world applications at all, in which case this MR would improve the wine status quo.
Thanks for the feedback.
I did some more testing to try and reproduce the pitch shifting behavior, but it turns out not to be the case. I modified wave_generate_la() to change the sine wave pitch over time (like a car alarm), and what I see is that Windows just speeds up the sound playback.
I also tried to reproduce your results and yes, I got the short blip with this MR and a longer tone on Windows. Notice also that the blip has a much higher pitch. I think that the difference is caused by Windows limiting the Doppler effect to half the speed of sound, so +-350 becomes +-180. There is a patch that adds this limit in the development branch: https://gitlab.winehq.org/baskanov/wine/-/commits/dsound-doppler/
On Thu May 11 03:00:53 2023 +0000, Anton Baskanov wrote:
Thanks for the feedback. I did some more testing to try and reproduce the pitch shifting behavior, but it turns out not to be the case. I modified wave_generate_la() to change the sine wave pitch over time (like a car alarm), and what I see is that Windows just speeds up the sound playback. I also tried to reproduce your results and yes, I got the short blip with this MR and a longer tone on Windows. Notice also that the blip has a much higher pitch. I think that the difference is caused by Windows limiting the Doppler effect to half the speed of sound, so +-350 becomes +-180. There is a patch that adds this limit in the development branch: https://gitlab.winehq.org/baskanov/wine/-/commits/dsound-doppler/
Oh, that makes sense! I'm sorry for the (my) confusion. This patch really improves Zusi 3 when a train passes by, so thanks again, and I hope it will be merged soon. :-)
Is there anything I can improve to get this merged?
On Wed May 17 12:24:06 2023 +0000, Anton Baskanov wrote:
Is there anything I can improve to get this merged?
I'm hoping to look at this again next week - sorry about the delay.
On Thu May 11 06:35:51 2023 +0000, Anton Baskanov wrote:
You are right, but the tests show that the used value is closer to 360. Maybe I'm missing something.
Could we add a comment to the effect that Windows appears to use a slightly higher than accepted value? This is to avoid somebody looking at this in the future and trying to 'correct' it back to 340 m/s.
Huw Davies (@huw) commented about dlls/dsound/tests/ds3d.c:
check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 1, -90, 22050, 29400); check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 1, 90, 22050, 17640);
- /* Wine TODO: The sound is missing. */
- check_doppler(dsound, listener, play, DS3DMODE_NORMAL, 0, 0, 0, -90, 22050, 22050);
I'd suggest squashing this commit in with the next one - they're both very small (and related) changes.