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/k... ============================================================================== --- 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);