An interactive test should have volume, else a rational user will
[wine/wine64.git] / dlls / winmm / tests / wave.c
blob82149216b0b926acb9980aa8efde9ffbd95918a4
1 /*
2 * Test winmm sound playback in each sound format
4 * Copyright (c) 2002 Francois Gouget
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.
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.
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
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <math.h>
26 #include "wine/test.h"
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winnls.h"
30 #include "mmsystem.h"
31 #define NOBITMAP
32 #include "mmreg.h"
33 #include "ks.h"
34 #include "ksguid.h"
35 #include "ksmedia.h"
37 #include "winmm_test.h"
40 * Note that in most of this test we may get MMSYSERR_BADDEVICEID errors
41 * at about any time if the user starts another application that uses the
42 * sound device. So we should not report these as test failures.
44 * This test can play a test tone. But this only makes sense if someone
45 * is going to carefully listen to it, and would only bother everyone else.
46 * So this is only done if the test is being run in interactive mode.
49 #define PI 3.14159265358979323846
50 static char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size)
52 int i,j;
53 int nb_samples;
54 char* buf;
55 char* b;
56 WAVEFORMATEXTENSIBLE *wfex = (WAVEFORMATEXTENSIBLE*)wfx;
58 nb_samples=(int)(duration*wfx->nSamplesPerSec);
59 *size=nb_samples*wfx->nBlockAlign;
60 b=buf=malloc(*size);
61 for (i=0;i<nb_samples;i++) {
62 double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec);
63 if (wfx->wBitsPerSample==8) {
64 unsigned char sample=(unsigned char)((double)127.5*(y+1.0));
65 for (j = 0; j < wfx->nChannels; j++)
66 *b++=sample;
67 } else if (wfx->wBitsPerSample==16) {
68 signed short sample=(signed short)((double)32767.5*y-0.5);
69 for (j = 0; j < wfx->nChannels; j++) {
70 b[0]=sample & 0xff;
71 b[1]=sample >> 8;
72 b+=2;
74 } else if (wfx->wBitsPerSample==24) {
75 signed int sample=(signed int)(((double)0x7fffff+0.5)*y-0.5);
76 for (j = 0; j < wfx->nChannels; j++) {
77 b[0]=sample & 0xff;
78 b[1]=(sample >> 8) & 0xff;
79 b[2]=(sample >> 16) & 0xff;
80 b+=3;
82 } else if ((wfx->wBitsPerSample==32) && ((wfx->wFormatTag == WAVE_FORMAT_PCM) ||
83 ((wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) &&
84 IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)))) {
85 signed int sample=(signed int)(((double)0x7fffffff+0.5)*y-0.5);
86 for (j = 0; j < wfx->nChannels; j++) {
87 b[0]=sample & 0xff;
88 b[1]=(sample >> 8) & 0xff;
89 b[2]=(sample >> 16) & 0xff;
90 b[3]=(sample >> 24) & 0xff;
91 b+=4;
93 } else if ((wfx->wBitsPerSample==32) && (wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) &&
94 IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
95 union { float f; char c[4]; } sample;
96 sample.f=(float)y;
97 for (j = 0; j < wfx->nChannels; j++) {
98 b[0]=sample.c[0];
99 b[1]=sample.c[1];
100 b[2]=sample.c[2];
101 b[3]=sample.c[3];
102 b+=4;
106 return buf;
109 static char* wave_generate_silence(WAVEFORMATEX* wfx, double duration, DWORD* size)
111 int i,j;
112 int nb_samples;
113 char* buf;
114 char* b;
115 WAVEFORMATEXTENSIBLE *wfex = (WAVEFORMATEXTENSIBLE*)wfx;
117 nb_samples=(int)(duration*wfx->nSamplesPerSec);
118 *size=nb_samples*wfx->nBlockAlign;
119 b=buf=malloc(*size);
120 for (i=0;i<nb_samples;i++) {
121 if (wfx->wBitsPerSample==8) {
122 for (j = 0; j < wfx->nChannels; j++)
123 *b++=128;
124 } else if (wfx->wBitsPerSample==16) {
125 for (j = 0; j < wfx->nChannels; j++) {
126 b[0]=0;
127 b[1]=0;
128 b+=2;
130 } else if (wfx->wBitsPerSample==24) {
131 for (j = 0; j < wfx->nChannels; j++) {
132 b[0]=0;
133 b[1]=0;
134 b[2]=0;
135 b+=3;
137 } else if ((wfx->wBitsPerSample==32) && ((wfx->wFormatTag == WAVE_FORMAT_PCM) ||
138 ((wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) &&
139 IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)))) {
140 for (j = 0; j < wfx->nChannels; j++) {
141 b[0]=0;
142 b[1]=0;
143 b[2]=0;
144 b[3]=0;
145 b+=4;
147 } else if ((wfx->wBitsPerSample==32) && (wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) &&
148 IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
149 union { float f; char c[4]; } sample;
150 sample.f=0;
151 for (j = 0; j < wfx->nChannels; j++) {
152 b[0]=sample.c[0];
153 b[1]=sample.c[1];
154 b[2]=sample.c[2];
155 b[3]=sample.c[3];
156 b+=4;
160 return buf;
163 const char * dev_name(int device)
165 static char name[16];
166 if (device == WAVE_MAPPER)
167 return "WAVE_MAPPER";
168 sprintf(name, "%d", device);
169 return name;
172 const char* mmsys_error(MMRESULT error)
174 #define ERR_TO_STR(dev) case dev: return #dev
175 static char unknown[32];
176 switch (error) {
177 ERR_TO_STR(MMSYSERR_NOERROR);
178 ERR_TO_STR(MMSYSERR_ERROR);
179 ERR_TO_STR(MMSYSERR_BADDEVICEID);
180 ERR_TO_STR(MMSYSERR_NOTENABLED);
181 ERR_TO_STR(MMSYSERR_ALLOCATED);
182 ERR_TO_STR(MMSYSERR_INVALHANDLE);
183 ERR_TO_STR(MMSYSERR_NODRIVER);
184 ERR_TO_STR(MMSYSERR_NOMEM);
185 ERR_TO_STR(MMSYSERR_NOTSUPPORTED);
186 ERR_TO_STR(MMSYSERR_BADERRNUM);
187 ERR_TO_STR(MMSYSERR_INVALFLAG);
188 ERR_TO_STR(MMSYSERR_INVALPARAM);
189 ERR_TO_STR(WAVERR_BADFORMAT);
190 ERR_TO_STR(WAVERR_STILLPLAYING);
191 ERR_TO_STR(WAVERR_UNPREPARED);
192 ERR_TO_STR(WAVERR_SYNC);
193 ERR_TO_STR(MIDIERR_UNPREPARED);
194 ERR_TO_STR(MIDIERR_STILLPLAYING);
195 ERR_TO_STR(MIDIERR_NOTREADY);
196 ERR_TO_STR(MIDIERR_NODEVICE);
197 ERR_TO_STR(MIDIERR_INVALIDSETUP);
198 ERR_TO_STR(TIMERR_NOCANDO);
199 ERR_TO_STR(TIMERR_STRUCT);
200 ERR_TO_STR(JOYERR_PARMS);
201 ERR_TO_STR(JOYERR_NOCANDO);
202 ERR_TO_STR(JOYERR_UNPLUGGED);
203 ERR_TO_STR(MIXERR_INVALLINE);
204 ERR_TO_STR(MIXERR_INVALCONTROL);
205 ERR_TO_STR(MIXERR_INVALVALUE);
206 ERR_TO_STR(MMIOERR_FILENOTFOUND);
207 ERR_TO_STR(MMIOERR_OUTOFMEMORY);
208 ERR_TO_STR(MMIOERR_CANNOTOPEN);
209 ERR_TO_STR(MMIOERR_CANNOTCLOSE);
210 ERR_TO_STR(MMIOERR_CANNOTREAD);
211 ERR_TO_STR(MMIOERR_CANNOTWRITE);
212 ERR_TO_STR(MMIOERR_CANNOTSEEK);
213 ERR_TO_STR(MMIOERR_CANNOTEXPAND);
214 ERR_TO_STR(MMIOERR_CHUNKNOTFOUND);
215 ERR_TO_STR(MMIOERR_UNBUFFERED);
217 sprintf(unknown, "Unknown(0x%08x)", error);
218 return unknown;
219 #undef ERR_TO_STR
222 const char* wave_out_error(MMRESULT error)
224 static char msg[1024];
225 static char long_msg[1100];
226 MMRESULT rc;
228 rc = waveOutGetErrorText(error, msg, sizeof(msg));
229 if (rc != MMSYSERR_NOERROR)
230 sprintf(long_msg, "waveOutGetErrorText(%x) failed with error %x",
231 error, rc);
232 else
233 sprintf(long_msg, "%s(%s)", mmsys_error(error), msg);
234 return long_msg;
237 const char * wave_open_flags(DWORD flags)
239 static char msg[1024];
240 int first = TRUE;
241 msg[0] = 0;
242 if ((flags & CALLBACK_TYPEMASK) == CALLBACK_EVENT) {
243 strcat(msg, "CALLBACK_EVENT");
244 first = FALSE;
246 if ((flags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION) {
247 if (!first) strcat(msg, "|");
248 strcat(msg, "CALLBACK_FUNCTION");
249 first = FALSE;
251 if ((flags & CALLBACK_TYPEMASK) == CALLBACK_NULL) {
252 if (!first) strcat(msg, "|");
253 strcat(msg, "CALLBACK_NULL");
254 first = FALSE;
256 if ((flags & CALLBACK_TYPEMASK) == CALLBACK_THREAD) {
257 if (!first) strcat(msg, "|");
258 strcat(msg, "CALLBACK_THREAD");
259 first = FALSE;
261 if ((flags & CALLBACK_TYPEMASK) == CALLBACK_WINDOW) {
262 if (!first) strcat(msg, "|");
263 strcat(msg, "CALLBACK_WINDOW");
264 first = FALSE;
266 if ((flags & WAVE_ALLOWSYNC) == WAVE_ALLOWSYNC) {
267 if (!first) strcat(msg, "|");
268 strcat(msg, "WAVE_ALLOWSYNC");
269 first = FALSE;
271 if ((flags & WAVE_FORMAT_DIRECT) == WAVE_FORMAT_DIRECT) {
272 if (!first) strcat(msg, "|");
273 strcat(msg, "WAVE_FORMAT_DIRECT");
274 first = FALSE;
276 if ((flags & WAVE_FORMAT_QUERY) == WAVE_FORMAT_QUERY) {
277 if (!first) strcat(msg, "|");
278 strcat(msg, "WAVE_FORMAT_QUERY");
279 first = FALSE;
281 if ((flags & WAVE_MAPPED) == WAVE_MAPPED) {
282 if (!first) strcat(msg, "|");
283 strcat(msg, "WAVE_MAPPED");
284 first = FALSE;
286 return msg;
289 static const char * wave_out_caps(DWORD dwSupport)
291 #define ADD_FLAG(f) if (dwSupport & f) strcat(msg, " " #f)
292 static char msg[256];
293 msg[0] = 0;
295 ADD_FLAG(WAVECAPS_PITCH);
296 ADD_FLAG(WAVECAPS_PLAYBACKRATE);
297 ADD_FLAG(WAVECAPS_VOLUME);
298 ADD_FLAG(WAVECAPS_LRVOLUME);
299 ADD_FLAG(WAVECAPS_SYNC);
300 ADD_FLAG(WAVECAPS_SAMPLEACCURATE);
302 return msg[0] ? msg + 1 : "";
303 #undef ADD_FLAG
306 static const char * wave_time_format(UINT type)
308 static char msg[32];
309 #define TIME_FORMAT(f) case f: return #f
310 switch (type) {
311 TIME_FORMAT(TIME_MS);
312 TIME_FORMAT(TIME_SAMPLES);
313 TIME_FORMAT(TIME_BYTES);
314 TIME_FORMAT(TIME_SMPTE);
315 TIME_FORMAT(TIME_MIDI);
316 TIME_FORMAT(TIME_TICKS);
318 #undef TIME_FORMAT
319 sprintf(msg, "Unknown(0x%04x)", type);
320 return msg;
323 const char * get_format_str(WORD format)
325 static char msg[32];
326 #define WAVE_FORMAT(f) case f: return #f
327 switch (format) {
328 WAVE_FORMAT(WAVE_FORMAT_PCM);
329 WAVE_FORMAT(WAVE_FORMAT_ADPCM);
330 WAVE_FORMAT(WAVE_FORMAT_IBM_CVSD);
331 WAVE_FORMAT(WAVE_FORMAT_ALAW);
332 WAVE_FORMAT(WAVE_FORMAT_MULAW);
333 WAVE_FORMAT(WAVE_FORMAT_OKI_ADPCM);
334 WAVE_FORMAT(WAVE_FORMAT_IMA_ADPCM);
335 WAVE_FORMAT(WAVE_FORMAT_MEDIASPACE_ADPCM);
336 WAVE_FORMAT(WAVE_FORMAT_SIERRA_ADPCM);
337 WAVE_FORMAT(WAVE_FORMAT_G723_ADPCM);
338 WAVE_FORMAT(WAVE_FORMAT_DIGISTD);
339 WAVE_FORMAT(WAVE_FORMAT_DIGIFIX);
340 WAVE_FORMAT(WAVE_FORMAT_DIALOGIC_OKI_ADPCM);
341 WAVE_FORMAT(WAVE_FORMAT_YAMAHA_ADPCM);
342 WAVE_FORMAT(WAVE_FORMAT_SONARC);
343 WAVE_FORMAT(WAVE_FORMAT_DSPGROUP_TRUESPEECH);
344 WAVE_FORMAT(WAVE_FORMAT_ECHOSC1);
345 WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF36);
346 WAVE_FORMAT(WAVE_FORMAT_APTX);
347 WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF10);
348 WAVE_FORMAT(WAVE_FORMAT_DOLBY_AC2);
349 WAVE_FORMAT(WAVE_FORMAT_GSM610);
350 WAVE_FORMAT(WAVE_FORMAT_ANTEX_ADPCME);
351 WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_VQLPC);
352 WAVE_FORMAT(WAVE_FORMAT_DIGIREAL);
353 WAVE_FORMAT(WAVE_FORMAT_DIGIADPCM);
354 WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_CR10);
355 WAVE_FORMAT(WAVE_FORMAT_NMS_VBXADPCM);
356 WAVE_FORMAT(WAVE_FORMAT_G721_ADPCM);
357 WAVE_FORMAT(WAVE_FORMAT_MPEG);
358 WAVE_FORMAT(WAVE_FORMAT_MPEGLAYER3);
359 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_ADPCM);
360 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH8);
361 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH10);
362 WAVE_FORMAT(WAVE_FORMAT_FM_TOWNS_SND);
363 WAVE_FORMAT(WAVE_FORMAT_OLIGSM);
364 WAVE_FORMAT(WAVE_FORMAT_OLIADPCM);
365 WAVE_FORMAT(WAVE_FORMAT_OLICELP);
366 WAVE_FORMAT(WAVE_FORMAT_OLISBC);
367 WAVE_FORMAT(WAVE_FORMAT_OLIOPR);
368 WAVE_FORMAT(WAVE_FORMAT_DEVELOPMENT);
369 WAVE_FORMAT(WAVE_FORMAT_EXTENSIBLE);
371 #undef WAVE_FORMAT
372 sprintf(msg, "Unknown(0x%04x)", format);
373 return msg;
376 static void check_position(int device, HWAVEOUT wout, DWORD bytes,
377 LPWAVEFORMATEX pwfx )
379 MMTIME mmtime;
380 DWORD samples;
381 double duration;
382 MMRESULT rc;
384 samples=bytes/(pwfx->wBitsPerSample/8*pwfx->nChannels);
385 duration=((double)samples)/pwfx->nSamplesPerSec;
387 mmtime.wType = TIME_BYTES;
388 rc=waveOutGetPosition(wout, &mmtime, sizeof(mmtime));
389 ok(rc==MMSYSERR_NOERROR,
390 "waveOutGetPosition(%s): rc=%s\n",dev_name(device),wave_out_error(rc));
391 if (mmtime.wType == TIME_BYTES)
392 ok(mmtime.u.cb==bytes,
393 "waveOutGetPosition(%s): returned %ld bytes, should be %ld\n",
394 dev_name(device),mmtime.u.cb, bytes);
395 else
396 trace("waveOutGetPosition(%s): TIME_BYTES not supported, returned %s\n",
397 dev_name(device),wave_time_format(mmtime.wType));
399 mmtime.wType = TIME_SAMPLES;
400 rc=waveOutGetPosition(wout, &mmtime, sizeof(mmtime));
401 ok(rc==MMSYSERR_NOERROR,
402 "waveOutGetPosition(%s): rc=%s\n",dev_name(device),wave_out_error(rc));
403 if (mmtime.wType == TIME_SAMPLES)
404 ok(mmtime.u.sample==samples,
405 "waveOutGetPosition(%s): returned %ld samples, should be %ld\n",
406 dev_name(device), mmtime.u.sample, samples);
407 else
408 trace("waveOutGetPosition(%s): TIME_SAMPLES not supported, "
409 "returned %s\n",dev_name(device),wave_time_format(mmtime.wType));
411 mmtime.wType = TIME_MS;
412 rc=waveOutGetPosition(wout, &mmtime, sizeof(mmtime));
413 ok(rc==MMSYSERR_NOERROR,
414 "waveOutGetPosition(%s): rc=%s\n",dev_name(device),wave_out_error(rc));
415 if (mmtime.wType == TIME_MS)
416 ok(mmtime.u.ms==floor(duration*1000.0),
417 "waveOutGetPosition(%s): returned %ld ms, should be %ld\n",
418 dev_name(device), mmtime.u.ms, (long)floor(duration*1000.0));
419 else
420 trace("waveOutGetPosition(%s): TIME_MS not supported, returned %s\n",
421 dev_name(device),wave_time_format(mmtime.wType));
423 mmtime.wType = TIME_SMPTE;
424 rc=waveOutGetPosition(wout, &mmtime, sizeof(mmtime));
425 ok(rc==MMSYSERR_NOERROR,
426 "waveOutGetPosition(%s): rc=%s\n",dev_name(device),wave_out_error(rc));
427 if (mmtime.wType == TIME_SMPTE)
429 BYTE frames=(BYTE)ceil(fmod(duration*mmtime.u.smpte.fps, mmtime.u.smpte.fps));
430 ok(mmtime.u.smpte.hour==(BYTE)(floor(duration/(60*60))) &&
431 mmtime.u.smpte.min==(BYTE)(fmod(floor(duration/60), 60)) &&
432 mmtime.u.smpte.sec==(BYTE)(fmod(duration,60)) &&
433 mmtime.u.smpte.frame==frames,
434 "waveOutGetPosition(%s): returned %d:%d:%d %d, "
435 "should be %d:%d:%d %d\n", dev_name(device), mmtime.u.smpte.hour,
436 mmtime.u.smpte.min, mmtime.u.smpte.sec, mmtime.u.smpte.frame,
437 (BYTE)(floor(duration/(60*60))),
438 (BYTE)(fmod(floor(duration/60), 60)),
439 (BYTE)(fmod(duration,60)),
440 frames);
442 else
443 trace("waveOutGetPosition(%s): TIME_SMPTE not supported, returned %s\n",
444 dev_name(device),wave_time_format(mmtime.wType));
447 static void wave_out_test_deviceOut(int device, double duration,
448 LPWAVEFORMATEX pwfx, DWORD format,
449 DWORD flags, LPWAVEOUTCAPS pcaps,
450 BOOL interactive, BOOL sine)
452 HWAVEOUT wout;
453 HANDLE hevent;
454 WAVEHDR frag;
455 MMRESULT rc;
456 DWORD volume;
457 WORD nChannels = pwfx->nChannels;
458 WORD wBitsPerSample = pwfx->wBitsPerSample;
459 DWORD nSamplesPerSec = pwfx->nSamplesPerSec;
461 hevent=CreateEvent(NULL,FALSE,FALSE,NULL);
462 ok(hevent!=NULL,"CreateEvent(): error=%ld\n",GetLastError());
463 if (hevent==NULL)
464 return;
466 wout=NULL;
467 rc=waveOutOpen(&wout,device,pwfx,(DWORD)hevent,0,CALLBACK_EVENT|flags);
468 /* Note: Win9x doesn't know WAVE_FORMAT_DIRECT */
469 /* It is acceptable to fail on formats that are not specified to work */
470 ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
471 rc==MMSYSERR_NOTENABLED || rc==MMSYSERR_NODRIVER ||
472 rc==MMSYSERR_ALLOCATED ||
473 ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
474 (flags & WAVE_FORMAT_DIRECT) && !(pcaps->dwFormats & format)) ||
475 ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
476 (!(flags & WAVE_FORMAT_DIRECT) || (flags & WAVE_MAPPED)) &&
477 !(pcaps->dwFormats & format)) ||
478 (rc==MMSYSERR_INVALFLAG && (flags & WAVE_FORMAT_DIRECT)),
479 "waveOutOpen(%s): format=%ldx%2dx%d flags=%lx(%s) rc=%s\n",
480 dev_name(device),pwfx->nSamplesPerSec,pwfx->wBitsPerSample,
481 pwfx->nChannels,CALLBACK_EVENT|flags,
482 wave_open_flags(CALLBACK_EVENT|flags),wave_out_error(rc));
483 if ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
484 (flags & WAVE_FORMAT_DIRECT) && (pcaps->dwFormats & format))
485 trace(" Reason: The device lists this format as supported in it's "
486 "capabilities but opening it failed.\n");
487 if ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
488 !(pcaps->dwFormats & format))
489 trace("waveOutOpen(%s): format=%ldx%2dx%d %s rc=%s failed but format "
490 "not supported so OK.\n", dev_name(device), pwfx->nSamplesPerSec,
491 pwfx->wBitsPerSample,pwfx->nChannels,
492 flags & WAVE_FORMAT_DIRECT ? "flags=WAVE_FORMAT_DIRECT" :
493 flags & WAVE_MAPPED ? "flags=WAVE_MAPPED" : "", mmsys_error(rc));
494 if (rc!=MMSYSERR_NOERROR) {
495 CloseHandle(hevent);
496 return;
499 ok(pwfx->nChannels==nChannels &&
500 pwfx->wBitsPerSample==wBitsPerSample &&
501 pwfx->nSamplesPerSec==nSamplesPerSec,
502 "got the wrong format: %ldx%2dx%d instead of %ldx%2dx%d\n",
503 pwfx->nSamplesPerSec, pwfx->wBitsPerSample,
504 pwfx->nChannels, nSamplesPerSec, wBitsPerSample, nChannels);
506 if (sine)
507 frag.lpData=wave_generate_la(pwfx,duration,&frag.dwBufferLength);
508 else
509 frag.lpData=wave_generate_silence(pwfx,duration,&frag.dwBufferLength);
511 frag.dwFlags=0;
512 frag.dwLoops=0;
514 rc=waveOutGetVolume(wout,&volume);
515 ok(rc==MMSYSERR_NOERROR,"waveOutGetVolume(%s): rc=%s\n",
516 dev_name(device),wave_out_error(rc));
518 rc=waveOutPrepareHeader(wout, &frag, sizeof(frag));
519 ok(rc==MMSYSERR_NOERROR,
520 "waveOutPrepareHeader(%s): rc=%s\n",dev_name(device),wave_out_error(rc));
522 if (interactive && rc==MMSYSERR_NOERROR) {
523 DWORD start,end;
524 trace("Playing %g second %s at %5ldx%2dx%d %s %s\n",duration,
525 sine ? "440Hz tone" : "silence",pwfx->nSamplesPerSec,
526 pwfx->wBitsPerSample,pwfx->nChannels,
527 get_format_str(pwfx->wFormatTag),
528 flags & WAVE_FORMAT_DIRECT ? "WAVE_FORMAT_DIRECT" :
529 flags & WAVE_MAPPED ? "WAVE_MAPPED" : "");
531 /* Check that the position is 0 at start */
532 check_position(device, wout, 0, pwfx);
534 rc=waveOutSetVolume(wout,0x20002000);
535 ok(rc==MMSYSERR_NOERROR,"waveOutSetVolume(%s): rc=%s\n",
536 dev_name(device),wave_out_error(rc));
537 WaitForSingleObject(hevent,INFINITE);
539 rc=waveOutSetVolume(wout,volume);
540 ok(rc==MMSYSERR_NOERROR,"waveOutSetVolume(%s): rc=%s\n",
541 dev_name(device),wave_out_error(rc));
543 start=GetTickCount();
544 rc=waveOutWrite(wout, &frag, sizeof(frag));
545 ok(rc==MMSYSERR_NOERROR,"waveOutWrite(%s): rc=%s\n",
546 dev_name(device),wave_out_error(rc));
547 WaitForSingleObject(hevent,INFINITE);
549 /* Check the sound duration was within 10% of the expected value */
550 end=GetTickCount();
551 if (winetest_debug > 1)
552 trace("sound duration=%ld\n",end-start);
553 ok(fabs(1000*duration-end+start)<=100*duration,
554 "The sound played for %ld ms instead of %g ms\n",
555 end-start,1000*duration);
557 check_position(device, wout, frag.dwBufferLength, pwfx);
560 rc=waveOutUnprepareHeader(wout, &frag, sizeof(frag));
561 ok(rc==MMSYSERR_NOERROR,
562 "waveOutUnprepareHeader(%s): rc=%s\n",dev_name(device),
563 wave_out_error(rc));
564 free(frag.lpData);
566 CloseHandle(hevent);
567 rc=waveOutClose(wout);
568 ok(rc==MMSYSERR_NOERROR,"waveOutClose(%s): rc=%s\n",dev_name(device),
569 wave_out_error(rc));
572 static void wave_out_test_device(int device)
574 WAVEOUTCAPSA capsA;
575 WAVEOUTCAPSW capsW;
576 WAVEFORMATEX format, oformat;
577 WAVEFORMATEXTENSIBLE wfex;
578 HWAVEOUT wout;
579 MMRESULT rc;
580 UINT f;
581 WCHAR * nameW;
582 CHAR * nameA;
583 DWORD size;
584 DWORD dwPageSize;
585 BYTE * twoPages;
586 SYSTEM_INFO sSysInfo;
587 DWORD flOldProtect;
588 BOOL res;
590 GetSystemInfo(&sSysInfo);
591 dwPageSize = sSysInfo.dwPageSize;
593 rc=waveOutGetDevCapsA(device,&capsA,sizeof(capsA));
594 ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
595 rc==MMSYSERR_NODRIVER,
596 "waveOutGetDevCapsA(%s): failed to get capabilities: rc=%s\n",
597 dev_name(device),wave_out_error(rc));
598 if (rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER)
599 return;
601 rc=waveOutGetDevCapsW(device,&capsW,sizeof(capsW));
602 ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED,
603 "waveOutGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NOTSUPPORTED "
604 "expected, got %s\n",dev_name(device),wave_out_error(rc));
606 rc=waveOutGetDevCapsA(device,0,sizeof(capsA));
607 ok(rc==MMSYSERR_INVALPARAM,
608 "waveOutGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, "
609 "got %s\n",dev_name(device),wave_out_error(rc));
611 rc=waveOutGetDevCapsW(device,0,sizeof(capsW));
612 ok(rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED,
613 "waveOutGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED "
614 "expected, got %s\n",dev_name(device),wave_out_error(rc));
616 #if 0 /* FIXME: this works on windows but crashes wine */
617 rc=waveOutGetDevCapsA(device,(LPWAVEOUTCAPSA)1,sizeof(capsA));
618 ok(rc==MMSYSERR_INVALPARAM,
619 "waveOutGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, got %s\n",
620 dev_name(device),wave_out_error(rc));
622 rc=waveOutGetDevCapsW(device,(LPWAVEOUTCAPSW)1,sizeof(capsW));
623 ok(rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED,
624 "waveOutGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED "
625 "expected, got %s\n",dev_name(device),wave_out_error(rc));
626 #endif
628 rc=waveOutGetDevCapsA(device,&capsA,4);
629 ok(rc==MMSYSERR_NOERROR,
630 "waveOutGetDevCapsA(%s): MMSYSERR_NOERROR expected, got %s\n",
631 dev_name(device),wave_out_error(rc));
633 rc=waveOutGetDevCapsW(device,&capsW,4);
634 ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED,
635 "waveOutGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NOTSUPPORTED "
636 "expected, got %s\n",dev_name(device),wave_out_error(rc));
638 nameA=NULL;
639 rc=waveOutMessage((HWAVEOUT)device, DRV_QUERYDEVICEINTERFACESIZE,
640 (DWORD_PTR)&size, 0);
641 ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_INVALPARAM ||
642 rc==MMSYSERR_NOTSUPPORTED,
643 "waveOutMessage(%s): failed to get interface size, rc=%s\n",
644 dev_name(device),wave_out_error(rc));
645 if (rc==MMSYSERR_NOERROR) {
646 nameW = (WCHAR *)malloc(size);
647 rc=waveOutMessage((HWAVEOUT)device, DRV_QUERYDEVICEINTERFACE,
648 (DWORD_PTR)nameW, size);
649 ok(rc==MMSYSERR_NOERROR,"waveOutMessage(%s): failed to get interface "
650 "name, rc=%s\n",dev_name(device),wave_out_error(rc));
651 ok(lstrlenW(nameW)+1==size/sizeof(WCHAR),"got an incorrect size: "
652 "%ld instead of %d\n",size,(lstrlenW(nameW)+1)*sizeof(WCHAR));
653 if (rc==MMSYSERR_NOERROR) {
654 nameA = malloc(size/sizeof(WCHAR));
655 WideCharToMultiByte(CP_ACP, 0, nameW, size/sizeof(WCHAR), nameA,
656 size/sizeof(WCHAR), NULL, NULL);
658 free(nameW);
660 else if (rc==MMSYSERR_NOTSUPPORTED) {
661 nameA=strdup("not supported");
664 trace(" %s: \"%s\" (%s) %d.%d (%d:%d)\n",dev_name(device),capsA.szPname,
665 (nameA?nameA:"failed"),capsA.vDriverVersion >> 8,
666 capsA.vDriverVersion & 0xff, capsA.wMid,capsA.wPid);
667 trace(" channels=%d formats=%05lx support=%04lx\n",
668 capsA.wChannels,capsA.dwFormats,capsA.dwSupport);
669 trace(" %s\n",wave_out_caps(capsA.dwSupport));
670 free(nameA);
672 if (winetest_interactive && (device != WAVE_MAPPER))
674 trace("Playing a 5 seconds reference tone.\n");
675 trace("All subsequent tones should be identical to this one.\n");
676 trace("Listen for stutter, changes in pitch, volume, etc.\n");
677 format.wFormatTag=WAVE_FORMAT_PCM;
678 format.nChannels=1;
679 format.wBitsPerSample=8;
680 format.nSamplesPerSec=22050;
681 format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
682 format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
683 format.cbSize=0;
684 wave_out_test_deviceOut(device,5.0,&format,WAVE_FORMAT_2M08,0,&capsA,
685 TRUE,TRUE);
686 } else {
687 format.wFormatTag=WAVE_FORMAT_PCM;
688 format.nChannels=1;
689 format.wBitsPerSample=8;
690 format.nSamplesPerSec=22050;
691 format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
692 format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
693 format.cbSize=0;
694 wave_out_test_deviceOut(device,1.0,&format,WAVE_FORMAT_2M08,0,&capsA,
695 TRUE,FALSE);
698 for (f=0;f<NB_WIN_FORMATS;f++) {
699 format.wFormatTag=WAVE_FORMAT_PCM;
700 format.nChannels=win_formats[f][3];
701 format.wBitsPerSample=win_formats[f][2];
702 format.nSamplesPerSec=win_formats[f][1];
703 format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
704 format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
705 format.cbSize=0;
706 wave_out_test_deviceOut(device,1.0,&format,win_formats[f][0],
707 0,&capsA,winetest_interactive,TRUE);
708 if (device != WAVE_MAPPER)
710 wave_out_test_deviceOut(device,1.0,&format,win_formats[f][0],
711 WAVE_FORMAT_DIRECT,&capsA,winetest_interactive,
712 TRUE);
713 wave_out_test_deviceOut(device,1.0,&format,win_formats[f][0],
714 WAVE_MAPPED,&capsA,winetest_interactive,
715 TRUE);
719 /* Try a PCMWAVEFORMAT aligned next to an unaccessible page for bounds
720 * checking */
721 twoPages = VirtualAlloc(NULL, 2 * dwPageSize, MEM_RESERVE | MEM_COMMIT,
722 PAGE_READWRITE);
723 ok(twoPages!=NULL,"Failed to allocate 2 pages of memory\n");
724 if (twoPages) {
725 res = VirtualProtect(twoPages + dwPageSize, dwPageSize, PAGE_NOACCESS,
726 &flOldProtect);
727 ok(res, "Failed to set memory access on second page\n");
728 if (res) {
729 LPWAVEFORMATEX pwfx = (LPWAVEFORMATEX)(twoPages + dwPageSize -
730 sizeof(PCMWAVEFORMAT));
731 pwfx->wFormatTag=WAVE_FORMAT_PCM;
732 pwfx->nChannels=1;
733 pwfx->wBitsPerSample=8;
734 pwfx->nSamplesPerSec=22050;
735 pwfx->nBlockAlign=pwfx->nChannels*pwfx->wBitsPerSample/8;
736 pwfx->nAvgBytesPerSec=pwfx->nSamplesPerSec*pwfx->nBlockAlign;
737 wave_out_test_deviceOut(device,1.0,pwfx,WAVE_FORMAT_2M08,0,
738 &capsA,winetest_interactive,TRUE);
739 if (device != WAVE_MAPPER)
741 wave_out_test_deviceOut(device,1.0,pwfx,WAVE_FORMAT_2M08,
742 WAVE_FORMAT_DIRECT,&capsA,
743 winetest_interactive,TRUE);
744 wave_out_test_deviceOut(device,1.0,pwfx,WAVE_FORMAT_2M08,
745 WAVE_MAPPED,&capsA,winetest_interactive,
746 TRUE);
749 VirtualFree(twoPages, 2 * dwPageSize, MEM_RELEASE);
752 /* Testing invalid format: 11 bits per sample */
753 format.wFormatTag=WAVE_FORMAT_PCM;
754 format.nChannels=2;
755 format.wBitsPerSample=11;
756 format.nSamplesPerSec=22050;
757 format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
758 format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
759 format.cbSize=0;
760 oformat=format;
761 rc=waveOutOpen(&wout,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
762 ok(rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG ||
763 rc==MMSYSERR_INVALPARAM,
764 "waveOutOpen(%s): opening the device in 11 bits mode should fail: "
765 "rc=%s\n",dev_name(device),wave_out_error(rc));
766 if (rc==MMSYSERR_NOERROR) {
767 trace(" got %ldx%2dx%d for %ldx%2dx%d\n",
768 format.nSamplesPerSec, format.wBitsPerSample,
769 format.nChannels,
770 oformat.nSamplesPerSec, oformat.wBitsPerSample,
771 oformat.nChannels);
772 waveOutClose(wout);
775 /* Testing invalid format: 2 MHz sample rate */
776 format.wFormatTag=WAVE_FORMAT_PCM;
777 format.nChannels=2;
778 format.wBitsPerSample=16;
779 format.nSamplesPerSec=2000000;
780 format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
781 format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
782 format.cbSize=0;
783 oformat=format;
784 rc=waveOutOpen(&wout,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
785 ok(rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG ||
786 rc==MMSYSERR_INVALPARAM,
787 "waveOutOpen(%s): opening the device at 2 MHz sample rate should fail: "
788 "rc=%s\n",dev_name(device),wave_out_error(rc));
789 if (rc==MMSYSERR_NOERROR) {
790 trace(" got %ldx%2dx%d for %ldx%2dx%d\n",
791 format.nSamplesPerSec, format.wBitsPerSample,
792 format.nChannels,
793 oformat.nSamplesPerSec, oformat.wBitsPerSample,
794 oformat.nChannels);
795 waveOutClose(wout);
798 /* try some non PCM formats */
799 format.wFormatTag=WAVE_FORMAT_MULAW;
800 format.nChannels=1;
801 format.wBitsPerSample=8;
802 format.nSamplesPerSec=8000;
803 format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
804 format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
805 format.cbSize=0;
806 oformat=format;
807 rc=waveOutOpen(&wout,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
808 ok(rc==MMSYSERR_NOERROR ||rc==WAVERR_BADFORMAT ||
809 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
810 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc));
811 if (rc==MMSYSERR_NOERROR) {
812 waveOutClose(wout);
813 wave_out_test_deviceOut(device,1.0,&format,0,0,
814 &capsA,winetest_interactive,TRUE);
815 } else
816 trace("waveOutOpen(%s): WAVE_FORMAT_MULAW not supported\n",
817 dev_name(device));
819 format.wFormatTag=WAVE_FORMAT_ADPCM;
820 format.nChannels=2;
821 format.wBitsPerSample=4;
822 format.nSamplesPerSec=22050;
823 format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
824 format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
825 format.cbSize=0;
826 oformat=format;
827 rc=waveOutOpen(&wout,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
828 ok(rc==MMSYSERR_NOERROR ||rc==WAVERR_BADFORMAT ||
829 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
830 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc));
831 if (rc==MMSYSERR_NOERROR) {
832 waveOutClose(wout);
833 wave_out_test_deviceOut(device,1.0,&format,0,0,
834 &capsA,winetest_interactive,TRUE);
835 } else
836 trace("waveOutOpen(%s): WAVE_FORMAT_ADPCM not supported\n",
837 dev_name(device));
839 /* test if WAVEFORMATEXTENSIBLE supported */
840 wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
841 wfex.Format.nChannels=2;
842 wfex.Format.wBitsPerSample=16;
843 wfex.Format.nSamplesPerSec=22050;
844 wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
845 wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
846 wfex.Format.nBlockAlign;
847 wfex.Format.cbSize=22;
848 wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
849 wfex.dwChannelMask=SPEAKER_ALL;
850 wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
851 rc=waveOutOpen(&wout,device,&wfex.Format,0,0,
852 CALLBACK_NULL|WAVE_FORMAT_DIRECT);
853 ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
854 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
855 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc));
856 if (rc==MMSYSERR_NOERROR) {
857 waveOutClose(wout);
858 wave_out_test_deviceOut(device,1.0,&wfex.Format,WAVE_FORMAT_2M16,0,
859 &capsA,winetest_interactive,TRUE);
860 } else
861 trace("waveOutOpen(%s): WAVE_FORMAT_EXTENSIBLE not supported\n",
862 dev_name(device));
864 /* test if 4 channels supported */
865 wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
866 wfex.Format.nChannels=4;
867 wfex.Format.wBitsPerSample=16;
868 wfex.Format.nSamplesPerSec=22050;
869 wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
870 wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
871 wfex.Format.nBlockAlign;
872 wfex.Format.cbSize=22;
873 wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
874 wfex.dwChannelMask=SPEAKER_ALL;
875 wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
876 rc=waveOutOpen(&wout,device,&wfex.Format,0,0,
877 CALLBACK_NULL|WAVE_FORMAT_DIRECT);
878 ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
879 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
880 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc));
881 if (rc==MMSYSERR_NOERROR) {
882 waveOutClose(wout);
883 wave_out_test_deviceOut(device,1.0,&wfex.Format,0,0,
884 &capsA,winetest_interactive,TRUE);
885 } else
886 trace("waveOutOpen(%s): 4 channels not supported\n",
887 dev_name(device));
889 /* test if 6 channels supported */
890 wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
891 wfex.Format.nChannels=6;
892 wfex.Format.wBitsPerSample=16;
893 wfex.Format.nSamplesPerSec=22050;
894 wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
895 wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
896 wfex.Format.nBlockAlign;
897 wfex.Format.cbSize=22;
898 wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
899 wfex.dwChannelMask=SPEAKER_ALL;
900 wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
901 rc=waveOutOpen(&wout,device,&wfex.Format,0,0,
902 CALLBACK_NULL|WAVE_FORMAT_DIRECT);
903 ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
904 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
905 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc));
906 if (rc==MMSYSERR_NOERROR) {
907 waveOutClose(wout);
908 wave_out_test_deviceOut(device,1.0,&wfex.Format,WAVE_FORMAT_2M16,0,
909 &capsA,winetest_interactive,TRUE);
910 } else
911 trace("waveOutOpen(%s): 6 channels not supported\n",
912 dev_name(device));
914 #if 0 /* ALSA doesn't like this format */
915 /* test if 24 bit samples supported */
916 wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
917 wfex.Format.nChannels=2;
918 wfex.Format.wBitsPerSample=24;
919 wfex.Format.nSamplesPerSec=22050;
920 wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
921 wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
922 wfex.Format.nBlockAlign;
923 wfex.Format.cbSize=22;
924 wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
925 wfex.dwChannelMask=SPEAKER_ALL;
926 wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
927 rc=waveOutOpen(&wout,device,&wfex.Format,0,0,
928 CALLBACK_NULL|WAVE_FORMAT_DIRECT);
929 ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
930 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
931 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc));
932 if (rc==MMSYSERR_NOERROR) {
933 waveOutClose(wout);
934 wave_out_test_deviceOut(device,1.0,&wfex.Format,WAVE_FORMAT_2M16,0,
935 &capsA,winetest_interactive,TRUE);
936 } else
937 trace("waveOutOpen(%s): 24 bit samples not supported\n",
938 dev_name(device));
939 #endif
941 /* test if 32 bit samples supported */
942 wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
943 wfex.Format.nChannels=2;
944 wfex.Format.wBitsPerSample=32;
945 wfex.Format.nSamplesPerSec=22050;
946 wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
947 wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
948 wfex.Format.nBlockAlign;
949 wfex.Format.cbSize=22;
950 wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
951 wfex.dwChannelMask=SPEAKER_ALL;
952 wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
953 rc=waveOutOpen(&wout,device,&wfex.Format,0,0,
954 CALLBACK_NULL|WAVE_FORMAT_DIRECT);
955 ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
956 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
957 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc));
958 if (rc==MMSYSERR_NOERROR) {
959 waveOutClose(wout);
960 wave_out_test_deviceOut(device,1.0,&wfex.Format,WAVE_FORMAT_2M16,0,
961 &capsA,winetest_interactive,TRUE);
962 } else
963 trace("waveOutOpen(%s): 32 bit samples not supported\n",
964 dev_name(device));
966 /* test if 32 bit float samples supported */
967 wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
968 wfex.Format.nChannels=2;
969 wfex.Format.wBitsPerSample=32;
970 wfex.Format.nSamplesPerSec=22050;
971 wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
972 wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
973 wfex.Format.nBlockAlign;
974 wfex.Format.cbSize=22;
975 wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
976 wfex.dwChannelMask=SPEAKER_ALL;
977 wfex.SubFormat=KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
978 rc=waveOutOpen(&wout,device,&wfex.Format,0,0,
979 CALLBACK_NULL|WAVE_FORMAT_DIRECT);
980 ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
981 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
982 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc));
983 if (rc==MMSYSERR_NOERROR) {
984 waveOutClose(wout);
985 wave_out_test_deviceOut(device,1.0,&wfex.Format,WAVE_FORMAT_2M16,0,
986 &capsA,winetest_interactive,TRUE);
987 } else
988 trace("waveOutOpen(%s): 32 bit float samples not supported\n",
989 dev_name(device));
992 static void wave_out_tests()
994 WAVEOUTCAPSA capsA;
995 WAVEOUTCAPSW capsW;
996 WAVEFORMATEX format;
997 HWAVEOUT wout;
998 MMRESULT rc;
999 UINT ndev,d;
1001 ndev=waveOutGetNumDevs();
1002 trace("found %d WaveOut devices\n",ndev);
1004 rc=waveOutGetDevCapsA(ndev+1,&capsA,sizeof(capsA));
1005 ok(rc==MMSYSERR_BADDEVICEID,
1006 "waveOutGetDevCapsA(%s): MMSYSERR_BADDEVICEID expected, got %s\n",
1007 dev_name(ndev+1),mmsys_error(rc));
1009 rc=waveOutGetDevCapsW(ndev+1,&capsW,sizeof(capsW));
1010 ok(rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NOTSUPPORTED,
1011 "waveOutGetDevCapsW(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NOTSUPPORTED "
1012 "expected, got %s\n",dev_name(ndev+1),mmsys_error(rc));
1014 rc=waveOutGetDevCapsA(WAVE_MAPPER,&capsA,sizeof(capsA));
1015 if (ndev>0)
1016 ok(rc==MMSYSERR_NOERROR,
1017 "waveOutGetDevCapsA(%s): MMSYSERR_NOERROR expected, got %s\n",
1018 dev_name(WAVE_MAPPER),mmsys_error(rc));
1019 else
1020 ok(rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER,
1021 "waveOutGetDevCapsA(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NODRIVER "
1022 "expected, got %s\n",dev_name(WAVE_MAPPER),mmsys_error(rc));
1024 rc=waveOutGetDevCapsW(WAVE_MAPPER,&capsW,sizeof(capsW));
1025 if (ndev>0)
1026 ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED,
1027 "waveOutGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NOTSUPPORTED "
1028 "expected, got %s\n",dev_name(WAVE_MAPPER),mmsys_error(rc));
1029 else
1030 ok(rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER ||
1031 rc==MMSYSERR_NOTSUPPORTED,
1032 "waveOutGetDevCapsW(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NODRIVER "
1033 " or MMSYSERR_NOTSUPPORTED expected, got %s\n",
1034 dev_name(WAVE_MAPPER),mmsys_error(rc));
1036 format.wFormatTag=WAVE_FORMAT_PCM;
1037 format.nChannels=2;
1038 format.wBitsPerSample=16;
1039 format.nSamplesPerSec=44100;
1040 format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
1041 format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
1042 format.cbSize=0;
1043 rc=waveOutOpen(&wout,ndev+1,&format,0,0,CALLBACK_NULL);
1044 ok(rc==MMSYSERR_BADDEVICEID,
1045 "waveOutOpen(%s): MMSYSERR_BADDEVICEID expected, got %s\n",
1046 dev_name(ndev+1),mmsys_error(rc));
1048 for (d=0;d<ndev;d++)
1049 wave_out_test_device(d);
1051 if (ndev>0)
1052 wave_out_test_device(WAVE_MAPPER);
1055 START_TEST(wave)
1057 wave_out_tests();