Sync with trunk (48237)
[reactos.git] / drivers / wdm / audio / filters / kmixer / pin.c
1 /*
2 * PROJECT: ReactOS Kernel Streaming Mixer
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/wdm/audio/filters/kmixer/kmixer.c
5 * PURPOSE: Pin functions
6 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
7 */
8
9 #include "kmixer.h"
10
11 const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
12
13 NTSTATUS
14 PerformSampleRateConversion(
15 PUCHAR Buffer,
16 ULONG BufferLength,
17 ULONG OldRate,
18 ULONG NewRate,
19 ULONG BytesPerSample,
20 ULONG NumChannels,
21 PVOID * Result,
22 PULONG ResultLength)
23 {
24 KFLOATING_SAVE FloatSave;
25 NTSTATUS Status;
26 ULONG Index;
27 SRC_STATE * State;
28 SRC_DATA Data;
29 PUCHAR ResultOut;
30 int error;
31 PFLOAT FloatIn, FloatOut;
32 ULONG NumSamples;
33 ULONG NewSamples;
34
35 DPRINT("PerformSampleRateConversion OldRate %u NewRate %u BytesPerSample %u NumChannels %u Irql %u\n", OldRate, NewRate, BytesPerSample, NumChannels, KeGetCurrentIrql());
36
37 ASSERT(BytesPerSample == 1 || BytesPerSample == 2 || BytesPerSample == 4);
38
39 /* first acquire float save context */
40 Status = KeSaveFloatingPointState(&FloatSave);
41
42 if (!NT_SUCCESS(Status))
43 {
44 DPRINT1("KeSaveFloatingPointState failed with %x\n", Status);
45 return Status;
46 }
47
48 NumSamples = BufferLength / (BytesPerSample * NumChannels);
49
50 FloatIn = ExAllocatePool(NonPagedPool, NumSamples * NumChannels * sizeof(FLOAT));
51 if (!FloatIn)
52 {
53 KeRestoreFloatingPointState(&FloatSave);
54 return STATUS_INSUFFICIENT_RESOURCES;
55 }
56
57 NewSamples = lrintf(((FLOAT)NumSamples * ((FLOAT)NewRate / (FLOAT)OldRate))) + 2;
58
59 FloatOut = ExAllocatePool(NonPagedPool, NewSamples * NumChannels * sizeof(FLOAT));
60 if (!FloatOut)
61 {
62 ExFreePool(FloatIn);
63 KeRestoreFloatingPointState(&FloatSave);
64 return STATUS_INSUFFICIENT_RESOURCES;
65 }
66
67 ResultOut = ExAllocatePool(NonPagedPool, NewSamples * NumChannels * BytesPerSample);
68 if (!ResultOut)
69 {
70 ExFreePool(FloatIn);
71 ExFreePool(FloatOut);
72 KeRestoreFloatingPointState(&FloatSave);
73 return STATUS_INSUFFICIENT_RESOURCES;
74 }
75
76 State = src_new(SRC_SINC_FASTEST, NumChannels, &error);
77 if (!State)
78 {
79 DPRINT1("KeSaveFloatingPointState failed with %x\n", Status);
80 KeRestoreFloatingPointState(&FloatSave);
81 ExFreePool(FloatIn);
82 ExFreePool(FloatOut);
83 ExFreePool(ResultOut);
84 return STATUS_UNSUCCESSFUL;
85 }
86
87 /* fixme use asm */
88 if (BytesPerSample == 1)
89 {
90 for(Index = 0; Index < NumSamples * NumChannels; Index++)
91 FloatIn[Index] = (float)(Buffer[Index] / (1.0 * 0x80));
92 }
93 else if (BytesPerSample == 2)
94 {
95 src_short_to_float_array((short*)Buffer, FloatIn, NumSamples * NumChannels);
96 }
97 else if (BytesPerSample == 4)
98 {
99 src_int_to_float_array((int*)Buffer, FloatIn, NumSamples * NumChannels);
100 }
101
102 Data.data_in = FloatIn;
103 Data.data_out = FloatOut;
104 Data.input_frames = NumSamples;
105 Data.output_frames = NewSamples;
106 Data.src_ratio = (double)NewRate / (double)OldRate;
107
108 error = src_process(State, &Data);
109 if (error)
110 {
111 DPRINT1("src_process failed with %x\n", error);
112 KeRestoreFloatingPointState(&FloatSave);
113 ExFreePool(FloatIn);
114 ExFreePool(FloatOut);
115 ExFreePool(ResultOut);
116 return STATUS_UNSUCCESSFUL;
117 }
118
119 if (BytesPerSample == 1)
120 {
121 /* FIXME perform over/under clipping */
122
123 for(Index = 0; Index < Data.output_frames_gen * NumChannels; Index++)
124 ResultOut[Index] = (lrintf(FloatOut[Index]) >> 24);
125 }
126 else if (BytesPerSample == 2)
127 {
128 PUSHORT Res = (PUSHORT)ResultOut;
129
130 src_float_to_short_array(FloatOut, (short*)Res, Data.output_frames_gen * NumChannels);
131 }
132 else if (BytesPerSample == 4)
133 {
134 PULONG Res = (PULONG)ResultOut;
135
136 src_float_to_int_array(FloatOut, (int*)Res, Data.output_frames_gen * NumChannels);
137 }
138
139
140 *Result = ResultOut;
141 *ResultLength = Data.output_frames_gen * BytesPerSample * NumChannels;
142 ExFreePool(FloatIn);
143 ExFreePool(FloatOut);
144 src_delete(State);
145 KeRestoreFloatingPointState(&FloatSave);
146 return STATUS_SUCCESS;
147 }
148
149 NTSTATUS
150 PerformChannelConversion(
151 PUCHAR Buffer,
152 ULONG BufferLength,
153 ULONG OldChannels,
154 ULONG NewChannels,
155 ULONG BitsPerSample,
156 PVOID * Result,
157 PULONG ResultLength)
158 {
159 ULONG Samples;
160 ULONG NewIndex, OldIndex;
161
162 Samples = BufferLength / (BitsPerSample / 8) / OldChannels;
163
164 if (NewChannels > OldChannels)
165 {
166 if (BitsPerSample == 8)
167 {
168 PUCHAR BufferOut = ExAllocatePool(NonPagedPool, Samples * NewChannels);
169 if (!BufferOut)
170 return STATUS_INSUFFICIENT_RESOURCES;
171
172 for(NewIndex = 0, OldIndex = 0; OldIndex < Samples * OldChannels; NewIndex += NewChannels, OldIndex += OldChannels)
173 {
174 ULONG SubIndex = 0;
175
176 RtlMoveMemory(&BufferOut[NewIndex], &Buffer[OldIndex], OldChannels * sizeof(UCHAR));
177
178 do
179 {
180 /* 2 channel stretched to 4 looks like LRLR */
181 BufferOut[NewIndex+OldChannels + SubIndex] = Buffer[OldIndex + (SubIndex % OldChannels)];
182 }while(SubIndex++ < NewChannels - OldChannels);
183 }
184 *Result = BufferOut;
185 *ResultLength = Samples * NewChannels;
186 }
187 else if (BitsPerSample == 16)
188 {
189 PUSHORT BufferOut = ExAllocatePool(NonPagedPool, Samples * NewChannels);
190 if (!BufferOut)
191 return STATUS_INSUFFICIENT_RESOURCES;
192
193 for(NewIndex = 0, OldIndex = 0; OldIndex < Samples * OldChannels; NewIndex += NewChannels, OldIndex += OldChannels)
194 {
195 ULONG SubIndex = 0;
196
197 RtlMoveMemory(&BufferOut[NewIndex], &Buffer[OldIndex], OldChannels * sizeof(USHORT));
198
199 do
200 {
201 BufferOut[NewIndex+OldChannels + SubIndex] = Buffer[OldIndex + (SubIndex % OldChannels)];
202 }while(SubIndex++ < NewChannels - OldChannels);
203 }
204 *Result = BufferOut;
205 *ResultLength = Samples * NewChannels;
206 }
207 else if (BitsPerSample == 24)
208 {
209 PUCHAR BufferOut = ExAllocatePool(NonPagedPool, Samples * NewChannels);
210 if (!BufferOut)
211 return STATUS_INSUFFICIENT_RESOURCES;
212
213 for(NewIndex = 0, OldIndex = 0; OldIndex < Samples * OldChannels; NewIndex += NewChannels, OldIndex += OldChannels)
214 {
215 ULONG SubIndex = 0;
216
217 RtlMoveMemory(&BufferOut[NewIndex], &Buffer[OldIndex], OldChannels * 3);
218
219 do
220 {
221 RtlMoveMemory(&BufferOut[(NewIndex+OldChannels + SubIndex) * 3], &Buffer[(OldIndex + (SubIndex % OldChannels)) * 3], 3);
222 }while(SubIndex++ < NewChannels - OldChannels);
223 }
224 *Result = BufferOut;
225 *ResultLength = Samples * NewChannels;
226 }
227 else if (BitsPerSample == 32)
228 {
229 PULONG BufferOut = ExAllocatePool(NonPagedPool, Samples * NewChannels);
230 if (!BufferOut)
231 return STATUS_INSUFFICIENT_RESOURCES;
232
233 for(NewIndex = 0, OldIndex = 0; OldIndex < Samples * OldChannels; NewIndex += NewChannels, OldIndex += OldChannels)
234 {
235 ULONG SubIndex = 0;
236
237 RtlMoveMemory(&BufferOut[NewIndex], &Buffer[OldIndex], OldChannels * sizeof(ULONG));
238
239 do
240 {
241 BufferOut[NewIndex+OldChannels + SubIndex] = Buffer[OldIndex + (SubIndex % OldChannels)];
242 }while(SubIndex++ < NewChannels - OldChannels);
243 }
244 *Result = BufferOut;
245 *ResultLength = Samples * NewChannels;
246 }
247
248 }
249 else
250 {
251 PUSHORT BufferOut = ExAllocatePool(NonPagedPool, Samples * NewChannels);
252 if (!BufferOut)
253 return STATUS_INSUFFICIENT_RESOURCES;
254
255 for(NewIndex = 0, OldIndex = 0; OldIndex < Samples * OldChannels; NewIndex += NewChannels, OldIndex += OldChannels)
256 {
257 /* TODO
258 * mix stream instead of just dumping part of it ;)
259 */
260 RtlMoveMemory(&BufferOut[NewIndex], &Buffer[OldIndex], NewChannels * (BitsPerSample/8));
261 }
262
263 *Result = BufferOut;
264 *ResultLength = Samples * NewChannels;
265 }
266 return STATUS_SUCCESS;
267 }
268
269
270 NTSTATUS
271 PerformQualityConversion(
272 PUCHAR Buffer,
273 ULONG BufferLength,
274 ULONG OldWidth,
275 ULONG NewWidth,
276 PVOID * Result,
277 PULONG ResultLength)
278 {
279 ULONG Samples;
280 ULONG Index;
281
282 ASSERT(OldWidth != NewWidth);
283
284 Samples = BufferLength / (OldWidth / 8);
285 //DPRINT("Samples %u BufferLength %u\n", Samples, BufferLength);
286
287 if (OldWidth == 8 && NewWidth == 16)
288 {
289 USHORT Sample;
290 PUSHORT BufferOut = ExAllocatePool(NonPagedPool, Samples * sizeof(USHORT));
291 if (!BufferOut)
292 return STATUS_INSUFFICIENT_RESOURCES;
293
294 for(Index = 0; Index < Samples; Index++)
295 {
296 Sample = Buffer[Index];
297 Sample *= 2;
298 #ifdef _X86_
299 Sample = _byteswap_ushort(Sample);
300 #endif
301 BufferOut[Index] = Sample;
302 }
303 *Result = BufferOut;
304 *ResultLength = Samples * sizeof(USHORT);
305 }
306 else if (OldWidth == 8 && NewWidth == 32)
307 {
308 ULONG Sample;
309 PULONG BufferOut = ExAllocatePool(NonPagedPool, Samples * sizeof(ULONG));
310 if (!BufferOut)
311 return STATUS_INSUFFICIENT_RESOURCES;
312
313 for(Index = 0; Index < Samples; Index++)
314 {
315 Sample = Buffer[Index];
316 Sample *= 16777216;
317 #ifdef _X86_
318 Sample = _byteswap_ulong(Sample);
319 #endif
320 BufferOut[Index] = Sample;
321 }
322 *Result = BufferOut;
323 *ResultLength = Samples * sizeof(ULONG);
324 }
325 else if (OldWidth == 16 && NewWidth == 32)
326 {
327 ULONG Sample;
328 PUSHORT BufferIn = (PUSHORT)Buffer;
329 PULONG BufferOut = ExAllocatePool(NonPagedPool, Samples * sizeof(ULONG));
330 if (!BufferOut)
331 return STATUS_INSUFFICIENT_RESOURCES;
332
333 for(Index = 0; Index < Samples; Index++)
334 {
335 Sample = BufferIn[Index];
336 Sample *= 65536;
337 #ifdef _X86_
338 Sample = _byteswap_ulong(Sample);
339 #endif
340 BufferOut[Index] = Sample;
341 }
342 *Result = BufferOut;
343 *ResultLength = Samples * sizeof(ULONG);
344 }
345
346 else if (OldWidth == 16 && NewWidth == 8)
347 {
348 USHORT Sample;
349 PUSHORT BufferIn = (PUSHORT)Buffer;
350 PUCHAR BufferOut = ExAllocatePool(NonPagedPool, Samples * sizeof(UCHAR));
351 if (!BufferOut)
352 return STATUS_INSUFFICIENT_RESOURCES;
353
354 for(Index = 0; Index < Samples; Index++)
355 {
356 Sample = BufferIn[Index];
357 #ifdef _X86_
358 Sample = _byteswap_ushort(Sample);
359 #endif
360 Sample /= 256;
361 BufferOut[Index] = (Sample & 0xFF);
362 }
363 *Result = BufferOut;
364 *ResultLength = Samples * sizeof(UCHAR);
365 }
366 else if (OldWidth == 32 && NewWidth == 8)
367 {
368 ULONG Sample;
369 PULONG BufferIn = (PULONG)Buffer;
370 PUCHAR BufferOut = ExAllocatePool(NonPagedPool, Samples * sizeof(UCHAR));
371 if (!BufferOut)
372 return STATUS_INSUFFICIENT_RESOURCES;
373
374 for(Index = 0; Index < Samples; Index++)
375 {
376 Sample = BufferIn[Index];
377 #ifdef _X86_
378 Sample = _byteswap_ulong(Sample);
379 #endif
380 Sample /= 16777216;
381 BufferOut[Index] = (Sample & 0xFF);
382 }
383 *Result = BufferOut;
384 *ResultLength = Samples * sizeof(UCHAR);
385 }
386 else if (OldWidth == 32 && NewWidth == 16)
387 {
388 USHORT Sample;
389 PULONG BufferIn = (PULONG)Buffer;
390 PUSHORT BufferOut = ExAllocatePool(NonPagedPool, Samples * sizeof(USHORT));
391 if (!BufferOut)
392 return STATUS_INSUFFICIENT_RESOURCES;
393
394 for(Index = 0; Index < Samples; Index++)
395 {
396 Sample = BufferIn[Index];
397 #ifdef _X86_
398 Sample = _byteswap_ulong(Sample);
399 #endif
400 Sample /= 65536;
401 BufferOut[Index] = (Sample & 0xFFFF);
402 }
403 *Result = BufferOut;
404 *ResultLength = Samples * sizeof(USHORT);
405 }
406 else
407 {
408 DPRINT1("Not implemented conversion OldWidth %u NewWidth %u\n", OldWidth, NewWidth);
409 return STATUS_NOT_IMPLEMENTED;
410 }
411
412 return STATUS_SUCCESS;
413 }
414
415
416 NTSTATUS
417 NTAPI
418 Pin_fnDeviceIoControl(
419 PDEVICE_OBJECT DeviceObject,
420 PIRP Irp)
421 {
422 PIO_STACK_LOCATION IoStack;
423 PKSP_PIN Property;
424 //DPRINT1("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
425
426 IoStack = IoGetCurrentIrpStackLocation(Irp);
427
428 if (IoStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(KSP_PIN) && IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSDATAFORMAT_WAVEFORMATEX))
429 {
430 Property = (PKSP_PIN)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
431
432 if (IsEqualGUIDAligned(&Property->Property.Set, &KSPROPSETID_Connection))
433 {
434 if (Property->Property.Id == KSPROPERTY_CONNECTION_DATAFORMAT && Property->Property.Flags == KSPROPERTY_TYPE_SET)
435 {
436 PKSDATAFORMAT_WAVEFORMATEX Formats;
437 PKSDATAFORMAT_WAVEFORMATEX WaveFormat;
438
439 Formats = (PKSDATAFORMAT_WAVEFORMATEX)IoStack->FileObject->FsContext2;
440 WaveFormat = (PKSDATAFORMAT_WAVEFORMATEX)Irp->UserBuffer;
441
442 ASSERT(Property->PinId == 0 || Property->PinId == 1);
443 ASSERT(Formats);
444 ASSERT(WaveFormat);
445
446 Formats[Property->PinId].WaveFormatEx.nChannels = WaveFormat->WaveFormatEx.nChannels;
447 Formats[Property->PinId].WaveFormatEx.wBitsPerSample = WaveFormat->WaveFormatEx.wBitsPerSample;
448 Formats[Property->PinId].WaveFormatEx.nSamplesPerSec = WaveFormat->WaveFormatEx.nSamplesPerSec;
449
450 Irp->IoStatus.Information = 0;
451 Irp->IoStatus.Status = STATUS_SUCCESS;
452 IoCompleteRequest(Irp, IO_NO_INCREMENT);
453 return STATUS_SUCCESS;
454 }
455 }
456 }
457 DPRINT1("Size %u Expected %u\n",IoStack->Parameters.DeviceIoControl.OutputBufferLength, sizeof(KSDATAFORMAT_WAVEFORMATEX));
458 Irp->IoStatus.Information = 0;
459 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
460 IoCompleteRequest(Irp, IO_NO_INCREMENT);
461 return STATUS_UNSUCCESSFUL;
462 }
463
464 NTSTATUS
465 NTAPI
466 Pin_fnRead(
467 PDEVICE_OBJECT DeviceObject,
468 PIRP Irp)
469 {
470 UNIMPLEMENTED
471
472 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
473 Irp->IoStatus.Information = 0;
474 IoCompleteRequest(Irp, IO_NO_INCREMENT);
475 return STATUS_UNSUCCESSFUL;
476 }
477
478 NTSTATUS
479 NTAPI
480 Pin_fnWrite(
481 PDEVICE_OBJECT DeviceObject,
482 PIRP Irp)
483 {
484 UNIMPLEMENTED
485
486 Irp->IoStatus.Information = 0;
487 Irp->IoStatus.Status = STATUS_SUCCESS;
488 IoCompleteRequest(Irp, IO_NO_INCREMENT);
489 return STATUS_SUCCESS;
490 }
491
492 NTSTATUS
493 NTAPI
494 Pin_fnFlush(
495 PDEVICE_OBJECT DeviceObject,
496 PIRP Irp)
497 {
498 UNIMPLEMENTED
499
500 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
501 Irp->IoStatus.Information = 0;
502 IoCompleteRequest(Irp, IO_NO_INCREMENT);
503 return STATUS_UNSUCCESSFUL;
504 }
505
506 NTSTATUS
507 NTAPI
508 Pin_fnClose(
509 PDEVICE_OBJECT DeviceObject,
510 PIRP Irp)
511 {
512 UNIMPLEMENTED
513
514 Irp->IoStatus.Status = STATUS_SUCCESS;
515 Irp->IoStatus.Information = 0;
516 IoCompleteRequest(Irp, IO_NO_INCREMENT);
517 return STATUS_SUCCESS;
518 }
519
520 NTSTATUS
521 NTAPI
522 Pin_fnQuerySecurity(
523 PDEVICE_OBJECT DeviceObject,
524 PIRP Irp)
525 {
526 UNIMPLEMENTED
527
528 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
529 Irp->IoStatus.Information = 0;
530 IoCompleteRequest(Irp, IO_NO_INCREMENT);
531 return STATUS_UNSUCCESSFUL;
532 }
533
534 NTSTATUS
535 NTAPI
536 Pin_fnSetSecurity(
537 PDEVICE_OBJECT DeviceObject,
538 PIRP Irp)
539 {
540
541 UNIMPLEMENTED
542
543 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
544 Irp->IoStatus.Information = 0;
545 IoCompleteRequest(Irp, IO_NO_INCREMENT);
546 return STATUS_UNSUCCESSFUL;
547 }
548
549 BOOLEAN
550 NTAPI
551 Pin_fnFastDeviceIoControl(
552 PFILE_OBJECT FileObject,
553 BOOLEAN Wait,
554 PVOID InputBuffer,
555 ULONG InputBufferLength,
556 PVOID OutputBuffer,
557 ULONG OutputBufferLength,
558 ULONG IoControlCode,
559 PIO_STATUS_BLOCK IoStatus,
560 PDEVICE_OBJECT DeviceObject)
561 {
562 UNIMPLEMENTED
563
564
565 return FALSE;
566 }
567
568
569 BOOLEAN
570 NTAPI
571 Pin_fnFastRead(
572 PFILE_OBJECT FileObject,
573 PLARGE_INTEGER FileOffset,
574 ULONG Length,
575 BOOLEAN Wait,
576 ULONG LockKey,
577 PVOID Buffer,
578 PIO_STATUS_BLOCK IoStatus,
579 PDEVICE_OBJECT DeviceObject)
580 {
581 UNIMPLEMENTED
582 return FALSE;
583
584 }
585
586 BOOLEAN
587 NTAPI
588 Pin_fnFastWrite(
589 PFILE_OBJECT FileObject,
590 PLARGE_INTEGER FileOffset,
591 ULONG Length,
592 BOOLEAN Wait,
593 ULONG LockKey,
594 PVOID Buffer,
595 PIO_STATUS_BLOCK IoStatus,
596 PDEVICE_OBJECT DeviceObject)
597 {
598 PKSSTREAM_HEADER StreamHeader;
599 PVOID BufferOut;
600 ULONG BufferLength;
601 NTSTATUS Status = STATUS_SUCCESS;
602 PKSDATAFORMAT_WAVEFORMATEX Formats;
603 PKSDATAFORMAT_WAVEFORMATEX InputFormat, OutputFormat;
604
605 DPRINT("Pin_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject);
606
607 Formats = (PKSDATAFORMAT_WAVEFORMATEX)FileObject->FsContext2;
608
609 InputFormat = Formats;
610 OutputFormat = (Formats + 1);
611 StreamHeader = (PKSSTREAM_HEADER)Buffer;
612
613
614 DPRINT("Num Channels %u Old Channels %u\n SampleRate %u Old SampleRate %u\n BitsPerSample %u Old BitsPerSample %u\n",
615 InputFormat->WaveFormatEx.nChannels, OutputFormat->WaveFormatEx.nChannels,
616 InputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.nSamplesPerSec,
617 InputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.wBitsPerSample);
618
619 if (InputFormat->WaveFormatEx.wBitsPerSample != OutputFormat->WaveFormatEx.wBitsPerSample)
620 {
621 Status = PerformQualityConversion(StreamHeader->Data,
622 StreamHeader->DataUsed,
623 InputFormat->WaveFormatEx.wBitsPerSample,
624 OutputFormat->WaveFormatEx.wBitsPerSample,
625 &BufferOut,
626 &BufferLength);
627 if (NT_SUCCESS(Status))
628 {
629 ExFreePool(StreamHeader->Data);
630 StreamHeader->Data = BufferOut;
631 StreamHeader->DataUsed = BufferLength;
632 }
633 }
634
635 if (InputFormat->WaveFormatEx.nChannels != OutputFormat->WaveFormatEx.nChannels)
636 {
637 Status = PerformChannelConversion(StreamHeader->Data,
638 StreamHeader->DataUsed,
639 InputFormat->WaveFormatEx.nChannels,
640 OutputFormat->WaveFormatEx.nChannels,
641 OutputFormat->WaveFormatEx.wBitsPerSample,
642 &BufferOut,
643 &BufferLength);
644
645 if (NT_SUCCESS(Status))
646 {
647 ExFreePool(StreamHeader->Data);
648 StreamHeader->Data = BufferOut;
649 StreamHeader->DataUsed = BufferLength;
650 }
651 }
652
653 if (InputFormat->WaveFormatEx.nSamplesPerSec != OutputFormat->WaveFormatEx.nSamplesPerSec)
654 {
655 Status = PerformSampleRateConversion(StreamHeader->Data,
656 StreamHeader->DataUsed,
657 InputFormat->WaveFormatEx.nSamplesPerSec,
658 OutputFormat->WaveFormatEx.nSamplesPerSec,
659 OutputFormat->WaveFormatEx.wBitsPerSample / 8,
660 OutputFormat->WaveFormatEx.nChannels,
661 &BufferOut,
662 &BufferLength);
663 if (NT_SUCCESS(Status))
664 {
665 ExFreePool(StreamHeader->Data);
666 StreamHeader->Data = BufferOut;
667 StreamHeader->DataUsed = BufferLength;
668 }
669 }
670
671 IoStatus->Status = Status;
672
673 if (NT_SUCCESS(Status))
674 return TRUE;
675 else
676 return TRUE;
677 }
678
679 static KSDISPATCH_TABLE PinTable =
680 {
681 Pin_fnDeviceIoControl,
682 Pin_fnRead,
683 Pin_fnWrite,
684 Pin_fnFlush,
685 Pin_fnClose,
686 Pin_fnQuerySecurity,
687 Pin_fnSetSecurity,
688 Pin_fnFastDeviceIoControl,
689 Pin_fnFastRead,
690 Pin_fnFastWrite,
691 };
692
693 NTSTATUS
694 CreatePin(
695 IN PIRP Irp)
696 {
697 NTSTATUS Status;
698 KSOBJECT_HEADER ObjectHeader;
699 PKSDATAFORMAT DataFormat;
700 PIO_STACK_LOCATION IoStack;
701
702
703 DataFormat = ExAllocatePool(NonPagedPool, sizeof(KSDATAFORMAT_WAVEFORMATEX) * 2);
704 if (!DataFormat)
705 return STATUS_INSUFFICIENT_RESOURCES;
706
707 RtlZeroMemory(DataFormat, sizeof(KSDATAFORMAT_WAVEFORMATEX) * 2);
708
709 IoStack = IoGetCurrentIrpStackLocation(Irp);
710 IoStack->FileObject->FsContext2 = (PVOID)DataFormat;
711
712 /* allocate object header */
713 Status = KsAllocateObjectHeader(&ObjectHeader, 0, NULL, Irp, &PinTable);
714 return Status;
715 }
716
717 void * calloc(size_t Elements, size_t ElementSize)
718 {
719 ULONG Index;
720 PUCHAR Block = ExAllocatePool(NonPagedPool, Elements * ElementSize);
721 if (!Block)
722 return NULL;
723
724 for(Index = 0; Index < Elements * ElementSize; Index++)
725 Block[Index] = 0;
726
727 return Block;
728 }
729
730 void free(PVOID Block)
731 {
732 ExFreePool(Block);
733 }