ok() does not support '%S'. Store the Ansi version, convert to Unicode
[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 <stdlib.h>
22 #include <math.h>
23
24 #include "wine/test.h"
25 #include "winbase.h"
26 #include "mmsystem.h"
27
28 /*
29  * Note that in most of this test we may get MMSYSERR_BADDEVICEID errors
30  * at about any time if the user starts another application that uses the
31  * sound device. So we should not report these as test failures.
32  *
33  * This test can play a test tone. But this only makes sense if someone
34  * is going to carefully listen to it, and would only bother everyone else.
35  * So this is only done if the test is being run in interactive mode.
36  */
37
38 static const unsigned int win_formats[][4]={
39     {WAVE_FORMAT_1M08,  11025,  8, 1},
40     {WAVE_FORMAT_1S08,  11025,  8, 2},
41     {WAVE_FORMAT_1M16,  11025, 16, 1},
42     {WAVE_FORMAT_1S16,  11025, 16, 2},
43     {WAVE_FORMAT_2M08,  22050,  8, 1},
44     {WAVE_FORMAT_2S08,  22050,  8, 2},
45     {WAVE_FORMAT_2M16,  22050, 16, 1},
46     {WAVE_FORMAT_2S16,  22050, 16, 2},
47     {WAVE_FORMAT_4M08,  44100,  8, 1},
48     {WAVE_FORMAT_4S08,  44100,  8, 2},
49     {WAVE_FORMAT_4M16,  44100, 16, 1},
50     {WAVE_FORMAT_4S16,  44100, 16, 2},
51 #ifdef WAVE_FORMAT_48M08
52     {WAVE_FORMAT_48M08, 48000,  8, 1},
53     {WAVE_FORMAT_48S08, 48000,  8, 2},
54     {WAVE_FORMAT_48M16, 48000, 16, 1},
55     {WAVE_FORMAT_48S16, 48000, 16, 2},
56     {WAVE_FORMAT_96M08, 96000,  8, 1},
57     {WAVE_FORMAT_96S08, 96000,  8, 2},
58     {WAVE_FORMAT_96M16, 96000, 16, 1},
59     {WAVE_FORMAT_96S16, 96000, 16, 2}
60 #endif
61 };
62 #define NB_WIN_FORMATS (sizeof(win_formats)/sizeof(*win_formats))
63
64 #define PI 3.14159265358979323846
65 static char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size)
66 {
67     int i;
68     int nb_samples;
69     char* buf;
70     char* b;
71
72     nb_samples=(int)(duration*wfx->nSamplesPerSec);
73     *size=nb_samples*wfx->nBlockAlign;
74     b=buf=malloc(*size);
75     for (i=0;i<nb_samples;i++) {
76         double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec);
77         if (wfx->wBitsPerSample==8) {
78             unsigned char sample=(unsigned char)((double)127.5*(y+1.0));
79             *b++=sample;
80             if (wfx->nChannels==2)
81                *b++=sample;
82         } else {
83             signed short sample=(signed short)((double)32767.5*y-0.5);
84             b[0]=sample & 0xff;
85             b[1]=sample >> 8;
86             b+=2;
87             if (wfx->nChannels==2) {
88                 b[0]=sample & 0xff;
89                 b[1]=sample >> 8;
90                 b+=2;
91             }
92         }
93     }
94     return buf;
95 }
96
97 static void wave_out_test_deviceOut(int device, int format, DWORD flags)
98 {
99     WAVEFORMATEX wfx;
100     HWAVEOUT wout;
101     HANDLE hevent;
102     WAVEHDR frag;
103     MMRESULT rc;
104     DWORD volume;
105
106     hevent=CreateEvent(NULL,FALSE,FALSE,NULL);
107     ok(hevent!=NULL,"CreateEvent: error=%ld\n",GetLastError());
108     if (hevent==NULL)
109         return;
110
111     wfx.wFormatTag=WAVE_FORMAT_PCM;
112     wfx.nChannels=win_formats[format][3];
113     wfx.wBitsPerSample=win_formats[format][2];
114     wfx.nSamplesPerSec=win_formats[format][1];
115     wfx.nBlockAlign=wfx.nChannels*wfx.wBitsPerSample/8;
116     wfx.nAvgBytesPerSec=wfx.nSamplesPerSec*wfx.nBlockAlign;
117     wfx.cbSize=0;
118
119     wout=NULL;
120     rc=waveOutOpen(&wout,device,&wfx,(DWORD)hevent,0,CALLBACK_EVENT|flags);
121     /* Note: Win9x doesn't know WAVE_FORMAT_DIRECT */
122     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
123        (rc==MMSYSERR_INVALFLAG && (flags & WAVE_FORMAT_DIRECT)),
124        "waveOutOpen: device=%d rc=%d",device,rc);
125     if (rc!=MMSYSERR_NOERROR) {
126         CloseHandle(hevent);
127         return;
128     }
129
130     ok(wfx.nChannels==win_formats[format][3] &&
131        wfx.wBitsPerSample==win_formats[format][2] &&
132        wfx.nSamplesPerSec==win_formats[format][1],
133        "got the wrong format: %ldx%2dx%d instead of %dx%2dx%d\n",
134        wfx.nSamplesPerSec, wfx.wBitsPerSample,
135        wfx.nChannels, win_formats[format][1], win_formats[format][2],
136        win_formats[format][3]);
137
138     frag.lpData=wave_generate_la(&wfx,1.0,&frag.dwBufferLength);
139     frag.dwFlags=0;
140     frag.dwLoops=0;
141
142     rc=waveOutGetVolume(wout,&volume);
143     ok(rc==MMSYSERR_NOERROR,"waveOutGetVolume: device=%d rc=%d\n",device,rc);
144
145     rc=waveOutPrepareHeader(wout, &frag, sizeof(frag));
146     ok(rc==MMSYSERR_NOERROR,
147        "waveOutPrepareHeader: device=%d rc=%d\n",device,rc);
148
149     if (winetest_interactive && rc==MMSYSERR_NOERROR) {
150         trace("Playing 440Hz LA at %ldx%2dx%d %04lx\n",
151               wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels,flags);
152         rc=waveOutSetVolume(wout,0x20002000);
153         ok(rc==MMSYSERR_NOERROR,"waveOutSetVolume: device=%d rc=%d\n",device,rc);
154         WaitForSingleObject(hevent,INFINITE);
155
156         rc=waveOutWrite(wout, &frag, sizeof(frag));
157         ok(rc==MMSYSERR_NOERROR,"waveOutWrite: device=%d rc=%d\n",device,rc);
158         WaitForSingleObject(hevent,INFINITE);
159
160         rc=waveOutSetVolume(wout,volume);
161         ok(rc==MMSYSERR_NOERROR,"waveOutSetVolume: device=%d rc=%d\n",device,rc);
162     }
163
164     rc=waveOutUnprepareHeader(wout, &frag, sizeof(frag));
165     ok(rc==MMSYSERR_NOERROR,
166        "waveOutUnprepareHeader: device=%d rc=%d\n",device,rc);
167     free(frag.lpData);
168
169     CloseHandle(hevent);
170     waveOutClose(wout);
171 }
172
173 static void wave_out_tests()
174 {
175     WAVEOUTCAPS caps;
176     WAVEFORMATEX format;
177     HWAVEOUT wout;
178     MMRESULT rc;
179     UINT ndev,d,f;
180
181     ndev=waveOutGetNumDevs();
182     trace("found %d WaveOut devices\n",ndev);
183
184     rc=waveOutGetDevCapsA(ndev+1,&caps,sizeof(caps));
185     ok(rc==MMSYSERR_BADDEVICEID,
186        "waveOutGetDevCa psA: MMSYSERR_BADDEVICEID expected, got %d",rc);
187
188     format.wFormatTag=WAVE_FORMAT_PCM;
189     format.nChannels=2;
190     format.wBitsPerSample=16;
191     format.nSamplesPerSec=44100;
192     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
193     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
194     format.cbSize=0;
195     rc=waveOutOpen(&wout,ndev+1,&format,0,0,CALLBACK_NULL);
196     ok(rc==MMSYSERR_BADDEVICEID,
197        "waveOutOpen: MMSYSERR_BADDEVICEID expected, got %d",rc);
198
199     for (d=0;d<ndev;d++) {
200         rc=waveOutGetDevCapsA(d,&caps,sizeof(caps));
201         ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID,
202            "failed to get capabilities of device %d: rc=%d",d,rc);
203         if (rc==MMSYSERR_BADDEVICEID)
204             continue;
205
206         trace("  %d: \"%s\" %d.%d (%d:%d): channels=%d formats=%04lx support=%04lx\n",
207               d,caps.szPname,caps.vDriverVersion >> 8,
208               caps.vDriverVersion & 0xff,
209               caps.wMid,caps.wPid,
210               caps.wChannels,caps.dwFormats,caps.dwSupport);
211
212         for (f=0;f<NB_WIN_FORMATS;f++) {
213             if (caps.dwFormats & win_formats[f][0]) {
214                 wave_out_test_deviceOut(d,f,0);
215                 wave_out_test_deviceOut(d,f,WAVE_FORMAT_DIRECT);
216             }
217         }
218
219         /* Try an invalid format to test error handling */
220         trace("Testing invalid 2MHz format\n");
221         format.wFormatTag=WAVE_FORMAT_PCM;
222         format.nChannels=2;
223         format.wBitsPerSample=16;
224         format.nSamplesPerSec=2000000; /* 2MHz! */
225         format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
226         format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
227         format.cbSize=0;
228         rc=waveOutOpen(&wout,d,&format,0,0,CALLBACK_NULL);
229         ok(rc==WAVERR_BADFORMAT,
230            "opening the device at 2MHz should fail %d: rc=%d",d,rc);
231         if (rc==MMSYSERR_NOERROR) {
232             trace("     got %ldx%2dx%d for %dx%2dx%d\n",
233                   format.nSamplesPerSec, format.wBitsPerSample,
234                   format.nChannels,
235                   win_formats[f][1], win_formats[f][2],
236                   win_formats[f][3]);
237             waveOutClose(wout);
238         }
239
240         format.wFormatTag=WAVE_FORMAT_PCM;
241         format.nChannels=2;
242         format.wBitsPerSample=16;
243         format.nSamplesPerSec=2000000; /* 2MHz! */
244         format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
245         format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
246         format.cbSize=0;
247         rc=waveOutOpen(&wout,d,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
248         ok(rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG,
249            "opening the device at 2MHz should fail %d: rc=%d",d,rc);
250         if (rc==MMSYSERR_NOERROR) {
251             trace("     got %ldx%2dx%d for %dx%2dx%d\n",
252                   format.nSamplesPerSec, format.wBitsPerSample,
253                   format.nChannels,
254                   win_formats[f][1], win_formats[f][2],
255                   win_formats[f][3]);
256             waveOutClose(wout);
257         }
258     }
259 }
260
261 START_TEST(wave)
262 {
263     wave_out_tests();
264 }