Added version information.
[wine] / dlls / winmm / tests / wave.c
1 /*
2  * Unit tests for winmm functions
3  *
4  * Copyright (c) 2002 Francois Gouget
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <math.h>
24
25 #include "wine/test.h"
26 #include "winbase.h"
27 #include "mmsystem.h"
28
29 /*
30  * Note that in most of this test we may get MMSYSERR_BADDEVICEID errors
31  * at about any time if the user starts another application that uses the
32  * sound device. So we should not report these as test failures.
33  *
34  * This test can play a test tone. But this only makes sense if someone
35  * is going to carefully listen to it, and would only bother everyone else.
36  * So this is only done if the test is being run in interactive mode.
37  */
38
39 #ifndef WAVE_FORMAT_48M08
40 #define WAVE_FORMAT_48M08      0x00001000    /* 48     kHz, Mono,   8-bit  */
41 #define WAVE_FORMAT_48S08      0x00002000    /* 48     kHz, Stereo, 8-bit  */
42 #define WAVE_FORMAT_48M16      0x00004000    /* 48     kHz, Mono,   16-bit */
43 #define WAVE_FORMAT_48S16      0x00008000    /* 48     kHz, Stereo, 16-bit */
44 #define WAVE_FORMAT_96M08      0x00010000    /* 96     kHz, Mono,   8-bit  */
45 #define WAVE_FORMAT_96S08      0x00020000    /* 96     kHz, Stereo, 8-bit  */
46 #define WAVE_FORMAT_96M16      0x00040000    /* 96     kHz, Mono,   16-bit */
47 #define WAVE_FORMAT_96S16      0x00080000    /* 96     kHz, Stereo, 16-bit */
48 #endif
49
50 static const unsigned int win_formats[][4]={
51     {WAVE_FORMAT_1M08,  11025,  8, 1},
52     {WAVE_FORMAT_1S08,  11025,  8, 2},
53     {WAVE_FORMAT_1M16,  11025, 16, 1},
54     {WAVE_FORMAT_1S16,  11025, 16, 2},
55     {WAVE_FORMAT_2M08,  22050,  8, 1},
56     {WAVE_FORMAT_2S08,  22050,  8, 2},
57     {WAVE_FORMAT_2M16,  22050, 16, 1},
58     {WAVE_FORMAT_2S16,  22050, 16, 2},
59     {WAVE_FORMAT_4M08,  44100,  8, 1},
60     {WAVE_FORMAT_4S08,  44100,  8, 2},
61     {WAVE_FORMAT_4M16,  44100, 16, 1},
62     {WAVE_FORMAT_4S16,  44100, 16, 2},
63     {WAVE_FORMAT_48M08, 48000,  8, 1},
64     {WAVE_FORMAT_48S08, 48000,  8, 2},
65     {WAVE_FORMAT_48M16, 48000, 16, 1},
66     {WAVE_FORMAT_48S16, 48000, 16, 2},
67     {WAVE_FORMAT_96M08, 96000,  8, 1},
68     {WAVE_FORMAT_96S08, 96000,  8, 2},
69     {WAVE_FORMAT_96M16, 96000, 16, 1},
70     {WAVE_FORMAT_96S16, 96000, 16, 2}
71 };
72 #define NB_WIN_FORMATS (sizeof(win_formats)/sizeof(*win_formats))
73
74 #define PI 3.14159265358979323846
75 static char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size)
76 {
77     int i;
78     int nb_samples;
79     char* buf;
80     char* b;
81
82     nb_samples=(int)(duration*wfx->nSamplesPerSec);
83     *size=nb_samples*wfx->nBlockAlign;
84     b=buf=malloc(*size);
85     for (i=0;i<nb_samples;i++) {
86         double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec);
87         if (wfx->wBitsPerSample==8) {
88             unsigned char sample=(unsigned char)((double)127.5*(y+1.0));
89             *b++=sample;
90             if (wfx->nChannels==2)
91                *b++=sample;
92         } else {
93             signed short sample=(signed short)((double)32767.5*y-0.5);
94             b[0]=sample & 0xff;
95             b[1]=sample >> 8;
96             b+=2;
97             if (wfx->nChannels==2) {
98                 b[0]=sample & 0xff;
99                 b[1]=sample >> 8;
100                 b+=2;
101             }
102         }
103     }
104     return buf;
105 }
106
107 static const char * wave_out_error(MMRESULT error)
108 {
109     static char msg[1024];
110     MMRESULT rc;
111
112     rc = waveOutGetErrorText(error, msg, sizeof(msg));
113     if (rc != MMSYSERR_NOERROR)
114         sprintf(msg, "waveOutGetErrorText(%x) failed with error %x", error, rc);
115     return msg;
116 }
117
118 static const char * wave_open_flags(DWORD flags)
119 {
120     static char msg[1024];
121     int first = TRUE;
122     msg[0] = 0;
123     if ((flags & CALLBACK_TYPEMASK) == CALLBACK_EVENT) {
124         strcat(msg, "CALLBACK_EVENT");
125         first = FALSE;
126     }
127     if ((flags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION) {
128         if (!first) strcat(msg, "|");
129         strcat(msg, "CALLBACK_FUNCTION");
130         first = FALSE;
131     }
132     if ((flags & CALLBACK_TYPEMASK) == CALLBACK_NULL) {
133         if (!first) strcat(msg, "|");
134         strcat(msg, "CALLBACK_NULL");
135         first = FALSE;
136     }
137     if ((flags & CALLBACK_TYPEMASK) == CALLBACK_THREAD) {
138         if (!first) strcat(msg, "|");
139         strcat(msg, "CALLBACK_THREAD");
140         first = FALSE;
141     }
142     if ((flags & CALLBACK_TYPEMASK) == CALLBACK_WINDOW) {
143         if (!first) strcat(msg, "|");
144         strcat(msg, "CALLBACK_WINDOW");
145         first = FALSE;
146     }
147     if ((flags & WAVE_ALLOWSYNC) == WAVE_ALLOWSYNC) {
148         if (!first) strcat(msg, "|");
149         strcat(msg, "WAVE_ALLOWSYNC");
150         first = FALSE;
151     }
152     if ((flags & WAVE_FORMAT_DIRECT) == WAVE_FORMAT_DIRECT) {
153         if (!first) strcat(msg, "|");
154         strcat(msg, "WAVE_FORMAT_DIRECT");
155         first = FALSE;
156     }
157     if ((flags & WAVE_FORMAT_QUERY) == WAVE_FORMAT_QUERY) {
158         if (!first) strcat(msg, "|");
159         strcat(msg, "WAVE_FORMAT_QUERY");
160         first = FALSE;
161     }
162     if ((flags & WAVE_MAPPED) == WAVE_MAPPED) {
163         if (!first) strcat(msg, "|");
164         strcat(msg, "WAVE_MAPPED");
165         first = FALSE;
166     }
167     return msg;
168 }
169
170 static void wave_out_test_deviceOut(int device, int format, DWORD flags)
171 {
172     WAVEFORMATEX wfx;
173     HWAVEOUT wout;
174     HANDLE hevent;
175     WAVEHDR frag;
176     MMRESULT rc;
177     DWORD volume;
178
179     hevent=CreateEvent(NULL,FALSE,FALSE,NULL);
180     ok(hevent!=NULL,"CreateEvent: error=%ld\n",GetLastError());
181     if (hevent==NULL)
182         return;
183
184     wfx.wFormatTag=WAVE_FORMAT_PCM;
185     wfx.nChannels=win_formats[format][3];
186     wfx.wBitsPerSample=win_formats[format][2];
187     wfx.nSamplesPerSec=win_formats[format][1];
188     wfx.nBlockAlign=wfx.nChannels*wfx.wBitsPerSample/8;
189     wfx.nAvgBytesPerSec=wfx.nSamplesPerSec*wfx.nBlockAlign;
190     wfx.cbSize=0;
191
192     wout=NULL;
193     rc=waveOutOpen(&wout,device,&wfx,(DWORD)hevent,0,CALLBACK_EVENT|flags);
194     /* Note: Win9x doesn't know WAVE_FORMAT_DIRECT */
195     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
196        (rc==MMSYSERR_INVALFLAG && (flags & WAVE_FORMAT_DIRECT)),
197        "waveOutOpen: device=%d format=%ldx%2dx%d flags=%lx(%s) rc=%d(%s)",device,
198        wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,CALLBACK_EVENT|flags,
199        wave_open_flags(CALLBACK_EVENT|flags),rc,wave_out_error(rc));
200     if (rc!=MMSYSERR_NOERROR) {
201         CloseHandle(hevent);
202         return;
203     }
204
205     ok(wfx.nChannels==win_formats[format][3] &&
206        wfx.wBitsPerSample==win_formats[format][2] &&
207        wfx.nSamplesPerSec==win_formats[format][1],
208        "got the wrong format: %ldx%2dx%d instead of %dx%2dx%d\n",
209        wfx.nSamplesPerSec, wfx.wBitsPerSample,
210        wfx.nChannels, win_formats[format][1], win_formats[format][2],
211        win_formats[format][3]);
212
213     frag.lpData=wave_generate_la(&wfx,1.0,&frag.dwBufferLength);
214     frag.dwFlags=0;
215     frag.dwLoops=0;
216
217     rc=waveOutGetVolume(wout,&volume);
218     ok(rc==MMSYSERR_NOERROR,"waveOutGetVolume: device=%d rc=%d\n",device,rc);
219
220     rc=waveOutPrepareHeader(wout, &frag, sizeof(frag));
221     ok(rc==MMSYSERR_NOERROR,
222        "waveOutPrepareHeader: device=%d rc=%d\n",device,rc);
223
224     if (winetest_interactive && rc==MMSYSERR_NOERROR) {
225         trace("Playing 440Hz LA at %ldx%2dx%d %04lx\n",
226               wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels,flags);
227         rc=waveOutSetVolume(wout,0x20002000);
228         ok(rc==MMSYSERR_NOERROR,"waveOutSetVolume: device=%d rc=%d\n",device,rc);
229         WaitForSingleObject(hevent,INFINITE);
230
231         rc=waveOutWrite(wout, &frag, sizeof(frag));
232         ok(rc==MMSYSERR_NOERROR,"waveOutWrite: device=%d rc=%d\n",device,rc);
233         WaitForSingleObject(hevent,INFINITE);
234
235         rc=waveOutSetVolume(wout,volume);
236         ok(rc==MMSYSERR_NOERROR,"waveOutSetVolume: device=%d rc=%d\n",device,rc);
237     }
238
239     rc=waveOutUnprepareHeader(wout, &frag, sizeof(frag));
240     ok(rc==MMSYSERR_NOERROR,
241        "waveOutUnprepareHeader: device=%d rc=%d\n",device,rc);
242     free(frag.lpData);
243
244     CloseHandle(hevent);
245     waveOutClose(wout);
246 }
247
248 static void wave_out_tests()
249 {
250     WAVEOUTCAPS caps;
251     WAVEFORMATEX format, oformat;
252     HWAVEOUT wout;
253     MMRESULT rc;
254     UINT ndev,d,f;
255
256     ndev=waveOutGetNumDevs();
257     trace("found %d WaveOut devices\n",ndev);
258
259     rc=waveOutGetDevCapsA(ndev+1,&caps,sizeof(caps));
260     ok(rc==MMSYSERR_BADDEVICEID,
261        "waveOutGetDevCapsA: MMSYSERR_BADDEVICEID expected, got %d",rc);
262
263     format.wFormatTag=WAVE_FORMAT_PCM;
264     format.nChannels=2;
265     format.wBitsPerSample=16;
266     format.nSamplesPerSec=44100;
267     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
268     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
269     format.cbSize=0;
270     rc=waveOutOpen(&wout,ndev+1,&format,0,0,CALLBACK_NULL);
271     ok(rc==MMSYSERR_BADDEVICEID,
272        "waveOutOpen: MMSYSERR_BADDEVICEID expected, got %d",rc);
273
274     for (d=0;d<ndev;d++) {
275         rc=waveOutGetDevCapsA(d,&caps,sizeof(caps));
276         ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID,
277            "waveOutGetDevCapsA: failed to get capabilities of device %d: rc=%d",d,rc);
278         if (rc==MMSYSERR_BADDEVICEID)
279             continue;
280
281         trace("  %d: \"%s\" %d.%d (%d:%d): channels=%d formats=%05lx support=%04lx\n",
282               d,caps.szPname,caps.vDriverVersion >> 8,
283               caps.vDriverVersion & 0xff,
284               caps.wMid,caps.wPid,
285               caps.wChannels,caps.dwFormats,caps.dwSupport);
286
287         for (f=0;f<NB_WIN_FORMATS;f++) {
288             if (caps.dwFormats & win_formats[f][0]) {
289                 wave_out_test_deviceOut(d,f,0);
290                 wave_out_test_deviceOut(d,f,WAVE_FORMAT_DIRECT);
291             }
292         }
293
294         /* Try an invalid format to test error handling */
295         trace("Testing invalid 2MHz format\n");
296         format.wFormatTag=WAVE_FORMAT_PCM;
297         format.nChannels=2;
298         format.wBitsPerSample=16;
299         format.nSamplesPerSec=2000000; /* 2MHz! */
300         format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
301         format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
302         format.cbSize=0;
303         oformat=format;
304         rc=waveOutOpen(&wout,d,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
305         ok(rc==WAVERR_BADFORMAT,
306            "waveOutOpen: opening the device at 2MHz should fail %d: rc=%d",d,rc);
307         if (rc==MMSYSERR_NOERROR) {
308             trace("     got %ldx%2dx%d for %ldx%2dx%d\n",
309                   format.nSamplesPerSec, format.wBitsPerSample,
310                   format.nChannels,
311                   oformat.nSamplesPerSec, oformat.wBitsPerSample,
312                   oformat.nChannels);
313             waveOutClose(wout);
314         }
315
316         format.wFormatTag=WAVE_FORMAT_PCM;
317         format.nChannels=2;
318         format.wBitsPerSample=16;
319         format.nSamplesPerSec=2000000; /* 2MHz! */
320         format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
321         format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
322         format.cbSize=0;
323         rc=waveOutOpen(&wout,d,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
324         ok(rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG,
325            "waveOutOpen: opening the device at 2MHz should fail %d: rc=%d",d,rc);
326         if (rc==MMSYSERR_NOERROR) {
327             trace("     got %ldx%2dx%d for %dx%2dx%d\n",
328                   format.nSamplesPerSec, format.wBitsPerSample,
329                   format.nChannels,
330                   win_formats[f][1], win_formats[f][2],
331                   win_formats[f][3]);
332             waveOutClose(wout);
333         }
334     }
335 }
336
337 static const char * wave_in_error(MMRESULT error)
338 {
339     static char msg[1024];
340     MMRESULT rc;
341
342     rc = waveInGetErrorText(error, msg, sizeof(msg));
343     if (rc != MMSYSERR_NOERROR)
344         sprintf(msg, "waveInGetErrorText(%x) failed with error %x", error, rc);
345     return msg;
346 }
347
348 static void wave_in_test_deviceIn(int device, int format, DWORD flags)
349 {
350     WAVEFORMATEX wfx;
351     HWAVEIN win;
352     HANDLE hevent;
353     WAVEHDR frag;
354     MMRESULT rc;
355
356     hevent=CreateEvent(NULL,FALSE,FALSE,NULL);
357     ok(hevent!=NULL,"CreateEvent: error=%ld\n",GetLastError());
358     if (hevent==NULL)
359         return;
360
361     wfx.wFormatTag=WAVE_FORMAT_PCM;
362     wfx.nChannels=win_formats[format][3];
363     wfx.wBitsPerSample=win_formats[format][2];
364     wfx.nSamplesPerSec=win_formats[format][1];
365     wfx.nBlockAlign=wfx.nChannels*wfx.wBitsPerSample/8;
366     wfx.nAvgBytesPerSec=wfx.nSamplesPerSec*wfx.nBlockAlign;
367     wfx.cbSize=0;
368
369     win=NULL;
370     rc=waveInOpen(&win,device,&wfx,(DWORD)hevent,0,CALLBACK_EVENT|flags);
371     /* Note: Win9x doesn't know WAVE_FORMAT_DIRECT */
372     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
373        (rc==MMSYSERR_INVALFLAG && (flags & WAVE_FORMAT_DIRECT)),
374        "waveInOpen: device=%d format=%ldx%2dx%d flags=%lx(%s) rc=%d(%s)",device,
375        wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,CALLBACK_EVENT|flags,
376        wave_open_flags(CALLBACK_EVENT|flags),rc,wave_in_error(rc));
377     if (rc!=MMSYSERR_NOERROR) {
378         CloseHandle(hevent);
379         return;
380     }
381
382     ok(wfx.nChannels==win_formats[format][3] &&
383        wfx.wBitsPerSample==win_formats[format][2] &&
384        wfx.nSamplesPerSec==win_formats[format][1],
385        "got the wrong format: %ldx%2dx%d instead of %dx%2dx%d\n",
386        wfx.nSamplesPerSec, wfx.wBitsPerSample,
387        wfx.nChannels, win_formats[format][1], win_formats[format][2],
388        win_formats[format][3]);
389
390     frag.lpData=malloc(wfx.nAvgBytesPerSec);
391     frag.dwBufferLength=wfx.nAvgBytesPerSec;
392     frag.dwFlags=0;
393     frag.dwLoops=0;
394
395     rc=waveInPrepareHeader(win, &frag, sizeof(frag));
396     ok(rc==MMSYSERR_NOERROR, "waveOutPrepareHeader: device=%d rc=%d\n",device,rc);
397
398     if (winetest_interactive && rc==MMSYSERR_NOERROR) {
399         trace("Recording at %ldx%2dx%d %04lx\n",
400               wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels,flags);
401
402         rc=waveInAddBuffer(win, &frag, sizeof(frag));
403         ok(rc==MMSYSERR_NOERROR,"waveInAddBuffer: device=%d rc=%d\n",device,rc);
404
405         rc=waveInStart(win);
406         ok(rc==MMSYSERR_NOERROR,"waveInStart: device=%d rc=%d\n",device,rc);
407         WaitForSingleObject(hevent,INFINITE);
408     }
409
410     rc=waveInUnprepareHeader(win, &frag, sizeof(frag));
411     ok(rc==MMSYSERR_NOERROR,
412        "waveInUnprepareHeader: device=%d rc=%d\n",device,rc);
413
414     free(frag.lpData);
415     CloseHandle(hevent);
416     waveInClose(win);
417 }
418
419 static void wave_in_tests()
420 {
421     WAVEINCAPS caps;
422     WAVEFORMATEX format,oformat;
423     HWAVEIN win;
424     MMRESULT rc;
425     UINT ndev,d,f;
426
427     ndev=waveInGetNumDevs();
428     trace("found %d WaveIn devices\n",ndev);
429
430     rc=waveInGetDevCapsA(ndev+1,&caps,sizeof(caps));
431     ok(rc==MMSYSERR_BADDEVICEID,
432        "waveInGetDevCapsA: MMSYSERR_BADDEVICEID expected, got %d",rc);
433
434     format.wFormatTag=WAVE_FORMAT_PCM;
435     format.nChannels=2;
436     format.wBitsPerSample=16;
437     format.nSamplesPerSec=44100;
438     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
439     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
440     format.cbSize=0;
441     rc=waveInOpen(&win,ndev+1,&format,0,0,CALLBACK_NULL);
442     ok(rc==MMSYSERR_BADDEVICEID,
443        "waveInOpen: MMSYSERR_BADDEVICEID expected, got %d",rc);
444
445     for (d=0;d<ndev;d++) {
446         rc=waveInGetDevCapsA(d,&caps,sizeof(caps));
447         ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID,
448            "waveInGetDevCapsA: failed to get capabilities of device %d: rc=%d",d,rc);
449         if (rc==MMSYSERR_BADDEVICEID)
450             continue;
451
452         trace("  %d: \"%s\" %d.%d (%d:%d): channels=%d formats=%05lx\n",
453               d,caps.szPname,caps.vDriverVersion >> 8,
454               caps.vDriverVersion & 0xff,
455               caps.wMid,caps.wPid,
456               caps.wChannels,caps.dwFormats);
457
458         for (f=0;f<NB_WIN_FORMATS;f++) {
459             if (caps.dwFormats & win_formats[f][0]) {
460                 wave_in_test_deviceIn(d,f,0);
461                 wave_in_test_deviceIn(d,f,WAVE_FORMAT_DIRECT);
462             }
463         }
464
465         /* Try an invalid format to test error handling */
466         trace("Testing invalid 2MHz format\n");
467         format.wFormatTag=WAVE_FORMAT_PCM;
468         format.nChannels=2;
469         format.wBitsPerSample=16;
470         format.nSamplesPerSec=2000000; /* 2MHz! */
471         format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
472         format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
473         format.cbSize=0;
474         oformat=format;
475         rc=waveInOpen(&win,d,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
476         ok(rc==WAVERR_BADFORMAT,
477            "waveInOpen: opening the device at 2MHz should fail %d: rc=%d",d,rc);
478         if (rc==MMSYSERR_NOERROR) {
479             trace("     got %ldx%2dx%d for %ldx%2dx%d\n",
480                   format.nSamplesPerSec, format.wBitsPerSample,
481                   format.nChannels,
482                   oformat.nSamplesPerSec, oformat.wBitsPerSample,
483                   oformat.nChannels);
484             waveInClose(win);
485         }
486
487         format.wFormatTag=WAVE_FORMAT_PCM;
488         format.nChannels=2;
489         format.wBitsPerSample=16;
490         format.nSamplesPerSec=2000000; /* 2MHz! */
491         format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
492         format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
493         format.cbSize=0;
494         rc=waveInOpen(&win,d,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
495         ok(rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG,
496            "waveInOpen: opening the device at 2MHz should fail %d: rc=%d",d,rc);
497         if (rc==MMSYSERR_NOERROR) {
498             trace("     got %ldx%2dx%d for %dx%2dx%d\n",
499                   format.nSamplesPerSec, format.wBitsPerSample,
500                   format.nChannels,
501                   win_formats[f][1], win_formats[f][2],
502                   win_formats[f][3]);
503             waveInClose(win);
504         }
505     }
506 }
507
508 START_TEST(wave)
509 {
510     wave_out_tests();
511     wave_in_tests();
512 }