Author: janderwald
Date: Wed Apr 15 14:41:41 2009
New Revision: 40524
URL: 
http://svn.reactos.org/svn/reactos?rev=40524&view=rev
Log:
- Plug in sample rate conversion library, doesnt work yet
- Implement calloc, memset, memcpy as calling their Rtl* wrapper doesnt work- Add define
for AC97 hacks
Modified:
    trunk/reactos/drivers/wdm/audio/filters/kmixer/pin.c
    trunk/reactos/drivers/wdm/audio/sysaudio/control.c
Modified: trunk/reactos/drivers/wdm/audio/filters/kmixer/pin.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/filters/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/filters/kmixer/pin.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/filters/kmixer/pin.c [iso-8859-1] Wed Apr 15 14:41:41
2009
@@ -9,6 +9,140 @@
 #include "kmixer.h"
 const GUID KSPROPSETID_Connection              = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5,
0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
+
+NTSTATUS
+PerformSampleRateConversion(
+    PUCHAR Buffer,
+    ULONG BufferLength,
+    ULONG OldRate,
+    ULONG NewRate,
+    ULONG BytesPerSample,
+    ULONG NumChannels,
+    PVOID * Result,
+    PULONG ResultLength)
+{
+    KFLOATING_SAVE FloatSave;
+    NTSTATUS Status;
+    ULONG Index;
+    SRC_STATE * State;
+    SRC_DATA Data;
+    PUCHAR ResultOut;
+    int error;
+    PFLOAT FloatIn, FloatOut;
+    ULONG NumSamples;
+    ULONG NewSamples;
+
+    DPRINT("PerformSampleRateConversion OldRate %u NewRate %u BytesPerSample %u
NumChannels %u Irql %u\n", OldRate, NewRate, BytesPerSample, NumChannels,
KeGetCurrentIrql());
+
+    /* first acquire float save context */
+    Status = KeSaveFloatingPointState(&FloatSave);
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("KeSaveFloatingPointState failed with %x\n", Status);
+        return Status;
+    }
+
+    NumSamples = BufferLength / BytesPerSample;
+
+    FloatIn = ExAllocatePool(NonPagedPool, NumSamples * sizeof(FLOAT));
+    if (!FloatIn)
+    {
+        KeRestoreFloatingPointState(&FloatSave);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    NewSamples = lrintf(((FLOAT)NumSamples * ((FLOAT)NewRate / (FLOAT)OldRate))) + 2;
+
+    FloatOut = ExAllocatePool(NonPagedPool, NewSamples * sizeof(FLOAT));
+    if (!FloatOut)
+    {
+        ExFreePool(FloatIn);
+        KeRestoreFloatingPointState(&FloatSave);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    ResultOut = ExAllocatePool(NonPagedPool, NewSamples * (BytesPerSample/8));
+    if (!FloatOut)
+    {
+        ExFreePool(FloatIn);
+        ExFreePool(FloatOut);
+        KeRestoreFloatingPointState(&FloatSave);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    State = src_new(SRC_SINC_FASTEST, NumChannels, &error);
+    if (!State)
+    {
+        DPRINT1("KeSaveFloatingPointState failed with %x\n", Status);
+        KeRestoreFloatingPointState(&FloatSave);
+        ExFreePool(FloatIn);
+        ExFreePool(FloatOut);
+        ExFreePool(ResultOut);
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    /* fixme use asm */
+    if (BytesPerSample == 8)
+    {
+        for(Index = 0; Index < NumSamples; Index++)
+            FloatIn[Index] = (float)Buffer[Index];
+    }
+    else if (BytesPerSample == 16)
+    {
+        PUSHORT Res = (PUSHORT)ResultOut;
+        for(Index = 0; Index < NumSamples; Index++)
+            FloatIn[Index] = (float)_byteswap_ushort(Res[Index]);
+    }
+    else
+    {
+        UNIMPLEMENTED
+        KeRestoreFloatingPointState(&FloatSave);
+        ExFreePool(FloatIn);
+        ExFreePool(FloatOut);
+        ExFreePool(ResultOut);
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    Data.data_in = FloatIn;
+    Data.data_out = FloatOut;
+    Data.input_frames = NumSamples / NumChannels;
+    Data.output_frames = NewSamples / NumChannels;
+    Data.src_ratio = (double)NewRate / (double)OldRate;
+
+    error = src_process(State, &Data);
+    if (error)
+    {
+        DPRINT1("src_process failed with %x\n", error);
+        KeRestoreFloatingPointState(&FloatSave);
+        ExFreePool(FloatIn);
+        ExFreePool(FloatOut);
+        ExFreePool(ResultOut);
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    if (BytesPerSample == 8)
+    {
+        for(Index = 0; Index < Data.output_frames_gen * NumChannels; Index++)
+            ResultOut[Index] = lrintf(FloatOut[Index]);
+    }
+    else if (BytesPerSample == 16)
+    {
+        PUSHORT Res = (PUSHORT)ResultOut;
+
+        for(Index = 0; Index < Data.output_frames_gen * NumChannels; Index++)
+            Res[Index] = _byteswap_ushort(lrintf(FloatOut[Index]));
+    }
+
+    *Result = ResultOut;
+    *ResultLength = Data.output_frames_gen * (BytesPerSample/8) * NumChannels;
+    ExFreePool(FloatIn);
+    ExFreePool(FloatOut);
+    src_delete(State);
+    KeRestoreFloatingPointState(&FloatSave);
+
+    return STATUS_SUCCESS;
+}
 NTSTATUS
 PerformChannelConversion(
@@ -502,7 +636,7 @@
                                           StreamHeader->DataUsed,
                                           InputFormat->WaveFormatEx.nChannels,
                                           OutputFormat->WaveFormatEx.nChannels,
-                                          InputFormat->WaveFormatEx.wBitsPerSample,
+                                          OutputFormat->WaveFormatEx.wBitsPerSample,
                                           &BufferOut,
                                           &BufferLength);
@@ -516,9 +650,20 @@
     if (InputFormat->WaveFormatEx.nSamplesPerSec !=
OutputFormat->WaveFormatEx.nSamplesPerSec)
     {
-        /* sample format conversion must be done in a deferred routine */
-        DPRINT1("SampleRate conversion not available yet %u %u\n",
InputFormat->WaveFormatEx.nSamplesPerSec,
OutputFormat->WaveFormatEx.nSamplesPerSec);
-        return FALSE;
+        Status = PerformSampleRateConversion(StreamHeader->Data,
+                                             StreamHeader->DataUsed,
+                                             InputFormat->WaveFormatEx.nSamplesPerSec,
+
OutputFormat->WaveFormatEx.nSamplesPerSec,
+
OutputFormat->WaveFormatEx.wBitsPerSample,
+                                             OutputFormat->WaveFormatEx.nChannels,
+                                             &BufferOut,
+                                             &BufferLength);
+        if (NT_SUCCESS(Status))
+        {
+            ExFreePool(StreamHeader->Data);
+            StreamHeader->Data = BufferOut;
+            StreamHeader->DataUsed = BufferLength;
+        }
     }
     if (NT_SUCCESS(Status))
@@ -567,9 +712,13 @@
 void * calloc(size_t Elements, size_t ElementSize)
 {
-    PVOID Block = ExAllocatePool(NonPagedPool, Elements * ElementSize);
-    if (Block)
-        RtlZeroMemory(Block, Elements * ElementSize);
+    ULONG Index;
+    PUCHAR Block = ExAllocatePool(NonPagedPool, Elements * ElementSize);
+    if (!Block)
+        return NULL;
+
+    for(Index = 0; Index < Elements * ElementSize; Index++)
+        Block[Index] = 0;
     return Block;
 }
@@ -584,7 +733,12 @@
    int c,
    size_t count)
 {
-    RtlFillMemory(dest, count, c);
+    ULONG Index;
+    PUCHAR Block = (PUCHAR)dest;
+
+    for(Index = 0; Index < count; Index++)
+        Block[Index] = c;
+
     return dest;
 }
@@ -593,18 +747,10 @@
    const void* src,
    size_t count)
 {
-    RtlCopyMemory(dest, src, count);
+    ULONG Index;
+    PUCHAR Src = (PUCHAR)src, Dest = (PUCHAR)dest;
+
+    for(Index = 0; Index < count; Index++)
+        Dest[Index] = Src[Index];
     return dest;
 }
-
-void *memmove(
-   void* dest,
-   const void* src,
-   size_t count)
-{
-    RtlMoveMemory(dest, src, count);
-    return dest;
-}
-
-
-
Modified: trunk/reactos/drivers/wdm/audio/sysaudio/control.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/sysaudio…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/sysaudio/control.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/sysaudio/control.c [iso-8859-1] Wed Apr 15 14:41:41
2009
@@ -201,6 +201,7 @@
     PFILE_OBJECT RealFileObject = NULL, VirtualFileObject = NULL;
     PSYSAUDIO_CLIENT AudioClient;
     PSYSAUDIO_PIN_HANDLE ClientPinHandle;
+    PKSDATAFORMAT_WAVEFORMATEX InputFormat;
     PKSDATAFORMAT_WAVEFORMATEX OutputFormat = NULL;
     PKSPIN_CONNECT MixerPinConnect = NULL;
     PPIN_WORKER_CONTEXT WorkerContext = (PPIN_WORKER_CONTEXT)Context;
@@ -215,6 +216,11 @@
     ASSERT(WorkerContext->PinConnect);
     ASSERT(WorkerContext->Entry->Pins);
     ASSERT(WorkerContext->Entry->NumberOfPins >
WorkerContext->PinConnect->PinId);
+
+
+    /* Fetch input format */
+    InputFormat = (PKSDATAFORMAT_WAVEFORMATEX)(WorkerContext->PinConnect + 1);
+
     /* Let's try to create the audio irp pin */
     Status = KsCreatePin(WorkerContext->Entry->Handle,
WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle);
@@ -258,6 +264,8 @@
             KeBugCheck(0);
             return;
         }
+        DPRINT(" InputFormat: SampleRate %u Bits %u Channels %u\n",
InputFormat->WaveFormatEx.nSamplesPerSec, InputFormat->WaveFormatEx.wBitsPerSample,
InputFormat->WaveFormatEx.nChannels);
+        DPRINT("OutputFormat: SampleRate %u Bits %u Channels %u\n",
OutputFormat->WaveFormatEx.nSamplesPerSec,
OutputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.nChannels);
     }
     /* get pin file object */
@@ -286,15 +294,10 @@
     /* Do we need to transform the audio stream */
     if (OutputFormat != NULL)
     {
-        PKSDATAFORMAT InputFormat;
-
-        /* Fetch input format */
-        InputFormat = (PKSDATAFORMAT)(WorkerContext->PinConnect + 1);
-
         /* Now create the mixer pin */
         Status =
CreateMixerPinAndSetFormat(WorkerContext->DeviceExtension->KMixerHandle,
                                             MixerPinConnect,
-                                            InputFormat,
+                                            (PKSDATAFORMAT)InputFormat,
                                             (PKSDATAFORMAT)OutputFormat,
&WorkerContext->DispatchContext->hMixerPin,
&WorkerContext->DispatchContext->MixerFileObject);
@@ -583,6 +586,7 @@
             AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange +
AudioRange->DataRange.FormatSize);
         }
         /* Select best quality available */
