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
26 #include "wine/test.h"
38 #include "winmm_test.h"
41 * Note that in most of this test we may get MMSYSERR_BADDEVICEID errors
42 * at about any time if the user starts another application that uses the
43 * sound device. So we should not report these as test failures.
45 * This test can play a test tone. But this only makes sense if someone
46 * is going to carefully listen to it, and would only bother everyone else.
47 * So this is only done if the test is being run in interactive mode.
50 #define PI 3.14159265358979323846
51 static char* wave_generate_la(WAVEFORMATEX
* wfx
, double duration
, DWORD
* size
)
58 nb_samples
=(int)(duration
*wfx
->nSamplesPerSec
);
59 *size
=nb_samples
*wfx
->nBlockAlign
;
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
++)
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
++) {
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
++) {
78 b
[1]=(sample
>> 8) & 0xff;
79 b
[2]=(sample
>> 16) & 0xff;
82 } else if (wfx
->wBitsPerSample
==32) {
83 signed int sample
=(signed int)(((double)0x7fffffff+0.5)*y
-0.5);
84 for (j
= 0; j
< wfx
->nChannels
; j
++) {
86 b
[1]=(sample
>> 8) & 0xff;
87 b
[2]=(sample
>> 16) & 0xff;
88 b
[3]=(sample
>> 24) & 0xff;
96 const char * dev_name(int device
)
99 if (device
== WAVE_MAPPER
)
100 return "WAVE_MAPPER";
101 sprintf(name
, "%d", device
);
105 const char* mmsys_error(MMRESULT error
)
107 #define ERR_TO_STR(dev) case dev: return #dev
108 static char unknown
[32];
110 ERR_TO_STR(MMSYSERR_NOERROR
);
111 ERR_TO_STR(MMSYSERR_ERROR
);
112 ERR_TO_STR(MMSYSERR_BADDEVICEID
);
113 ERR_TO_STR(MMSYSERR_NOTENABLED
);
114 ERR_TO_STR(MMSYSERR_ALLOCATED
);
115 ERR_TO_STR(MMSYSERR_INVALHANDLE
);
116 ERR_TO_STR(MMSYSERR_NODRIVER
);
117 ERR_TO_STR(MMSYSERR_NOMEM
);
118 ERR_TO_STR(MMSYSERR_NOTSUPPORTED
);
119 ERR_TO_STR(MMSYSERR_BADERRNUM
);
120 ERR_TO_STR(MMSYSERR_INVALFLAG
);
121 ERR_TO_STR(MMSYSERR_INVALPARAM
);
122 ERR_TO_STR(WAVERR_BADFORMAT
);
123 ERR_TO_STR(WAVERR_STILLPLAYING
);
124 ERR_TO_STR(WAVERR_UNPREPARED
);
125 ERR_TO_STR(WAVERR_SYNC
);
126 ERR_TO_STR(MIDIERR_UNPREPARED
);
127 ERR_TO_STR(MIDIERR_STILLPLAYING
);
128 ERR_TO_STR(MIDIERR_NOTREADY
);
129 ERR_TO_STR(MIDIERR_NODEVICE
);
130 ERR_TO_STR(MIDIERR_INVALIDSETUP
);
131 ERR_TO_STR(TIMERR_NOCANDO
);
132 ERR_TO_STR(TIMERR_STRUCT
);
133 ERR_TO_STR(JOYERR_PARMS
);
134 ERR_TO_STR(JOYERR_NOCANDO
);
135 ERR_TO_STR(JOYERR_UNPLUGGED
);
136 ERR_TO_STR(MIXERR_INVALLINE
);
137 ERR_TO_STR(MIXERR_INVALCONTROL
);
138 ERR_TO_STR(MIXERR_INVALVALUE
);
139 ERR_TO_STR(MMIOERR_FILENOTFOUND
);
140 ERR_TO_STR(MMIOERR_OUTOFMEMORY
);
141 ERR_TO_STR(MMIOERR_CANNOTOPEN
);
142 ERR_TO_STR(MMIOERR_CANNOTCLOSE
);
143 ERR_TO_STR(MMIOERR_CANNOTREAD
);
144 ERR_TO_STR(MMIOERR_CANNOTWRITE
);
145 ERR_TO_STR(MMIOERR_CANNOTSEEK
);
146 ERR_TO_STR(MMIOERR_CANNOTEXPAND
);
147 ERR_TO_STR(MMIOERR_CHUNKNOTFOUND
);
148 ERR_TO_STR(MMIOERR_UNBUFFERED
);
150 sprintf(unknown
, "Unknown(0x%08x)", error
);
155 const char* wave_out_error(MMRESULT error
)
157 static char msg
[1024];
158 static char long_msg
[1100];
161 rc
= waveOutGetErrorText(error
, msg
, sizeof(msg
));
162 if (rc
!= MMSYSERR_NOERROR
)
163 sprintf(long_msg
, "waveOutGetErrorText(%x) failed with error %x",
166 sprintf(long_msg
, "%s(%s)", mmsys_error(error
), msg
);
170 const char * wave_open_flags(DWORD flags
)
172 static char msg
[1024];
175 if ((flags
& CALLBACK_TYPEMASK
) == CALLBACK_EVENT
) {
176 strcat(msg
, "CALLBACK_EVENT");
179 if ((flags
& CALLBACK_TYPEMASK
) == CALLBACK_FUNCTION
) {
180 if (!first
) strcat(msg
, "|");
181 strcat(msg
, "CALLBACK_FUNCTION");
184 if ((flags
& CALLBACK_TYPEMASK
) == CALLBACK_NULL
) {
185 if (!first
) strcat(msg
, "|");
186 strcat(msg
, "CALLBACK_NULL");
189 if ((flags
& CALLBACK_TYPEMASK
) == CALLBACK_THREAD
) {
190 if (!first
) strcat(msg
, "|");
191 strcat(msg
, "CALLBACK_THREAD");
194 if ((flags
& CALLBACK_TYPEMASK
) == CALLBACK_WINDOW
) {
195 if (!first
) strcat(msg
, "|");
196 strcat(msg
, "CALLBACK_WINDOW");
199 if ((flags
& WAVE_ALLOWSYNC
) == WAVE_ALLOWSYNC
) {
200 if (!first
) strcat(msg
, "|");
201 strcat(msg
, "WAVE_ALLOWSYNC");
204 if ((flags
& WAVE_FORMAT_DIRECT
) == WAVE_FORMAT_DIRECT
) {
205 if (!first
) strcat(msg
, "|");
206 strcat(msg
, "WAVE_FORMAT_DIRECT");
209 if ((flags
& WAVE_FORMAT_QUERY
) == WAVE_FORMAT_QUERY
) {
210 if (!first
) strcat(msg
, "|");
211 strcat(msg
, "WAVE_FORMAT_QUERY");
214 if ((flags
& WAVE_MAPPED
) == WAVE_MAPPED
) {
215 if (!first
) strcat(msg
, "|");
216 strcat(msg
, "WAVE_MAPPED");
222 static const char * wave_out_caps(DWORD dwSupport
)
224 #define ADD_FLAG(f) if (dwSupport & f) strcat(msg, " " #f)
225 static char msg
[256];
228 ADD_FLAG(WAVECAPS_PITCH
);
229 ADD_FLAG(WAVECAPS_PLAYBACKRATE
);
230 ADD_FLAG(WAVECAPS_VOLUME
);
231 ADD_FLAG(WAVECAPS_LRVOLUME
);
232 ADD_FLAG(WAVECAPS_SYNC
);
233 ADD_FLAG(WAVECAPS_SAMPLEACCURATE
);
235 return msg
[0] ? msg
+ 1 : "";
239 static const char * wave_time_format(UINT type
)
242 #define TIME_FORMAT(f) case f: return #f
244 TIME_FORMAT(TIME_MS
);
245 TIME_FORMAT(TIME_SAMPLES
);
246 TIME_FORMAT(TIME_BYTES
);
247 TIME_FORMAT(TIME_SMPTE
);
248 TIME_FORMAT(TIME_MIDI
);
249 TIME_FORMAT(TIME_TICKS
);
252 sprintf(msg
, "Unknown(0x%04x)", type
);
256 const char * get_format_str(WORD format
)
259 #define WAVE_FORMAT(f) case f: return #f
261 WAVE_FORMAT(WAVE_FORMAT_PCM
);
262 WAVE_FORMAT(WAVE_FORMAT_ADPCM
);
263 WAVE_FORMAT(WAVE_FORMAT_IBM_CVSD
);
264 WAVE_FORMAT(WAVE_FORMAT_ALAW
);
265 WAVE_FORMAT(WAVE_FORMAT_MULAW
);
266 WAVE_FORMAT(WAVE_FORMAT_OKI_ADPCM
);
267 WAVE_FORMAT(WAVE_FORMAT_IMA_ADPCM
);
268 WAVE_FORMAT(WAVE_FORMAT_MEDIASPACE_ADPCM
);
269 WAVE_FORMAT(WAVE_FORMAT_SIERRA_ADPCM
);
270 WAVE_FORMAT(WAVE_FORMAT_G723_ADPCM
);
271 WAVE_FORMAT(WAVE_FORMAT_DIGISTD
);
272 WAVE_FORMAT(WAVE_FORMAT_DIGIFIX
);
273 WAVE_FORMAT(WAVE_FORMAT_DIALOGIC_OKI_ADPCM
);
274 WAVE_FORMAT(WAVE_FORMAT_YAMAHA_ADPCM
);
275 WAVE_FORMAT(WAVE_FORMAT_SONARC
);
276 WAVE_FORMAT(WAVE_FORMAT_DSPGROUP_TRUESPEECH
);
277 WAVE_FORMAT(WAVE_FORMAT_ECHOSC1
);
278 WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF36
);
279 WAVE_FORMAT(WAVE_FORMAT_APTX
);
280 WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF10
);
281 WAVE_FORMAT(WAVE_FORMAT_DOLBY_AC2
);
282 WAVE_FORMAT(WAVE_FORMAT_GSM610
);
283 WAVE_FORMAT(WAVE_FORMAT_ANTEX_ADPCME
);
284 WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_VQLPC
);
285 WAVE_FORMAT(WAVE_FORMAT_DIGIREAL
);
286 WAVE_FORMAT(WAVE_FORMAT_DIGIADPCM
);
287 WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_CR10
);
288 WAVE_FORMAT(WAVE_FORMAT_NMS_VBXADPCM
);
289 WAVE_FORMAT(WAVE_FORMAT_G721_ADPCM
);
290 WAVE_FORMAT(WAVE_FORMAT_MPEG
);
291 WAVE_FORMAT(WAVE_FORMAT_MPEGLAYER3
);
292 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_ADPCM
);
293 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH8
);
294 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH10
);
295 WAVE_FORMAT(WAVE_FORMAT_FM_TOWNS_SND
);
296 WAVE_FORMAT(WAVE_FORMAT_OLIGSM
);
297 WAVE_FORMAT(WAVE_FORMAT_OLIADPCM
);
298 WAVE_FORMAT(WAVE_FORMAT_OLICELP
);
299 WAVE_FORMAT(WAVE_FORMAT_OLISBC
);
300 WAVE_FORMAT(WAVE_FORMAT_OLIOPR
);
301 WAVE_FORMAT(WAVE_FORMAT_DEVELOPMENT
);
302 WAVE_FORMAT(WAVE_FORMAT_EXTENSIBLE
);
305 sprintf(msg
, "Unknown(0x%04x)", format
);
309 static void check_position(int device
, HWAVEOUT wout
, DWORD bytes
,
310 LPWAVEFORMATEX pwfx
)
317 samples
=bytes
/(pwfx
->wBitsPerSample
/8*pwfx
->nChannels
);
318 duration
=((double)samples
)/pwfx
->nSamplesPerSec
;
320 mmtime
.wType
= TIME_BYTES
;
321 rc
=waveOutGetPosition(wout
, &mmtime
, sizeof(mmtime
));
322 ok(rc
==MMSYSERR_NOERROR
,
323 "waveOutGetPosition(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
324 if (mmtime
.wType
== TIME_BYTES
)
325 ok(mmtime
.u
.cb
==bytes
,
326 "waveOutGetPosition(%s): returned %ld bytes, should be %ld\n",
327 dev_name(device
),mmtime
.u
.cb
, bytes
);
329 trace("waveOutGetPosition(%s): TIME_BYTES not supported, returned %s\n",
330 dev_name(device
),wave_time_format(mmtime
.wType
));
332 mmtime
.wType
= TIME_SAMPLES
;
333 rc
=waveOutGetPosition(wout
, &mmtime
, sizeof(mmtime
));
334 ok(rc
==MMSYSERR_NOERROR
,
335 "waveOutGetPosition(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
336 if (mmtime
.wType
== TIME_SAMPLES
)
337 ok(mmtime
.u
.sample
==samples
,
338 "waveOutGetPosition(%s): returned %ld samples, should be %ld\n",
339 dev_name(device
), mmtime
.u
.sample
, samples
);
341 trace("waveOutGetPosition(%s): TIME_SAMPLES not supported, "
342 "returned %s\n",dev_name(device
),wave_time_format(mmtime
.wType
));
344 mmtime
.wType
= TIME_MS
;
345 rc
=waveOutGetPosition(wout
, &mmtime
, sizeof(mmtime
));
346 ok(rc
==MMSYSERR_NOERROR
,
347 "waveOutGetPosition(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
348 if (mmtime
.wType
== TIME_MS
)
349 ok(mmtime
.u
.ms
==floor(duration
*1000.0),
350 "waveOutGetPosition(%s): returned %ld ms, should be %ld\n",
351 dev_name(device
), mmtime
.u
.ms
, (long)floor(duration
*1000.0));
353 trace("waveOutGetPosition(%s): TIME_MS not supported, returned %s\n",
354 dev_name(device
),wave_time_format(mmtime
.wType
));
356 mmtime
.wType
= TIME_SMPTE
;
357 rc
=waveOutGetPosition(wout
, &mmtime
, sizeof(mmtime
));
358 ok(rc
==MMSYSERR_NOERROR
,
359 "waveOutGetPosition(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
360 if (mmtime
.wType
== TIME_SMPTE
)
362 BYTE frames
=ceil(fmod(duration
*mmtime
.u
.smpte
.fps
, mmtime
.u
.smpte
.fps
));
363 ok(mmtime
.u
.smpte
.hour
==(BYTE
)(floor(duration
/(60*60))) &&
364 mmtime
.u
.smpte
.min
==(BYTE
)(fmod(floor(duration
/60), 60)) &&
365 mmtime
.u
.smpte
.sec
==(BYTE
)(fmod(duration
,60)) &&
366 mmtime
.u
.smpte
.frame
==frames
,
367 "waveOutGetPosition(%s): returned %d:%d:%d %d, "
368 "should be %d:%d:%d %d\n", dev_name(device
), mmtime
.u
.smpte
.hour
,
369 mmtime
.u
.smpte
.min
, mmtime
.u
.smpte
.sec
, mmtime
.u
.smpte
.frame
,
370 (BYTE
)(floor(duration
/(60*60))),
371 (BYTE
)(fmod(floor(duration
/60), 60)),
372 (BYTE
)(fmod(duration
,60)),
376 trace("waveOutGetPosition(%s): TIME_SMPTE not supported, returned %s\n",
377 dev_name(device
),wave_time_format(mmtime
.wType
));
380 static void wave_out_test_deviceOut(int device
, double duration
,
381 LPWAVEFORMATEX pwfx
, DWORD format
,
382 DWORD flags
, LPWAVEOUTCAPS pcaps
)
389 WORD nChannels
= pwfx
->nChannels
;
390 WORD wBitsPerSample
= pwfx
->wBitsPerSample
;
391 DWORD nSamplesPerSec
= pwfx
->nSamplesPerSec
;
393 hevent
=CreateEvent(NULL
,FALSE
,FALSE
,NULL
);
394 ok(hevent
!=NULL
,"CreateEvent(): error=%ld\n",GetLastError());
399 rc
=waveOutOpen(&wout
,device
,pwfx
,(DWORD
)hevent
,0,CALLBACK_EVENT
|flags
);
400 /* Note: Win9x doesn't know WAVE_FORMAT_DIRECT */
401 /* It is acceptable to fail on formats that are not specified to work */
402 ok(rc
==MMSYSERR_NOERROR
|| rc
==MMSYSERR_BADDEVICEID
||
403 rc
==MMSYSERR_NOTENABLED
|| rc
==MMSYSERR_NODRIVER
||
404 rc
==MMSYSERR_ALLOCATED
||
405 ((rc
==WAVERR_BADFORMAT
|| rc
==MMSYSERR_NOTSUPPORTED
) &&
406 (flags
& WAVE_FORMAT_DIRECT
) && !(pcaps
->dwFormats
& format
)) ||
407 ((rc
==WAVERR_BADFORMAT
|| rc
==MMSYSERR_NOTSUPPORTED
) &&
408 (!(flags
& WAVE_FORMAT_DIRECT
) || (flags
& WAVE_MAPPED
)) &&
409 !(pcaps
->dwFormats
& format
)) ||
410 (rc
==MMSYSERR_INVALFLAG
&& (flags
& WAVE_FORMAT_DIRECT
)),
411 "waveOutOpen(%s): format=%ldx%2dx%d flags=%lx(%s) rc=%s\n",
412 dev_name(device
),pwfx
->nSamplesPerSec
,pwfx
->wBitsPerSample
,
413 pwfx
->nChannels
,CALLBACK_EVENT
|flags
,
414 wave_open_flags(CALLBACK_EVENT
|flags
),wave_out_error(rc
));
415 if ((rc
==WAVERR_BADFORMAT
|| rc
==MMSYSERR_NOTSUPPORTED
) &&
416 (flags
& WAVE_FORMAT_DIRECT
) && (pcaps
->dwFormats
& format
))
417 trace(" Reason: The device lists this format as supported in it's "
418 "capabilities but opening it failed.\n");
419 if ((rc
==WAVERR_BADFORMAT
|| rc
==MMSYSERR_NOTSUPPORTED
) &&
420 !(pcaps
->dwFormats
& format
))
421 trace("waveOutOpen(%s): format=%ldx%2dx%d %s rc=%s failed but format "
422 "not supported so OK.\n", dev_name(device
), pwfx
->nSamplesPerSec
,
423 pwfx
->wBitsPerSample
,pwfx
->nChannels
,
424 flags
& WAVE_FORMAT_DIRECT
? "flags=WAVE_FORMAT_DIRECT" :
425 flags
& WAVE_MAPPED
? "flags=WAVE_MAPPED" : "", mmsys_error(rc
));
426 if (rc
!=MMSYSERR_NOERROR
) {
431 ok(pwfx
->nChannels
==nChannels
&&
432 pwfx
->wBitsPerSample
==wBitsPerSample
&&
433 pwfx
->nSamplesPerSec
==nSamplesPerSec
,
434 "got the wrong format: %ldx%2dx%d instead of %ldx%2dx%d\n",
435 pwfx
->nSamplesPerSec
, pwfx
->wBitsPerSample
,
436 pwfx
->nChannels
, nSamplesPerSec
, wBitsPerSample
, nChannels
);
438 frag
.lpData
=wave_generate_la(pwfx
,duration
,&frag
.dwBufferLength
);
442 rc
=waveOutGetVolume(wout
,&volume
);
443 ok(rc
==MMSYSERR_NOERROR
,"waveOutGetVolume(%s): rc=%s\n",
444 dev_name(device
),wave_out_error(rc
));
446 rc
=waveOutPrepareHeader(wout
, &frag
, sizeof(frag
));
447 ok(rc
==MMSYSERR_NOERROR
,
448 "waveOutPrepareHeader(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
450 if (winetest_interactive
&& rc
==MMSYSERR_NOERROR
) {
452 trace("Playing %g second 440Hz tone at %5ldx%2dx%d %s %s\n",duration
,
453 pwfx
->nSamplesPerSec
, pwfx
->wBitsPerSample
,pwfx
->nChannels
,
454 get_format_str(pwfx
->wFormatTag
),
455 flags
& WAVE_FORMAT_DIRECT
? "WAVE_FORMAT_DIRECT" :
456 flags
& WAVE_MAPPED
? "WAVE_MAPPED" : "");
458 /* Check that the position is 0 at start */
459 check_position(device
, wout
, 0.0, pwfx
);
461 rc
=waveOutSetVolume(wout
,0x20002000);
462 ok(rc
==MMSYSERR_NOERROR
,"waveOutSetVolume(%s): rc=%s\n",
463 dev_name(device
),wave_out_error(rc
));
464 WaitForSingleObject(hevent
,INFINITE
);
466 start
=GetTickCount();
467 rc
=waveOutWrite(wout
, &frag
, sizeof(frag
));
468 ok(rc
==MMSYSERR_NOERROR
,"waveOutWrite(%s): rc=%s\n",
469 dev_name(device
),wave_out_error(rc
));
470 WaitForSingleObject(hevent
,INFINITE
);
472 /* Check the sound duration was within 10% of the expected value */
474 if (winetest_debug
> 1)
475 trace("sound duration=%ld\n",end
-start
);
476 ok(fabs(1000*duration
-end
+start
)<=100*duration
,
477 "The sound played for %ld ms instead of %g ms\n",
478 end
-start
,1000*duration
);
480 rc
=waveOutSetVolume(wout
,volume
);
481 ok(rc
==MMSYSERR_NOERROR
,"waveOutSetVolume(%s): rc=%s\n",
482 dev_name(device
),wave_out_error(rc
));
484 check_position(device
, wout
, frag
.dwBufferLength
, pwfx
);
487 rc
=waveOutUnprepareHeader(wout
, &frag
, sizeof(frag
));
488 ok(rc
==MMSYSERR_NOERROR
,
489 "waveOutUnprepareHeader(%s): rc=%s\n",dev_name(device
),
494 rc
=waveOutClose(wout
);
495 ok(rc
==MMSYSERR_NOERROR
,"waveOutClose(%s): rc=%s\n",dev_name(device
),
499 static void wave_out_test_device(int device
)
503 WAVEFORMATEX format
, oformat
;
504 WAVEFORMATEXTENSIBLE wfex
;
513 SYSTEM_INFO sSysInfo
;
517 GetSystemInfo(&sSysInfo
);
518 dwPageSize
= sSysInfo
.dwPageSize
;
520 rc
=waveOutGetDevCapsA(device
,&capsA
,sizeof(capsA
));
521 ok(rc
==MMSYSERR_NOERROR
|| rc
==MMSYSERR_BADDEVICEID
||
522 rc
==MMSYSERR_NODRIVER
,
523 "waveOutGetDevCapsA(%s): failed to get capabilities: rc=%s\n",
524 dev_name(device
),wave_out_error(rc
));
525 if (rc
==MMSYSERR_BADDEVICEID
|| rc
==MMSYSERR_NODRIVER
)
528 rc
=waveOutGetDevCapsW(device
,&capsW
,sizeof(capsW
));
529 ok(rc
==MMSYSERR_NOERROR
|| rc
==MMSYSERR_NOTSUPPORTED
,
530 "waveOutGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NOTSUPPORTED "
531 "expected, got %s\n",dev_name(device
),wave_out_error(rc
));
533 rc
=waveOutGetDevCapsA(device
,0,sizeof(capsA
));
534 ok(rc
==MMSYSERR_INVALPARAM
,
535 "waveOutGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, "
536 "got %s\n",dev_name(device
),wave_out_error(rc
));
538 rc
=waveOutGetDevCapsW(device
,0,sizeof(capsW
));
539 ok(rc
==MMSYSERR_INVALPARAM
|| rc
==MMSYSERR_NOTSUPPORTED
,
540 "waveOutGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED "
541 "expected, got %s\n",dev_name(device
),wave_out_error(rc
));
543 #if 0 /* FIXME: this works on windows but crashes wine */
544 rc
=waveOutGetDevCapsA(device
,(LPWAVEOUTCAPSA
)1,sizeof(capsA
));
545 ok(rc
==MMSYSERR_INVALPARAM
,
546 "waveOutGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, got %s\n",
547 dev_name(device
),wave_out_error(rc
));
549 rc
=waveOutGetDevCapsW(device
,(LPWAVEOUTCAPSW
)1,sizeof(capsW
));
550 ok(rc
==MMSYSERR_INVALPARAM
|| rc
==MMSYSERR_NOTSUPPORTED
,
551 "waveOutGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED "
552 "expected, got %s\n",dev_name(device
),wave_out_error(rc
));
555 rc
=waveOutGetDevCapsA(device
,&capsA
,4);
556 ok(rc
==MMSYSERR_NOERROR
,
557 "waveOutGetDevCapsA(%s): MMSYSERR_NOERROR expected, got %s\n",
558 dev_name(device
),wave_out_error(rc
));
560 rc
=waveOutGetDevCapsW(device
,&capsW
,4);
561 ok(rc
==MMSYSERR_NOERROR
|| rc
==MMSYSERR_NOTSUPPORTED
,
562 "waveOutGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NOTSUPPORTED "
563 "expected, got %s\n",dev_name(device
),wave_out_error(rc
));
566 rc
=waveOutMessage((HWAVEOUT
)device
, DRV_QUERYDEVICEINTERFACESIZE
,
567 (DWORD_PTR
)&size
, 0);
568 ok(rc
==MMSYSERR_NOERROR
|| rc
==MMSYSERR_INVALPARAM
||
569 rc
==MMSYSERR_NOTSUPPORTED
,
570 "waveOutMessage(%s): failed to get interface size, rc=%s\n",
571 dev_name(device
),wave_out_error(rc
));
572 if (rc
==MMSYSERR_NOERROR
) {
573 nameW
= (WCHAR
*)malloc(size
);
574 rc
=waveOutMessage((HWAVEOUT
)device
, DRV_QUERYDEVICEINTERFACE
,
575 (DWORD_PTR
)nameW
, size
);
576 ok(rc
==MMSYSERR_NOERROR
,"waveOutMessage(%s): failed to get interface "
577 "name, rc=%s\n",dev_name(device
),wave_out_error(rc
));
578 ok(lstrlenW(nameW
)+1==size
/sizeof(WCHAR
),"got an incorrect size: "
579 "%ld instead of %d\n",size
,(lstrlenW(nameW
)+1)*sizeof(WCHAR
));
580 if (rc
==MMSYSERR_NOERROR
) {
581 nameA
= malloc(size
/sizeof(WCHAR
));
582 WideCharToMultiByte(CP_ACP
, 0, nameW
, size
/sizeof(WCHAR
), nameA
,
583 size
/sizeof(WCHAR
), NULL
, NULL
);
587 else if (rc
==MMSYSERR_NOTSUPPORTED
) {
588 nameA
=strdup("not supported");
591 trace(" %s: \"%s\" (%s) %d.%d (%d:%d)\n",dev_name(device
),capsA
.szPname
,
592 (nameA
?nameA
:"failed"),capsA
.vDriverVersion
>> 8,
593 capsA
.vDriverVersion
& 0xff, capsA
.wMid
,capsA
.wPid
);
594 trace(" channels=%d formats=%05lx support=%04lx\n",
595 capsA
.wChannels
,capsA
.dwFormats
,capsA
.dwSupport
);
596 trace(" %s\n",wave_out_caps(capsA
.dwSupport
));
599 if (winetest_interactive
&& (device
!= WAVE_MAPPER
))
601 trace("Playing a 5 seconds reference tone.\n");
602 trace("All subsequent tones should be identical to this one.\n");
603 trace("Listen for stutter, changes in pitch, volume, etc.\n");
604 format
.wFormatTag
=WAVE_FORMAT_PCM
;
606 format
.wBitsPerSample
=8;
607 format
.nSamplesPerSec
=22050;
608 format
.nBlockAlign
=format
.nChannels
*format
.wBitsPerSample
/8;
609 format
.nAvgBytesPerSec
=format
.nSamplesPerSec
*format
.nBlockAlign
;
611 wave_out_test_deviceOut(device
,5.0,&format
,WAVE_FORMAT_2M08
,0,&capsA
);
614 for (f
=0;f
<NB_WIN_FORMATS
;f
++) {
615 format
.wFormatTag
=WAVE_FORMAT_PCM
;
616 format
.nChannels
=win_formats
[f
][3];
617 format
.wBitsPerSample
=win_formats
[f
][2];
618 format
.nSamplesPerSec
=win_formats
[f
][1];
619 format
.nBlockAlign
=format
.nChannels
*format
.wBitsPerSample
/8;
620 format
.nAvgBytesPerSec
=format
.nSamplesPerSec
*format
.nBlockAlign
;
622 wave_out_test_deviceOut(device
,1.0,&format
,win_formats
[f
][0],0,&capsA
);
623 wave_out_test_deviceOut(device
,1.0,&format
,win_formats
[f
][0],
624 WAVE_FORMAT_DIRECT
,&capsA
);
625 if (device
!= WAVE_MAPPER
)
626 wave_out_test_deviceOut(device
,1.0,&format
,win_formats
[f
][0],
630 /* Try a PCMWAVEFORMAT aligned next to an unaccessable page for bounds
632 twoPages
= VirtualAlloc(NULL
, 2 * dwPageSize
, MEM_RESERVE
| MEM_COMMIT
,
634 ok(twoPages
!=NULL
,"Failed to allocate 2 pages of memory\n");
636 res
= VirtualProtect(twoPages
+ dwPageSize
, dwPageSize
, PAGE_NOACCESS
,
638 ok(res
, "Failed to set memory access on second page\n");
640 LPWAVEFORMATEX pwfx
= (LPWAVEFORMATEX
)(twoPages
+ dwPageSize
-
641 sizeof(PCMWAVEFORMAT
));
642 pwfx
->wFormatTag
=WAVE_FORMAT_PCM
;
644 pwfx
->wBitsPerSample
=8;
645 pwfx
->nSamplesPerSec
=22050;
646 pwfx
->nBlockAlign
=pwfx
->nChannels
*pwfx
->wBitsPerSample
/8;
647 pwfx
->nAvgBytesPerSec
=pwfx
->nSamplesPerSec
*pwfx
->nBlockAlign
;
648 wave_out_test_deviceOut(device
,1.0,pwfx
,WAVE_FORMAT_2M08
,0,&capsA
);
649 wave_out_test_deviceOut(device
,1.0,pwfx
,WAVE_FORMAT_2M08
,
650 WAVE_FORMAT_DIRECT
,&capsA
);
651 if (device
!= WAVE_MAPPER
)
652 wave_out_test_deviceOut(device
,1.0,pwfx
,WAVE_FORMAT_2M08
,
655 VirtualFree(twoPages
, 2 * dwPageSize
, MEM_RELEASE
);
658 /* Testing invalid format: 11 bits per sample */
659 format
.wFormatTag
=WAVE_FORMAT_PCM
;
661 format
.wBitsPerSample
=11;
662 format
.nSamplesPerSec
=22050;
663 format
.nBlockAlign
=format
.nChannels
*format
.wBitsPerSample
/8;
664 format
.nAvgBytesPerSec
=format
.nSamplesPerSec
*format
.nBlockAlign
;
667 rc
=waveOutOpen(&wout
,device
,&format
,0,0,CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
668 ok(rc
==WAVERR_BADFORMAT
|| rc
==MMSYSERR_INVALFLAG
||
669 rc
==MMSYSERR_INVALPARAM
,
670 "waveOutOpen(%s): opening the device in 11 bits mode should fail: "
671 "rc=%s\n",dev_name(device
),wave_out_error(rc
));
672 if (rc
==MMSYSERR_NOERROR
) {
673 trace(" got %ldx%2dx%d for %ldx%2dx%d\n",
674 format
.nSamplesPerSec
, format
.wBitsPerSample
,
676 oformat
.nSamplesPerSec
, oformat
.wBitsPerSample
,
681 /* Testing invalid format: 2 MHz sample rate */
682 format
.wFormatTag
=WAVE_FORMAT_PCM
;
684 format
.wBitsPerSample
=16;
685 format
.nSamplesPerSec
=2000000;
686 format
.nBlockAlign
=format
.nChannels
*format
.wBitsPerSample
/8;
687 format
.nAvgBytesPerSec
=format
.nSamplesPerSec
*format
.nBlockAlign
;
690 rc
=waveOutOpen(&wout
,device
,&format
,0,0,CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
691 ok(rc
==WAVERR_BADFORMAT
|| rc
==MMSYSERR_INVALFLAG
||
692 rc
==MMSYSERR_INVALPARAM
,
693 "waveOutOpen(%s): opening the device at 2 MHz sample rate should fail: "
694 "rc=%s\n",dev_name(device
),wave_out_error(rc
));
695 if (rc
==MMSYSERR_NOERROR
) {
696 trace(" got %ldx%2dx%d for %ldx%2dx%d\n",
697 format
.nSamplesPerSec
, format
.wBitsPerSample
,
699 oformat
.nSamplesPerSec
, oformat
.wBitsPerSample
,
704 /* try some non PCM formats */
705 format
.wFormatTag
=WAVE_FORMAT_MULAW
;
707 format
.wBitsPerSample
=8;
708 format
.nSamplesPerSec
=8000;
709 format
.nBlockAlign
=format
.nChannels
*format
.wBitsPerSample
/8;
710 format
.nAvgBytesPerSec
=format
.nSamplesPerSec
*format
.nBlockAlign
;
713 rc
=waveOutOpen(&wout
,device
,&format
,0,0,CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
714 ok(rc
==MMSYSERR_NOERROR
||rc
==WAVERR_BADFORMAT
||
715 rc
==MMSYSERR_INVALFLAG
|| rc
==MMSYSERR_INVALPARAM
,
716 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
717 if (rc
==MMSYSERR_NOERROR
) {
719 wave_out_test_deviceOut(device
,1.0,&format
,0,0,
722 trace("waveOutOpen(%s): WAVE_FORMAT_MULAW not supported\n",
725 format
.wFormatTag
=WAVE_FORMAT_ADPCM
;
727 format
.wBitsPerSample
=4;
728 format
.nSamplesPerSec
=22050;
729 format
.nBlockAlign
=format
.nChannels
*format
.wBitsPerSample
/8;
730 format
.nAvgBytesPerSec
=format
.nSamplesPerSec
*format
.nBlockAlign
;
733 rc
=waveOutOpen(&wout
,device
,&format
,0,0,CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
734 ok(rc
==MMSYSERR_NOERROR
||rc
==WAVERR_BADFORMAT
||
735 rc
==MMSYSERR_INVALFLAG
|| rc
==MMSYSERR_INVALPARAM
,
736 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
737 if (rc
==MMSYSERR_NOERROR
) {
739 wave_out_test_deviceOut(device
,1.0,&format
,0,0,
742 trace("waveOutOpen(%s): WAVE_FORMAT_ADPCM not supported\n",
745 /* test if WAVEFORMATEXTENSIBLE supported */
746 wfex
.Format
.wFormatTag
=WAVE_FORMAT_EXTENSIBLE
;
747 wfex
.Format
.nChannels
=2;
748 wfex
.Format
.wBitsPerSample
=16;
749 wfex
.Format
.nSamplesPerSec
=22050;
750 wfex
.Format
.nBlockAlign
=wfex
.Format
.nChannels
*wfex
.Format
.wBitsPerSample
/8;
751 wfex
.Format
.nAvgBytesPerSec
=wfex
.Format
.nSamplesPerSec
*
752 wfex
.Format
.nBlockAlign
;
753 wfex
.Format
.cbSize
=22;
754 wfex
.Samples
.wValidBitsPerSample
=wfex
.Format
.wBitsPerSample
;
755 wfex
.dwChannelMask
=SPEAKER_ALL
;
756 wfex
.SubFormat
=KSDATAFORMAT_SUBTYPE_PCM
;
757 rc
=waveOutOpen(&wout
,device
,&wfex
.Format
,0,0,
758 CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
759 ok(rc
==MMSYSERR_NOERROR
|| rc
==WAVERR_BADFORMAT
||
760 rc
==MMSYSERR_INVALFLAG
|| rc
==MMSYSERR_INVALPARAM
,
761 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
762 if (rc
==MMSYSERR_NOERROR
) {
764 wave_out_test_deviceOut(device
,1.0,&wfex
.Format
,WAVE_FORMAT_2M16
,0,
767 trace("waveOutOpen(%s): WAVE_FORMAT_EXTENSIBLE not supported\n",
770 /* test if 4 channels supported */
771 wfex
.Format
.wFormatTag
=WAVE_FORMAT_EXTENSIBLE
;
772 wfex
.Format
.nChannels
=4;
773 wfex
.Format
.wBitsPerSample
=16;
774 wfex
.Format
.nSamplesPerSec
=22050;
775 wfex
.Format
.nBlockAlign
=wfex
.Format
.nChannels
*wfex
.Format
.wBitsPerSample
/8;
776 wfex
.Format
.nAvgBytesPerSec
=wfex
.Format
.nSamplesPerSec
*
777 wfex
.Format
.nBlockAlign
;
778 wfex
.Format
.cbSize
=22;
779 wfex
.Samples
.wValidBitsPerSample
=wfex
.Format
.wBitsPerSample
;
780 wfex
.dwChannelMask
=SPEAKER_ALL
;
781 wfex
.SubFormat
=KSDATAFORMAT_SUBTYPE_PCM
;
782 rc
=waveOutOpen(&wout
,device
,&wfex
.Format
,0,0,
783 CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
784 ok(rc
==MMSYSERR_NOERROR
|| rc
==WAVERR_BADFORMAT
||
785 rc
==MMSYSERR_INVALFLAG
|| rc
==MMSYSERR_INVALPARAM
,
786 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
787 if (rc
==MMSYSERR_NOERROR
) {
789 wave_out_test_deviceOut(device
,1.0,&wfex
.Format
,0,0,
792 trace("waveOutOpen(%s): 4 channels not supported\n",
795 /* test if 6 channels supported */
796 wfex
.Format
.wFormatTag
=WAVE_FORMAT_EXTENSIBLE
;
797 wfex
.Format
.nChannels
=6;
798 wfex
.Format
.wBitsPerSample
=16;
799 wfex
.Format
.nSamplesPerSec
=22050;
800 wfex
.Format
.nBlockAlign
=wfex
.Format
.nChannels
*wfex
.Format
.wBitsPerSample
/8;
801 wfex
.Format
.nAvgBytesPerSec
=wfex
.Format
.nSamplesPerSec
*
802 wfex
.Format
.nBlockAlign
;
803 wfex
.Format
.cbSize
=22;
804 wfex
.Samples
.wValidBitsPerSample
=wfex
.Format
.wBitsPerSample
;
805 wfex
.dwChannelMask
=SPEAKER_ALL
;
806 wfex
.SubFormat
=KSDATAFORMAT_SUBTYPE_PCM
;
807 rc
=waveOutOpen(&wout
,device
,&wfex
.Format
,0,0,
808 CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
809 ok(rc
==MMSYSERR_NOERROR
|| rc
==WAVERR_BADFORMAT
||
810 rc
==MMSYSERR_INVALFLAG
|| rc
==MMSYSERR_INVALPARAM
,
811 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
812 if (rc
==MMSYSERR_NOERROR
) {
814 wave_out_test_deviceOut(device
,1.0,&wfex
.Format
,WAVE_FORMAT_2M16
,0,
817 trace("waveOutOpen(%s): 6 channels not supported\n",
820 #if 0 /* ALSA doesn't like this format */
821 /* test if 24 bit samples supported */
822 wfex
.Format
.wFormatTag
=WAVE_FORMAT_EXTENSIBLE
;
823 wfex
.Format
.nChannels
=2;
824 wfex
.Format
.wBitsPerSample
=24;
825 wfex
.Format
.nSamplesPerSec
=22050;
826 wfex
.Format
.nBlockAlign
=wfex
.Format
.nChannels
*wfex
.Format
.wBitsPerSample
/8;
827 wfex
.Format
.nAvgBytesPerSec
=wfex
.Format
.nSamplesPerSec
*
828 wfex
.Format
.nBlockAlign
;
829 wfex
.Format
.cbSize
=22;
830 wfex
.Samples
.wValidBitsPerSample
=wfex
.Format
.wBitsPerSample
;
831 wfex
.dwChannelMask
=SPEAKER_ALL
;
832 wfex
.SubFormat
=KSDATAFORMAT_SUBTYPE_PCM
;
833 rc
=waveOutOpen(&wout
,device
,&wfex
.Format
,0,0,
834 CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
835 ok(rc
==MMSYSERR_NOERROR
|| rc
==WAVERR_BADFORMAT
||
836 rc
==MMSYSERR_INVALFLAG
|| rc
==MMSYSERR_INVALPARAM
,
837 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
838 if (rc
==MMSYSERR_NOERROR
) {
840 wave_out_test_deviceOut(device
,1.0,&wfex
.Format
,WAVE_FORMAT_2M16
,0,
843 trace("waveOutOpen(%s): 24 bit samples not supported\n",
847 /* test if 32 bit samples supported */
848 wfex
.Format
.wFormatTag
=WAVE_FORMAT_EXTENSIBLE
;
849 wfex
.Format
.nChannels
=2;
850 wfex
.Format
.wBitsPerSample
=32;
851 wfex
.Format
.nSamplesPerSec
=22050;
852 wfex
.Format
.nBlockAlign
=wfex
.Format
.nChannels
*wfex
.Format
.wBitsPerSample
/8;
853 wfex
.Format
.nAvgBytesPerSec
=wfex
.Format
.nSamplesPerSec
*
854 wfex
.Format
.nBlockAlign
;
855 wfex
.Format
.cbSize
=22;
856 wfex
.Samples
.wValidBitsPerSample
=wfex
.Format
.wBitsPerSample
;
857 wfex
.dwChannelMask
=SPEAKER_ALL
;
858 wfex
.SubFormat
=KSDATAFORMAT_SUBTYPE_PCM
;
859 rc
=waveOutOpen(&wout
,device
,&wfex
.Format
,0,0,
860 CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
861 ok(rc
==MMSYSERR_NOERROR
|| rc
==WAVERR_BADFORMAT
||
862 rc
==MMSYSERR_INVALFLAG
|| rc
==MMSYSERR_INVALPARAM
,
863 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
864 if (rc
==MMSYSERR_NOERROR
) {
866 wave_out_test_deviceOut(device
,1.0,&wfex
.Format
,WAVE_FORMAT_2M16
,0,
869 trace("waveOutOpen(%s): 32 bit samples not supported\n",
873 static void wave_out_tests()
882 ndev
=waveOutGetNumDevs();
883 trace("found %d WaveOut devices\n",ndev
);
885 rc
=waveOutGetDevCapsA(ndev
+1,&capsA
,sizeof(capsA
));
886 ok(rc
==MMSYSERR_BADDEVICEID
,
887 "waveOutGetDevCapsA(%s): MMSYSERR_BADDEVICEID expected, got %s\n",
888 dev_name(ndev
+1),mmsys_error(rc
));
890 rc
=waveOutGetDevCapsW(ndev
+1,&capsW
,sizeof(capsW
));
891 ok(rc
==MMSYSERR_BADDEVICEID
,
892 "waveOutGetDevCapsW(%s): MMSYSERR_BADDEVICEID expected, got %s\n",
893 dev_name(ndev
+1),mmsys_error(rc
));
895 rc
=waveOutGetDevCapsA(WAVE_MAPPER
,&capsA
,sizeof(capsA
));
897 ok(rc
==MMSYSERR_NOERROR
,
898 "waveOutGetDevCapsA(%s): MMSYSERR_NOERROR expected, got %s\n",
899 dev_name(WAVE_MAPPER
),mmsys_error(rc
));
901 ok(rc
==MMSYSERR_BADDEVICEID
|| rc
==MMSYSERR_NODRIVER
,
902 "waveOutGetDevCapsA(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NODRIVER "
903 "expected, got %s\n",dev_name(WAVE_MAPPER
),mmsys_error(rc
));
905 rc
=waveOutGetDevCapsW(WAVE_MAPPER
,&capsW
,sizeof(capsW
));
907 ok(rc
==MMSYSERR_NOERROR
,
908 "waveOutGetDevCapsW(%s): MMSYSERR_NOERROR expected, got %s\n",
909 dev_name(WAVE_MAPPER
),mmsys_error(rc
));
911 ok(rc
==MMSYSERR_BADDEVICEID
|| rc
==MMSYSERR_NODRIVER
,
912 "waveOutGetDevCapsW(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NODRIVER "
913 "expected, got %s\n",dev_name(WAVE_MAPPER
),mmsys_error(rc
));
915 format
.wFormatTag
=WAVE_FORMAT_PCM
;
917 format
.wBitsPerSample
=16;
918 format
.nSamplesPerSec
=44100;
919 format
.nBlockAlign
=format
.nChannels
*format
.wBitsPerSample
/8;
920 format
.nAvgBytesPerSec
=format
.nSamplesPerSec
*format
.nBlockAlign
;
922 rc
=waveOutOpen(&wout
,ndev
+1,&format
,0,0,CALLBACK_NULL
);
923 ok(rc
==MMSYSERR_BADDEVICEID
,
924 "waveOutOpen(%s): MMSYSERR_BADDEVICEID expected, got %s\n",
925 dev_name(ndev
+1),mmsys_error(rc
));
928 wave_out_test_device(d
);
931 wave_out_test_device(WAVE_MAPPER
);