[REACTOS] Fix MSVC printf format warnings
[reactos.git] / drivers / wdm / audio / backpln / audio_test / audio_test.c
1 #define _UNICODE
2 #define UNICODE
3 #define WIN32_NO_STATUS
4 #define _KSDDK_
5
6 #include <windows.h>
7 #include <stdio.h>
8 #include <math.h>
9 #include <setupapi.h>
10 #include <ndk/umtypes.h>
11 #include <ks.h>
12 #include <ksmedia.h>
13 #include "interface.h"
14
15 #define _2pi 6.283185307179586476925286766559
16
17 GUID CategoryGuid = {STATIC_KSCATEGORY_AUDIO};
18
19 const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
20 const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
21 const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
22 const GUID KSPROPSETID_General = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
23 const GUID KSINTERFACESETID_Standard = {0x1A8766A0L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
24 const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
25 const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
26 const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
27 const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
28
29 VOID
30 TestKs()
31 {
32 SP_DEVICE_INTERFACE_DATA InterfaceData;
33 SP_DEVINFO_DATA DeviceData;
34 PSP_DEVICE_INTERFACE_DETAIL_DATA DetailData;
35 HDEVINFO DeviceHandle;
36 PKSDATAFORMAT_WAVEFORMATEX DataFormat;
37 PKSPIN_CONNECT PinConnect;
38 PKSSTREAM_HEADER Packet;
39 PKSPROPERTY Property;
40 KSSTATE State;
41 DWORD Length;
42 HANDLE FilterHandle;
43 HANDLE PinHandle;
44 PSHORT SoundBuffer;
45 UINT i = 0;
46 BOOL Result;
47 NTSTATUS Status;
48
49 //
50 // Get a handle to KS Audio Interfaces
51 //
52 DeviceHandle = SetupDiGetClassDevs(&CategoryGuid,
53 NULL,
54 NULL,
55 DIGCF_DEVICEINTERFACE); //DIGCF_PRESENT
56
57 printf("DeviceHandle %p\n", DeviceHandle);
58
59 //
60 // Enumerate the first interface
61 //
62 InterfaceData.cbSize = sizeof(InterfaceData);
63 InterfaceData.Reserved = 0;
64 Result = SetupDiEnumDeviceInterfaces(DeviceHandle,
65 NULL,
66 &CategoryGuid,
67 1,
68 &InterfaceData);
69
70 printf("SetupDiEnumDeviceInterfaces %u Error %ld\n", Result, GetLastError());
71
72 //
73 // Get the interface details (namely the device path)
74 //
75 Length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR);
76 DetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(),
77 0,
78 Length);
79 DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
80 DeviceData.cbSize = sizeof(DeviceData);
81 DeviceData.Reserved = 0;
82 Result = SetupDiGetDeviceInterfaceDetail(DeviceHandle,
83 &InterfaceData,
84 DetailData,
85 Length,
86 NULL,
87 &DeviceData);
88
89 wprintf(L"SetupDiGetDeviceInterfaceDetail %u Path DetailData %s\n", Result, (LPWSTR)&DetailData->DevicePath[0]);
90
91 //
92 // Open a handle to the device
93 //
94 FilterHandle = CreateFile(DetailData->DevicePath,
95 GENERIC_READ | GENERIC_WRITE,
96 0,
97 NULL,
98 OPEN_EXISTING,
99 FILE_ATTRIBUTE_NORMAL,
100 NULL);
101
102 printf("Handle %p\n", FilterHandle);
103
104 //
105 // Close the interface handle and clean up
106 //
107 SetupDiDestroyDeviceInfoList(DeviceHandle);
108
109 //
110 // Allocate a KS Pin Connection Request Structure
111 //
112 Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX);
113 printf("Length %ld KSPIN %Iu DATAFORMAT %Iu\n", Length, sizeof(KSPIN_CONNECT), sizeof(KSDATAFORMAT_WAVEFORMATEX));
114 PinConnect = (PKSPIN_CONNECT)HeapAlloc(GetProcessHeap(), 0, Length);
115 DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)(PinConnect + 1);
116
117 //
118 // Setup the KS Pin Data
119 //
120 PinConnect->Interface.Set = KSINTERFACESETID_Standard;
121 PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING;
122 PinConnect->Interface.Flags = 0;
123 PinConnect->Medium.Set = KSMEDIUMSETID_Standard;
124 PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;
125 PinConnect->Medium.Flags = 0;
126 PinConnect->PinId = 0;
127 PinConnect->PinToHandle = NULL;
128 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
129 PinConnect->Priority.PrioritySubClass = 1;
130
131 //
132 // Setup the KS Data Format Information
133 //
134 DataFormat->WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
135 DataFormat->WaveFormatEx.nChannels = 2;
136 DataFormat->WaveFormatEx.nSamplesPerSec = 48000;
137 DataFormat->WaveFormatEx.nBlockAlign = 4;
138 DataFormat->WaveFormatEx.nAvgBytesPerSec = 48000 * 4;
139 DataFormat->WaveFormatEx.wBitsPerSample = 16;
140 DataFormat->WaveFormatEx.cbSize = 0;
141 DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) +
142 sizeof(WAVEFORMATEX);
143 DataFormat->DataFormat.Flags = KSDATAFORMAT_ATTRIBUTES;
144 DataFormat->DataFormat.Reserved = 0;
145 DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
146 DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
147 DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
148 DataFormat->DataFormat.SampleSize = 4;
149
150 //
151 // Create the pin
152 //
153 Status = KsCreatePin(FilterHandle, PinConnect, GENERIC_WRITE, &PinHandle);
154
155 printf("PinHandle %p Status %lx\n", PinHandle, Status);
156
157 //
158 // Allocate a buffer for 1 second
159 //
160 Length = 48000 * 4;
161 SoundBuffer = (PSHORT)HeapAlloc(GetProcessHeap(), 0, Length);
162
163 //
164 // Fill the buffer with a 500 Hz sine tone
165 //
166 while (i < Length / 2)
167 {
168 //
169 // Generate the wave for each channel:
170 // Amplitude * sin( Sample * Frequency * 2PI / SamplesPerSecond )
171 //
172 SoundBuffer[i] = 0x7FFF * sin(0.5 * (i - 1) * 500 * _2pi / 48000);
173 i++;
174 SoundBuffer[i] = 0x7FFF * sin((0.5 * i - 2) * 500 * _2pi / 48000);
175 i++;
176 }
177
178 //
179 // Create and fill out the KS Stream Packet
180 //
181 Packet = (PKSSTREAM_HEADER)HeapAlloc(GetProcessHeap(),
182 HEAP_ZERO_MEMORY,
183 sizeof(KSSTREAM_HEADER));
184 Packet->Data = SoundBuffer;
185 Packet->FrameExtent = Length;
186 Packet->DataUsed = Length;
187 Packet->Size = sizeof(KSSTREAM_HEADER);
188 Packet->PresentationTime.Numerator = 1;
189 Packet->PresentationTime.Denominator = 1;
190
191 //
192 // Setup a KS Property to change the state
193 //
194 Property = (PKSPROPERTY)HeapAlloc(GetProcessHeap(), 0, sizeof(KSPROPERTY));
195 Property->Set = KSPROPSETID_Connection;
196 Property->Id = KSPROPERTY_CONNECTION_STATE;
197 Property->Flags = KSPROPERTY_TYPE_SET;
198
199 //
200 // Change the state to run
201 //
202 State = KSSTATE_RUN;
203 DeviceIoControl(PinHandle,
204 IOCTL_KS_PROPERTY,
205 Property,
206 sizeof(KSPROPERTY),
207 &State,
208 sizeof(State),
209 &Length,
210 NULL);
211
212 //
213 // Play our 1-second buffer
214 //
215 DeviceIoControl(PinHandle,
216 IOCTL_KS_WRITE_STREAM,
217 NULL,
218 0,
219 Packet,
220 Packet->Size,
221 &Length,
222 NULL);
223
224 //
225 // Change the state to stop
226 //
227 State = KSSTATE_STOP;
228 DeviceIoControl(PinHandle,
229 IOCTL_KS_PROPERTY,
230 Property,
231 sizeof(KSPROPERTY),
232 &State,
233 sizeof(State),
234 &Length,
235 NULL);
236
237 CloseHandle(PinHandle);
238 CloseHandle(FilterHandle);
239 }
240
241 int
242 __cdecl
243 main(int argc, char* argv[])
244 {
245 ULONG Length;
246 PSHORT SoundBuffer;
247 ULONG i = 0;
248 BOOL Status;
249 OVERLAPPED Overlapped;
250 DWORD BytesReturned;
251 HANDLE hWdmAud;
252 WDMAUD_DEVICE_INFO DeviceInfo;
253
254 TestKs();
255 return 0;
256
257 hWdmAud = CreateFileW(L"\\\\.\\wdmaud",
258 GENERIC_READ | GENERIC_WRITE,
259 0,
260 NULL,
261 OPEN_EXISTING,
262 FILE_FLAG_OVERLAPPED,
263 NULL);
264 if (!hWdmAud)
265 {
266 printf("Failed to open wdmaud with %lx\n", GetLastError());
267 return -1;
268 }
269
270 printf("WDMAUD: opened\n");
271
272 /* clear device info */
273 RtlZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
274
275 ZeroMemory(&Overlapped, sizeof(OVERLAPPED));
276 Overlapped.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
277
278 DeviceInfo.DeviceType = WAVE_OUT_DEVICE_TYPE;
279
280
281 Status = DeviceIoControl(hWdmAud, IOCTL_GETNUMDEVS_TYPE, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
282
283 if (!Status)
284 {
285 if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0)
286 {
287 printf("Failed to get num of wave out devices with %lx\n", GetLastError());
288 CloseHandle(hWdmAud);
289 return -1;
290 }
291 }
292
293 printf("WDMAUD: Num Devices %lu\n", DeviceInfo.DeviceCount);
294
295 if (!DeviceInfo.DeviceCount)
296 {
297 CloseHandle(hWdmAud);
298 return 0;
299 }
300
301 Status = DeviceIoControl(hWdmAud, IOCTL_GETCAPABILITIES, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
302
303 if (!Status)
304 {
305 if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0)
306 {
307 printf("Failed to get iocaps %lx\n", GetLastError());
308 }
309 }
310 printf("WDMAUD: Capabilities NumChannels %x dwFormats %lx\n", DeviceInfo.u.WaveOutCaps.wChannels, DeviceInfo.u.WaveOutCaps.dwFormats);
311
312 DeviceInfo.u.WaveFormatEx.cbSize = sizeof(WAVEFORMATEX);
313 DeviceInfo.u.WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
314 DeviceInfo.u.WaveFormatEx.nChannels = 2;
315 DeviceInfo.u.WaveFormatEx.nSamplesPerSec = 48000;
316 DeviceInfo.u.WaveFormatEx.nBlockAlign = 4;
317 DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = 48000 * 4;
318 DeviceInfo.u.WaveFormatEx.wBitsPerSample = 16;
319
320
321
322 Status = DeviceIoControl(hWdmAud, IOCTL_OPEN_WDMAUD, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
323 if (!Status)
324 {
325 if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0)
326 {
327 printf("Failed to open device with %lx\n", GetLastError());
328 CloseHandle(hWdmAud);
329 return -1;
330 }
331 }
332
333 printf("WDMAUD: opened device\n");
334
335 //
336 // Allocate a buffer for 1 second
337 //
338 Length = 48000 * 4;
339 SoundBuffer = (PSHORT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
340
341 //
342 // Fill the buffer with a 500 Hz sine tone
343 //
344 while (i < Length / 2)
345 {
346 //
347 // Generate the wave for each channel:
348 // Amplitude * sin( Sample * Frequency * 2PI / SamplesPerSecond )
349 //
350 SoundBuffer[i] = 0x7FFF * sin(0.5 * (i - 1) * 500 * _2pi / 48000);
351 i++;
352 SoundBuffer[i] = 0x7FFF * sin((0.5 * i - 2) * 500 * _2pi / 48000);
353 i++;
354 }
355
356 DeviceInfo.u.State = KSSTATE_RUN;
357 Status = DeviceIoControl(hWdmAud, IOCTL_SETDEVICE_STATE, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
358 if (!Status)
359 {
360 if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0)
361 {
362 printf("Failed to set device into run state %lx\n", GetLastError());
363 CloseHandle(hWdmAud);
364 return -1;
365 }
366 }
367
368 //
369 // Play our 1-second buffer
370 //
371 DeviceInfo.Header.Data = (PUCHAR)SoundBuffer;
372 DeviceInfo.Header.DataUsed = DeviceInfo.Header.FrameExtent = Length;
373 Status = DeviceIoControl(hWdmAud, IOCTL_WRITEDATA, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
374 if (!Status)
375 {
376 if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0)
377 {
378 printf("Failed to play buffer %lx\n", GetLastError());
379 CloseHandle(hWdmAud);
380 return -1;
381 }
382 }
383
384 printf("WDMAUD: Played buffer\n");
385
386 DeviceInfo.u.State = KSSTATE_STOP;
387 Status = DeviceIoControl(hWdmAud, IOCTL_SETDEVICE_STATE, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped);
388 if (!Status)
389 {
390 if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0)
391 {
392 printf("Failed to set device into stop state %lx\n", GetLastError());
393 CloseHandle(hWdmAud);
394 return -1;
395 }
396 }
397 printf("WDMAUD: STOPPED\n");
398 CloseHandle(&Overlapped.hEvent);
399 CloseHandle(hWdmAud);
400 printf("WDMAUD: COMPLETE\n");
401 return 0;
402 }