Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenaudio_test.c
Go to the documentation of this file.
00001 #define _UNICODE 00002 #define UNICODE 00003 #define WIN32_NO_STATUS 00004 #define _KSDDK_ 00005 00006 #include <windows.h> 00007 #include <stdio.h> 00008 #include <math.h> 00009 #include <setupapi.h> 00010 #include <ndk/umtypes.h> 00011 #include <ksmedia.h> 00012 #include "interface.h" 00013 00014 #define _2pi 6.283185307179586476925286766559 00015 00016 GUID CategoryGuid = {STATIC_KSCATEGORY_AUDIO}; 00017 00018 const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}}; 00019 const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 00020 const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}}; 00021 const GUID KSPROPSETID_General = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 00022 const GUID KSINTERFACESETID_Standard = {0x1A8766A0L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 00023 const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 00024 const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; 00025 const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; 00026 const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}}; 00027 00028 VOID 00029 TestKs() 00030 { 00031 SP_DEVICE_INTERFACE_DATA InterfaceData; 00032 SP_DEVINFO_DATA DeviceData; 00033 PSP_DEVICE_INTERFACE_DETAIL_DATA DetailData; 00034 HDEVINFO DeviceHandle; 00035 PKSDATAFORMAT_WAVEFORMATEX DataFormat; 00036 PKSPIN_CONNECT PinConnect; 00037 PKSSTREAM_HEADER Packet; 00038 PKSPROPERTY Property; 00039 KSSTATE State; 00040 DWORD Length; 00041 HANDLE FilterHandle; 00042 HANDLE PinHandle; 00043 PSHORT SoundBuffer; 00044 UINT i = 0; 00045 BOOL Result; 00046 NTSTATUS Status; 00047 00048 // 00049 // Get a handle to KS Audio Interfaces 00050 // 00051 DeviceHandle = SetupDiGetClassDevs(&CategoryGuid, 00052 NULL, 00053 NULL, 00054 DIGCF_DEVICEINTERFACE); //DIGCF_PRESENT 00055 00056 printf("DeviceHandle %p\n", DeviceHandle); 00057 00058 // 00059 // Enumerate the first interface 00060 // 00061 InterfaceData.cbSize = sizeof(InterfaceData); 00062 InterfaceData.Reserved = 0; 00063 Result = SetupDiEnumDeviceInterfaces(DeviceHandle, 00064 NULL, 00065 &CategoryGuid, 00066 1, 00067 &InterfaceData); 00068 00069 printf("SetupDiEnumDeviceInterfaces %u Error %ld\n", Result, GetLastError()); 00070 00071 // 00072 // Get the interface details (namely the device path) 00073 // 00074 Length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR); 00075 DetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(), 00076 0, 00077 Length); 00078 DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 00079 DeviceData.cbSize = sizeof(DeviceData); 00080 DeviceData.Reserved = 0; 00081 Result = SetupDiGetDeviceInterfaceDetail(DeviceHandle, 00082 &InterfaceData, 00083 DetailData, 00084 Length, 00085 NULL, 00086 &DeviceData); 00087 00088 wprintf(L"SetupDiGetDeviceInterfaceDetail %u Path DetailData %s\n", Result, (LPWSTR)&DetailData->DevicePath[0]); 00089 00090 // 00091 // Open a handle to the device 00092 // 00093 FilterHandle = CreateFile(DetailData->DevicePath, 00094 GENERIC_READ | GENERIC_WRITE, 00095 0, 00096 NULL, 00097 OPEN_EXISTING, 00098 FILE_ATTRIBUTE_NORMAL, 00099 NULL); 00100 00101 printf("Handle %p\n", FilterHandle); 00102 00103 // 00104 // Close the interface handle and clean up 00105 // 00106 SetupDiDestroyDeviceInfoList(DeviceHandle); 00107 00108 // 00109 // Allocate a KS Pin Connection Request Structure 00110 // 00111 Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX); 00112 printf("Length %ld KSPIN %u DATAFORMAT %u\n", Length, sizeof(KSPIN_CONNECT), sizeof(KSDATAFORMAT_WAVEFORMATEX)); 00113 PinConnect = (PKSPIN_CONNECT)HeapAlloc(GetProcessHeap(), 0, Length); 00114 DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)(PinConnect + 1); 00115 00116 // 00117 // Setup the KS Pin Data 00118 // 00119 PinConnect->Interface.Set = KSINTERFACESETID_Standard; 00120 PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING; 00121 PinConnect->Interface.Flags = 0; 00122 PinConnect->Medium.Set = KSMEDIUMSETID_Standard; 00123 PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE; 00124 PinConnect->Medium.Flags = 0; 00125 PinConnect->PinId = 0; 00126 PinConnect->PinToHandle = NULL; 00127 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; 00128 PinConnect->Priority.PrioritySubClass = 1; 00129 00130 // 00131 // Setup the KS Data Format Information 00132 // 00133 DataFormat->WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM; 00134 DataFormat->WaveFormatEx.nChannels = 2; 00135 DataFormat->WaveFormatEx.nSamplesPerSec = 48000; 00136 DataFormat->WaveFormatEx.nBlockAlign = 4; 00137 DataFormat->WaveFormatEx.nAvgBytesPerSec = 48000 * 4; 00138 DataFormat->WaveFormatEx.wBitsPerSample = 16; 00139 DataFormat->WaveFormatEx.cbSize = 0; 00140 DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + 00141 sizeof(WAVEFORMATEX); 00142 DataFormat->DataFormat.Flags = KSDATAFORMAT_ATTRIBUTES; 00143 DataFormat->DataFormat.Reserved = 0; 00144 DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; 00145 DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; 00146 DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; 00147 DataFormat->DataFormat.SampleSize = 4; 00148 00149 // 00150 // Create the pin 00151 // 00152 Status = KsCreatePin(FilterHandle, PinConnect, GENERIC_WRITE, &PinHandle); 00153 00154 printf("PinHandle %p Status %lx\n", PinHandle, Status); 00155 00156 // 00157 // Allocate a buffer for 1 second 00158 // 00159 Length = 48000 * 4; 00160 SoundBuffer = (PSHORT)HeapAlloc(GetProcessHeap(), 0, Length); 00161 00162 // 00163 // Fill the buffer with a 500 Hz sine tone 00164 // 00165 while (i < Length / 2) 00166 { 00167 // 00168 // Generate the wave for each channel: 00169 // Amplitude * sin( Sample * Frequency * 2PI / SamplesPerSecond ) 00170 // 00171 SoundBuffer[i] = 0x7FFF * sin(0.5 * (i - 1) * 500 * _2pi / 48000); 00172 i++; 00173 SoundBuffer[i] = 0x7FFF * sin((0.5 * i - 2) * 500 * _2pi / 48000); 00174 i++; 00175 } 00176 00177 // 00178 // Create and fill out the KS Stream Packet 00179 // 00180 Packet = (PKSSTREAM_HEADER)HeapAlloc(GetProcessHeap(), 00181 HEAP_ZERO_MEMORY, 00182 sizeof(KSSTREAM_HEADER)); 00183 Packet->Data = SoundBuffer; 00184 Packet->FrameExtent = Length; 00185 Packet->DataUsed = Length; 00186 Packet->Size = sizeof(KSSTREAM_HEADER); 00187 Packet->PresentationTime.Numerator = 1; 00188 Packet->PresentationTime.Denominator = 1; 00189 00190 // 00191 // Setup a KS Property to change the state 00192 // 00193 Property = (PKSPROPERTY)HeapAlloc(GetProcessHeap(), 0, sizeof(KSPROPERTY)); 00194 Property->Set = KSPROPSETID_Connection; 00195 Property->Id = KSPROPERTY_CONNECTION_STATE; 00196 Property->Flags = KSPROPERTY_TYPE_SET; 00197 00198 // 00199 // Change the state to run 00200 // 00201 State = KSSTATE_RUN; 00202 DeviceIoControl(PinHandle, 00203 IOCTL_KS_PROPERTY, 00204 Property, 00205 sizeof(KSPROPERTY), 00206 &State, 00207 sizeof(State), 00208 &Length, 00209 NULL); 00210 00211 // 00212 // Play our 1-second buffer 00213 // 00214 DeviceIoControl(PinHandle, 00215 IOCTL_KS_WRITE_STREAM, 00216 NULL, 00217 0, 00218 Packet, 00219 Packet->Size, 00220 &Length, 00221 NULL); 00222 00223 // 00224 // Change the state to stop 00225 // 00226 State = KSSTATE_STOP; 00227 DeviceIoControl(PinHandle, 00228 IOCTL_KS_PROPERTY, 00229 Property, 00230 sizeof(KSPROPERTY), 00231 &State, 00232 sizeof(State), 00233 &Length, 00234 NULL); 00235 00236 CloseHandle(PinHandle); 00237 CloseHandle(FilterHandle); 00238 } 00239 00240 int 00241 __cdecl 00242 main(int argc, char* argv[]) 00243 { 00244 ULONG Length; 00245 PSHORT SoundBuffer; 00246 ULONG i = 0; 00247 BOOL Status; 00248 OVERLAPPED Overlapped; 00249 DWORD BytesReturned; 00250 HANDLE hWdmAud; 00251 WDMAUD_DEVICE_INFO DeviceInfo; 00252 00253 TestKs(); 00254 return 0; 00255 00256 hWdmAud = CreateFileW(L"\\\\.\\wdmaud", 00257 GENERIC_READ | GENERIC_WRITE, 00258 0, 00259 NULL, 00260 OPEN_EXISTING, 00261 FILE_FLAG_OVERLAPPED, 00262 NULL); 00263 if (!hWdmAud) 00264 { 00265 printf("Failed to open wdmaud with %lx\n", GetLastError()); 00266 return -1; 00267 } 00268 00269 printf("WDMAUD: opened\n"); 00270 00271 /* clear device info */ 00272 RtlZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); 00273 00274 ZeroMemory(&Overlapped, sizeof(OVERLAPPED)); 00275 Overlapped.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); 00276 00277 DeviceInfo.DeviceType = WAVE_OUT_DEVICE_TYPE; 00278 00279 00280 Status = DeviceIoControl(hWdmAud, IOCTL_GETNUMDEVS_TYPE, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped); 00281 00282 if (!Status) 00283 { 00284 if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0) 00285 { 00286 printf("Failed to get num of wave out devices with %lx\n", GetLastError()); 00287 CloseHandle(hWdmAud); 00288 return -1; 00289 } 00290 } 00291 00292 printf("WDMAUD: Num Devices %lu\n", DeviceInfo.DeviceCount); 00293 00294 if (!DeviceInfo.DeviceCount) 00295 { 00296 CloseHandle(hWdmAud); 00297 return 0; 00298 } 00299 00300 Status = DeviceIoControl(hWdmAud, IOCTL_GETCAPABILITIES, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped); 00301 00302 if (!Status) 00303 { 00304 if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0) 00305 { 00306 printf("Failed to get iocaps %lx\n", GetLastError()); 00307 } 00308 } 00309 printf("WDMAUD: Capabilites NumChannels %x dwFormats %lx\n", DeviceInfo.u.WaveOutCaps.wChannels, DeviceInfo.u.WaveOutCaps.dwFormats); 00310 00311 DeviceInfo.u.WaveFormatEx.cbSize = sizeof(WAVEFORMATEX); 00312 DeviceInfo.u.WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM; 00313 DeviceInfo.u.WaveFormatEx.nChannels = 2; 00314 DeviceInfo.u.WaveFormatEx.nSamplesPerSec = 48000; 00315 DeviceInfo.u.WaveFormatEx.nBlockAlign = 4; 00316 DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = 48000 * 4; 00317 DeviceInfo.u.WaveFormatEx.wBitsPerSample = 16; 00318 00319 00320 00321 Status = DeviceIoControl(hWdmAud, IOCTL_OPEN_WDMAUD, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped); 00322 if (!Status) 00323 { 00324 if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0) 00325 { 00326 printf("Failed to open device with %lx\n", GetLastError()); 00327 CloseHandle(hWdmAud); 00328 return -1; 00329 } 00330 } 00331 00332 printf("WDMAUD: opened device\n"); 00333 00334 // 00335 // Allocate a buffer for 1 second 00336 // 00337 Length = 48000 * 4; 00338 SoundBuffer = (PSHORT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length); 00339 00340 // 00341 // Fill the buffer with a 500 Hz sine tone 00342 // 00343 while (i < Length / 2) 00344 { 00345 // 00346 // Generate the wave for each channel: 00347 // Amplitude * sin( Sample * Frequency * 2PI / SamplesPerSecond ) 00348 // 00349 SoundBuffer[i] = 0x7FFF * sin(0.5 * (i - 1) * 500 * _2pi / 48000); 00350 i++; 00351 SoundBuffer[i] = 0x7FFF * sin((0.5 * i - 2) * 500 * _2pi / 48000); 00352 i++; 00353 } 00354 00355 DeviceInfo.u.State = KSSTATE_RUN; 00356 Status = DeviceIoControl(hWdmAud, IOCTL_SETDEVICE_STATE, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped); 00357 if (!Status) 00358 { 00359 if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0) 00360 { 00361 printf("Failed to set device into run state %lx\n", GetLastError()); 00362 CloseHandle(hWdmAud); 00363 return -1; 00364 } 00365 } 00366 00367 // 00368 // Play our 1-second buffer 00369 // 00370 DeviceInfo.Header.Data = (PUCHAR)SoundBuffer; 00371 DeviceInfo.Header.DataUsed = DeviceInfo.Header.FrameExtent = Length; 00372 Status = DeviceIoControl(hWdmAud, IOCTL_WRITEDATA, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped); 00373 if (!Status) 00374 { 00375 if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0) 00376 { 00377 printf("Failed to play buffer %lx\n", GetLastError()); 00378 CloseHandle(hWdmAud); 00379 return -1; 00380 } 00381 } 00382 00383 printf("WDMAUD: Played buffer\n"); 00384 00385 DeviceInfo.u.State = KSSTATE_STOP; 00386 Status = DeviceIoControl(hWdmAud, IOCTL_SETDEVICE_STATE, (LPVOID)&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), &BytesReturned, &Overlapped); 00387 if (!Status) 00388 { 00389 if (WaitForSingleObject(&Overlapped.hEvent, 5000) != WAIT_OBJECT_0) 00390 { 00391 printf("Failed to set device into stop state %lx\n", GetLastError()); 00392 CloseHandle(hWdmAud); 00393 return -1; 00394 } 00395 } 00396 printf("WDMAUD: STOPPED\n"); 00397 CloseHandle(&Overlapped.hEvent); 00398 CloseHandle(hWdmAud); 00399 printf("WDMAUD: COMPLETE\n"); 00400 return 0; 00401 } Generated on Sun May 27 2012 04:28:32 for ReactOS by
1.7.6.1
|