[AUDIO-BRINGUP]
[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 <mmsystem.h>
8 #include <stdio.h>
9 #include <math.h>
10 #include <setupapi.h>
11 #include <ndk/ntndk.h>
12 #include <ks.h>
13 #include <ksmedia.h>
14
15 #define _2pi 6.283185307179586476925286766559
16
17
18
19 #include <ks.h>
20
21
22 GUID CategoryGuid = {STATIC_KSCATEGORY_AUDIO};
23
24
25 const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
26 const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
27 const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
28 const GUID KSPROPSETID_General = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
29 const GUID KSINTERFACESETID_Standard = {0x1A8766A0L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
30 const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
31 const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
32 const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
33 const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
34
35
36 VOID
37 TestKs()
38 {
39 SP_DEVICE_INTERFACE_DATA InterfaceData;
40 SP_DEVINFO_DATA DeviceData;
41 PSP_DEVICE_INTERFACE_DETAIL_DATA DetailData;
42 HDEVINFO DeviceHandle;
43 PKSDATAFORMAT_WAVEFORMATEX DataFormat;
44 PKSPIN_CONNECT PinConnect;
45 PKSSTREAM_HEADER Packet;
46 PKSPROPERTY Property;
47 KSSTATE State;
48 DWORD Length;
49 HANDLE FilterHandle;
50 HANDLE PinHandle;
51 PSHORT SoundBuffer;
52 UINT i = 0;
53 BOOL Result;
54 NTSTATUS Status;
55
56 //
57 // Get a handle to KS Audio Interfaces
58 //
59 DeviceHandle = SetupDiGetClassDevs(&CategoryGuid,
60 NULL,
61 NULL,
62 DIGCF_DEVICEINTERFACE); //DIGCF_PRESENT
63
64 printf("DeviceHandle %p\n", DeviceHandle);
65
66 //
67 // Enumerate the first interface
68 //
69 InterfaceData.cbSize = sizeof(InterfaceData);
70 InterfaceData.Reserved = 0;
71 Result = SetupDiEnumDeviceInterfaces(DeviceHandle,
72 NULL,
73 &CategoryGuid,
74 1,
75 &InterfaceData);
76
77 printf("SetupDiEnumDeviceInterfaces %u Error %ld\n", Result, GetLastError());
78
79 //
80 // Get the interface details (namely the device path)
81 //
82 Length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR);
83 DetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(),
84 0,
85 Length);
86 DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
87 DeviceData.cbSize = sizeof(DeviceData);
88 DeviceData.Reserved = 0;
89 Result = SetupDiGetDeviceInterfaceDetail(DeviceHandle,
90 &InterfaceData,
91 DetailData,
92 Length,
93 NULL,
94 &DeviceData);
95
96 wprintf(L"SetupDiGetDeviceInterfaceDetail %u Path DetailData %s\n", Result, (LPWSTR)&DetailData->DevicePath[0]);
97
98 //
99 // Open a handle to the device
100 //
101 FilterHandle = CreateFile(DetailData->DevicePath,
102 GENERIC_READ | GENERIC_WRITE,
103 0,
104 NULL,
105 OPEN_EXISTING,
106 FILE_ATTRIBUTE_NORMAL,
107 NULL);
108
109 printf("Handle %p\n", FilterHandle);
110
111 //
112 // Close the interface handle and clean up
113 //
114 SetupDiDestroyDeviceInfoList(DeviceHandle);
115
116 //
117 // Allocate a KS Pin Connection Request Structure
118 //
119 Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX);
120 printf("Length %ld KSPIN %u DATAFORMAT %u\n", Length, sizeof(KSPIN_CONNECT), sizeof(KSDATAFORMAT_WAVEFORMATEX));
121 PinConnect = (PKSPIN_CONNECT)HeapAlloc(GetProcessHeap(), 0, Length);
122 DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)(PinConnect + 1);
123
124 //
125 // Setup the KS Pin Data
126 //
127 PinConnect->Interface.Set = KSINTERFACESETID_Standard;
128 PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING;
129 PinConnect->Interface.Flags = 0;
130 PinConnect->Medium.Set = KSMEDIUMSETID_Standard;
131 PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;
132 PinConnect->Medium.Flags = 0;
133 PinConnect->PinId = 0;
134 PinConnect->PinToHandle = NULL;
135 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
136 PinConnect->Priority.PrioritySubClass = 1;
137
138 //
139 // Setup the KS Data Format Information
140 //
141 DataFormat->WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
142 DataFormat->WaveFormatEx.nChannels = 2;
143 DataFormat->WaveFormatEx.nSamplesPerSec = 48000;
144 DataFormat->WaveFormatEx.nBlockAlign = 4;
145 DataFormat->WaveFormatEx.nAvgBytesPerSec = 48000 * 4;
146 DataFormat->WaveFormatEx.wBitsPerSample = 16;
147 DataFormat->WaveFormatEx.cbSize = 0;
148 DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) +
149 sizeof(WAVEFORMATEX);
150 DataFormat->DataFormat.Flags = KSDATAFORMAT_ATTRIBUTES;
151 DataFormat->DataFormat.Reserved = 0;
152 DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
153 DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
154 DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
155 DataFormat->DataFormat.SampleSize = 4;
156
157 //
158 // Create the pin
159 //
160 Status = KsCreatePin(FilterHandle, PinConnect, GENERIC_WRITE, &PinHandle);
161
162 printf("PinHandle %p Status %lx\n", PinHandle, Status);
163
164 //
165 // Allocate a buffer for 1 second
166 //
167 Length = 48000 * 4;
168 SoundBuffer = (PSHORT)HeapAlloc(GetProcessHeap(), 0, Length);
169
170 //
171 // Fill the buffer with a 500 Hz sine tone
172 //
173 while (i < Length / 2)
174 {
175 //
176 // Generate the wave for each channel:
177 // Amplitude * sin( Sample * Frequency * 2PI / SamplesPerSecond )
178 //
179 SoundBuffer[i] = 0x7FFF * sin(0.5 * (i - 1) * 500 * _2pi / 48000);
180 i++;
181 SoundBuffer[i] = 0x7FFF * sin((0.5 * i - 2) * 500 * _2pi / 48000);
182 i++;
183 }
184
185 //
186 // Create and fill out the KS Stream Packet
187 //
188 Packet = (PKSSTREAM_HEADER)HeapAlloc(GetProcessHeap(),
189 HEAP_ZERO_MEMORY,
190 sizeof(KSSTREAM_HEADER));
191 Packet->Data = SoundBuffer;
192 Packet->FrameExtent = Length;
193 Packet->DataUsed = Length;
194 Packet->Size = sizeof(KSSTREAM_HEADER);
195 Packet->PresentationTime.Numerator = 1;
196 Packet->PresentationTime.Denominator = 1;
197
198 //
199 // Setup a KS Property to change the state
200 //
201 Property = (PKSPROPERTY)HeapAlloc(GetProcessHeap(), 0, sizeof(KSPROPERTY));
202 Property->Set = KSPROPSETID_Connection;
203 Property->Id = KSPROPERTY_CONNECTION_STATE;
204 Property->Flags = KSPROPERTY_TYPE_SET;
205
206 //
207 // Change the state to run
208 //
209 State = KSSTATE_RUN;
210 DeviceIoControl(PinHandle,
211 IOCTL_KS_PROPERTY,
212 Property,
213 sizeof(KSPROPERTY),
214 &State,
215 sizeof(State),
216 &Length,
217 NULL);
218
219 //
220 // Play our 1-second buffer
221 //
222 DeviceIoControl(PinHandle,
223 IOCTL_KS_WRITE_STREAM,
224 NULL,
225 0,
226 Packet,
227 Packet->Size,
228 &Length,
229 NULL);
230
231 //
232 // Change the state to stop
233 //
234 State = KSSTATE_STOP;
235 DeviceIoControl(PinHandle,
236 IOCTL_KS_PROPERTY,
237 Property,
238 sizeof(KSPROPERTY),
239 &State,
240 sizeof(State),
241 &Length,
242 NULL);
243
244 CloseHandle(PinHandle);
245 CloseHandle(FilterHandle);
246 }
247
248 int
249 __cdecl
250 main(int argc, char* argv[])
251 {
252 TestKs();
253 return 0;
254 }