+
         MixerFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) +
sizeof(WAVEFORMATEX);
         MixerFormat->DataFormat.Flags = 0;
         MixerFormat->DataFormat.Reserved = 0;
@@ -591,9 +595,23 @@
         MixerFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
         MixerFormat->DataFormat.SampleSize = 4;
         MixerFormat->WaveFormatEx.wFormatTag =
ClientFormat->WaveFormatEx.wFormatTag;
-        MixerFormat->WaveFormatEx.nChannels = min(2, AudioRange->MaximumChannels);
/* AC97 does not support mono render / record */
+#ifndef NO_AC97_HACK
+        /* HACK: AC97 does not support mono render / record */
+        MixerFormat->WaveFormatEx.nChannels = 2;
+        /*HACK: AC97 only supports 16-Bit Bits */
+        MixerFormat->WaveFormatEx.wBitsPerSample = 16;
+
+#else
+        MixerFormat->WaveFormatEx.nChannels =
min(ClientFormat->WaveFormatEx.nSamplesPerSec, AudioRange->MaximumChannels);
+        MixerFormat->WaveFormatEx.wBitsPerSample =
AudioRange->MaximumBitsPerSample;
+#endif
+
+#ifdef KMIXER_RESAMPLING_IMPLEMENTED
         MixerFormat->WaveFormatEx.nSamplesPerSec =
AudioRange->MaximumSampleFrequency;
-        MixerFormat->WaveFormatEx.wBitsPerSample =
AudioRange->MaximumBitsPerSample;
+#else
+        MixerFormat->WaveFormatEx.nSamplesPerSec =
max(AudioRange->MinimumSampleFrequency,
min(ClientFormat->WaveFormatEx.nSamplesPerSec, AudioRange->MaximumSampleFrequency));
+#endif
+
         MixerFormat->WaveFormatEx.cbSize = 0;
         MixerFormat->WaveFormatEx.nBlockAlign =
(MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.wBitsPerSample) /
8;
         MixerFormat->WaveFormatEx.nAvgBytesPerSec =
MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.nSamplesPerSec *
(MixerFormat->WaveFormatEx.wBitsPerSample / 8);