- Implement Channel de-muxing
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Tue, 14 Apr 2009 16:43:17 +0000 (16:43 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Tue, 14 Apr 2009 16:43:17 +0000 (16:43 +0000)
- WIP, bugs expected

svn path=/trunk/; revision=40505

reactos/drivers/wdm/audio/filters/kmixer/pin.c

index fbfc14f..c76326e 100644 (file)
 
 const GUID KSPROPSETID_Connection              = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
 
+NTSTATUS
+PerformChannelConversion(
+    PUCHAR Buffer,
+    ULONG BufferLength,
+    ULONG OldChannels,
+    ULONG NewChannels,
+    ULONG BitsPerSample,
+    PVOID * Result,
+    PULONG ResultLength)
+{
+    ULONG Samples;
+    ULONG NewIndex, OldIndex;
+
+    Samples = BufferLength / (BitsPerSample / 8) / OldChannels;
+
+    if (NewChannels > OldChannels)
+    {
+        if (BitsPerSample == 8)
+        {
+            PUCHAR BufferOut = ExAllocatePool(NonPagedPool, Samples * NewChannels);
+            if (!BufferOut)
+                return STATUS_INSUFFICIENT_RESOURCES;
+
+            for(NewIndex = 0, OldIndex = 0; OldIndex < Samples * OldChannels; NewIndex += NewChannels, OldIndex += OldChannels)
+            {
+                ULONG SubIndex = 0;
+
+                RtlMoveMemory(&BufferOut[NewIndex], &Buffer[OldIndex], OldChannels * sizeof(UCHAR));
+
+                do
+                {
+                    /* 2 channel stretched to 4 looks like LRLR */
+                     BufferOut[NewIndex+OldChannels + SubIndex] = Buffer[OldIndex + (SubIndex % OldChannels)];
+                }while(SubIndex++ < NewChannels - OldChannels);
+            }
+            *Result = BufferOut;
+            *ResultLength = Samples * NewChannels;
+        }
+        else if (BitsPerSample == 16)
+        {
+            PUSHORT BufferOut = ExAllocatePool(NonPagedPool, Samples * NewChannels);
+            if (!BufferOut)
+                return STATUS_INSUFFICIENT_RESOURCES;
+
+            for(NewIndex = 0, OldIndex = 0; OldIndex < Samples * OldChannels; NewIndex += NewChannels, OldIndex += OldChannels)
+            {
+                ULONG SubIndex = 0;
+
+                RtlMoveMemory(&BufferOut[NewIndex], &Buffer[OldIndex], OldChannels * sizeof(USHORT));
+
+                do
+                {
+                     BufferOut[NewIndex+OldChannels + SubIndex] = Buffer[OldIndex + (SubIndex % OldChannels)];
+                }while(SubIndex++ < NewChannels - OldChannels);
+            }
+            *Result = BufferOut;
+            *ResultLength = Samples * NewChannels;
+        }
+        else if (BitsPerSample == 24)
+        {
+            PUCHAR BufferOut = ExAllocatePool(NonPagedPool, Samples * NewChannels);
+            if (!BufferOut)
+                return STATUS_INSUFFICIENT_RESOURCES;
+
+            for(NewIndex = 0, OldIndex = 0; OldIndex < Samples * OldChannels; NewIndex += NewChannels, OldIndex += OldChannels)
+            {
+                ULONG SubIndex = 0;
+
+                RtlMoveMemory(&BufferOut[NewIndex], &Buffer[OldIndex], OldChannels * 3);
+
+                do
+                {
+                     RtlMoveMemory(&BufferOut[(NewIndex+OldChannels + SubIndex) * 3], &Buffer[(OldIndex + (SubIndex % OldChannels)) * 3], 3);
+                }while(SubIndex++ < NewChannels - OldChannels);
+            }
+            *Result = BufferOut;
+            *ResultLength = Samples * NewChannels;
+        }
+        else if (BitsPerSample == 32)
+        {
+            PULONG BufferOut = ExAllocatePool(NonPagedPool, Samples * NewChannels);
+            if (!BufferOut)
+                return STATUS_INSUFFICIENT_RESOURCES;
+
+            for(NewIndex = 0, OldIndex = 0; OldIndex < Samples * OldChannels; NewIndex += NewChannels, OldIndex += OldChannels)
+            {
+                ULONG SubIndex = 0;
+
+                RtlMoveMemory(&BufferOut[NewIndex], &Buffer[OldIndex], OldChannels * sizeof(ULONG));
+
+                do
+                {
+                     BufferOut[NewIndex+OldChannels + SubIndex] = Buffer[OldIndex + (SubIndex % OldChannels)];
+                }while(SubIndex++ < NewChannels - OldChannels);
+            }
+            *Result = BufferOut;
+            *ResultLength = Samples * NewChannels;
+        }
+
+    }
+    else
+    {
+        PUSHORT BufferOut = ExAllocatePool(NonPagedPool, Samples * NewChannels);
+        if (!BufferOut)
+            return STATUS_INSUFFICIENT_RESOURCES;
+
+        for(NewIndex = 0, OldIndex = 0; OldIndex < Samples * OldChannels; NewIndex += NewChannels, OldIndex += OldChannels)
+        {
+            /* TODO
+             * mix stream instead of just dumping part of it ;)
+             */
+            RtlMoveMemory(&BufferOut[NewIndex], &Buffer[OldIndex], NewChannels * (BitsPerSample/8));
+        }
+
+        *Result = BufferOut;
+        *ResultLength = Samples * NewChannels;
+    }
+    return STATUS_SUCCESS;
+}
+
+
 NTSTATUS
 PerformQualityConversion(
     PUCHAR Buffer,
@@ -359,7 +480,6 @@ Pin_fnFastWrite(
                InputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.nSamplesPerSec,
                InputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.wBitsPerSample);
 
-
     if (InputFormat->WaveFormatEx.wBitsPerSample != OutputFormat->WaveFormatEx.wBitsPerSample)
     {
         Status = PerformQualityConversion(StreamHeader->Data,
@@ -370,7 +490,24 @@ Pin_fnFastWrite(
                                           &BufferLength);
         if (NT_SUCCESS(Status))
         {
-            //DPRINT1("Old BufferSize %u NewBufferSize %u\n", StreamHeader->DataUsed, BufferLength);
+            ExFreePool(StreamHeader->Data);
+            StreamHeader->Data = BufferOut;
+            StreamHeader->DataUsed = BufferLength;
+        }
+    }
+
+    if (InputFormat->WaveFormatEx.nChannels != OutputFormat->WaveFormatEx.nChannels)
+    {
+        Status = PerformChannelConversion(StreamHeader->Data,
+                                          StreamHeader->DataUsed,
+                                          InputFormat->WaveFormatEx.nChannels,
+                                          OutputFormat->WaveFormatEx.nChannels,
+                                          InputFormat->WaveFormatEx.wBitsPerSample,
+                                          &BufferOut,
+                                          &BufferLength);
+
+        if (NT_SUCCESS(Status))
+        {
             ExFreePool(StreamHeader->Data);
             StreamHeader->Data = BufferOut;
             StreamHeader->DataUsed = BufferLength;