Fix winmm's check_position() tests

Francois Gouget fgouget at
Tue Jul 20 12:01:31 CDT 2004

Hi Robert,

Robert Reif wrote:
> Please revert this patch.  It is wrong and produces the following errors 
> in windows xp:

Aaaargh, you were right. The problem was caused by another change I made 
a long time ago while experimenting with wave_generate_la(). I had 
completely forgotten that this change added an extra sample for a given 
duration so I looked everywhere but there. That also explains why my 
results were consistent across platforms.
Sorry. I suck :-(

The silver lining is that this made me realise that the disconnect 
between wave_generate_la() and check_position(). I found other problems 
with that.

If I change the duration to 1.11 seconds, then wave_generate_la() 
computes the number of sample as follows:


So for an 11025x16x2 test we get nb_samples = 12237.75 which is rounded 
down to 12237.

But check_position() computes everything based on the theoretical duration:

-> bytes = 1.11 * (11025*2*2) = 1.11 * 44100 = 48951
but in fact the number of bytes is:
    bytes = nb_samples * (2*2) = 12237 * 4 = 48948

So the test fails. Another way to see this is that since we rounded down 
the number of samples the real duration is now

real_duration = 12337 / samples_per_sec = 1.10993

So all calculations based on the original duration are slightly off.

So this patch:
  * reverts my previous incorrect change in check_position()
  * modifies check_position() to work off the actual number of bytes as 
calculated by wave_generate_la() (which we get from frag.dwBufferLength)
  * finally check_position() was not ronuding up the frame field of 


  * dlls/winmm/tests/wave.c

    Francois Gouget <fgouget at>
    Revert my previous incorrect check_position() patch: Windows returns 
exactly the number of samples/bytes played (no plus one there).
    Modify check_position() to work off the actual number of bytes as 
calculated by wave_generate_la(). This fixes problems due to rounding 
when duration is not a neat integer.
    Round up the frame field when checking TIME_SMPTE.

Francois Gouget
fgouget at

-------------- next part --------------
Index: dlls/winmm/tests/wave.c
RCS file: /var/cvs/wine/dlls/winmm/tests/wave.c,v
retrieving revision 1.33
diff -u -r1.33 wave.c
--- dlls/winmm/tests/wave.c	20 Jul 2004 01:22:47 -0000	1.33
+++ dlls/winmm/tests/wave.c	20 Jul 2004 16:45:25 -0000
@@ -211,19 +211,22 @@
     return msg;
-static void check_position(int device, HWAVEOUT wout, double duration, LPWAVEFORMATEX pwfx)
+static void check_position(int device, HWAVEOUT wout, DWORD bytes, LPWAVEFORMATEX pwfx )
     MMTIME mmtime;
+    DWORD samples;
     MMRESULT rc;
+    samples=bytes*8/pwfx->wBitsPerSample/pwfx->nChannels;
     mmtime.wType = TIME_BYTES;
     rc=waveOutGetPosition(wout, &mmtime, sizeof(mmtime));
        "waveOutGetPosition: device=%s rc=%s\n",dev_name(device),wave_out_error(rc));
     if (mmtime.wType == TIME_BYTES)
-        ok(mmtime.u.cb==duration*pwfx->nAvgBytesPerSec+pwfx->wBitsPerSample/8,
+        ok(mmtime.u.cb==bytes,
            "waveOutGetPosition returned %ld bytes, should be %ld\n",
-           mmtime.u.cb, (DWORD)(duration*pwfx->nAvgBytesPerSec)+pwfx->wBitsPerSample/8);
+           mmtime.u.cb, bytes);
         trace("TIME_BYTES not supported, returned %s\n",wave_time_format(mmtime.wType));
@@ -232,9 +235,9 @@
        "waveOutGetPosition: device=%s rc=%s\n",dev_name(device),wave_out_error(rc));
     if (mmtime.wType == TIME_SAMPLES)
-        ok(mmtime.u.sample==duration*pwfx->nSamplesPerSec+1,
+        ok(mmtime.u.sample==samples,
            "waveOutGetPosition returned %ld samples, should be %ld\n",
-           mmtime.u.sample, (DWORD)(duration*pwfx->nSamplesPerSec)+1);
+           mmtime.u.sample, samples);
         trace("TIME_SAMPLES not supported, returned %s\n",wave_time_format(mmtime.wType));
@@ -243,9 +246,9 @@
        "waveOutGetPosition: device=%s rc=%s\n",dev_name(device),wave_out_error(rc));
     if (mmtime.wType == TIME_MS)
-        ok(*1000),
+        ok(*1000/pwfx->nSamplesPerSec,
            "waveOutGetPosition returned %ld ms, should be %ld\n",
- , (DWORD)(duration*1000));
+ , samples*1000/pwfx->nSamplesPerSec);
         trace("TIME_MS not supported, returned %s\n",wave_time_format(mmtime.wType));
@@ -254,18 +257,22 @@
        "waveOutGetPosition: device=%s rc=%s\n",dev_name(device),wave_out_error(rc));
     if (mmtime.wType == TIME_SMPTE)
+    {
+        double duration=((double)samples)/pwfx->nSamplesPerSec;
+        BYTE frames=ceil(fmod(duration*mmtime.u.smpte.fps, mmtime.u.smpte.fps));
         ok(mmtime.u.smpte.hour==(BYTE)(floor(duration/(60*60))) &&
            mmtime.u.smpte.min==(BYTE)(fmod(floor(duration/60), 60)) &&
            mmtime.u.smpte.sec==(BYTE)(fmod(duration,60)) &&
-           mmtime.u.smpte.frame==(BYTE)(fmod(duration*mmtime.u.smpte.fps, mmtime.u.smpte.fps)),
+           mmtime.u.smpte.frame==frames,
            "waveOutGetPosition returned %d:%d:%d %d, should be %d:%d:%d %d\n",
            mmtime.u.smpte.hour, mmtime.u.smpte.min, mmtime.u.smpte.sec, mmtime.u.smpte.frame,
            (BYTE)(fmod(floor(duration/60), 60)),
-           (BYTE)(fmod(duration*mmtime.u.smpte.fps, mmtime.u.smpte.fps)));
+           frames);
+    }
-        trace("TIME_TIME_SMPTE not supported, returned %s\n",wave_time_format(mmtime.wType));
+        trace("TIME_SMPTE not supported, returned %s\n",wave_time_format(mmtime.wType));
 static void wave_out_test_deviceOut(int device, double duration, LPWAVEFORMATEX pwfx, DWORD format, DWORD flags, LPWAVEOUTCAPS pcaps)
@@ -357,7 +364,7 @@
         ok(rc==MMSYSERR_NOERROR,"waveOutSetVolume: device=%s rc=%s\n",dev_name(device),wave_out_error(rc));
-        check_position(device, wout, duration, pwfx);
+        check_position(device, wout, frag.dwBufferLength, pwfx);
     rc=waveOutUnprepareHeader(wout, &frag, sizeof(frag));

More information about the wine-patches mailing list