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);