mirror of
https://github.com/reactos/reactos.git
synced 2024-07-28 15:19:09 +00:00
- 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 svn path=/trunk/; revision=40524
This commit is contained in:
parent
2b9ed04e31
commit
27c2bd90eb
|
@ -10,6 +10,140 @@
|
||||||
|
|
||||||
const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
|
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
|
NTSTATUS
|
||||||
PerformChannelConversion(
|
PerformChannelConversion(
|
||||||
PUCHAR Buffer,
|
PUCHAR Buffer,
|
||||||
|
@ -502,7 +636,7 @@ Pin_fnFastWrite(
|
||||||
StreamHeader->DataUsed,
|
StreamHeader->DataUsed,
|
||||||
InputFormat->WaveFormatEx.nChannels,
|
InputFormat->WaveFormatEx.nChannels,
|
||||||
OutputFormat->WaveFormatEx.nChannels,
|
OutputFormat->WaveFormatEx.nChannels,
|
||||||
InputFormat->WaveFormatEx.wBitsPerSample,
|
OutputFormat->WaveFormatEx.wBitsPerSample,
|
||||||
&BufferOut,
|
&BufferOut,
|
||||||
&BufferLength);
|
&BufferLength);
|
||||||
|
|
||||||
|
@ -516,9 +650,20 @@ Pin_fnFastWrite(
|
||||||
|
|
||||||
if (InputFormat->WaveFormatEx.nSamplesPerSec != OutputFormat->WaveFormatEx.nSamplesPerSec)
|
if (InputFormat->WaveFormatEx.nSamplesPerSec != OutputFormat->WaveFormatEx.nSamplesPerSec)
|
||||||
{
|
{
|
||||||
/* sample format conversion must be done in a deferred routine */
|
Status = PerformSampleRateConversion(StreamHeader->Data,
|
||||||
DPRINT1("SampleRate conversion not available yet %u %u\n", InputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.nSamplesPerSec);
|
StreamHeader->DataUsed,
|
||||||
return FALSE;
|
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))
|
if (NT_SUCCESS(Status))
|
||||||
|
@ -567,9 +712,13 @@ CreatePin(
|
||||||
|
|
||||||
void * calloc(size_t Elements, size_t ElementSize)
|
void * calloc(size_t Elements, size_t ElementSize)
|
||||||
{
|
{
|
||||||
PVOID Block = ExAllocatePool(NonPagedPool, Elements * ElementSize);
|
ULONG Index;
|
||||||
if (Block)
|
PUCHAR Block = ExAllocatePool(NonPagedPool, Elements * ElementSize);
|
||||||
RtlZeroMemory(Block, Elements * ElementSize);
|
if (!Block)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for(Index = 0; Index < Elements * ElementSize; Index++)
|
||||||
|
Block[Index] = 0;
|
||||||
|
|
||||||
return Block;
|
return Block;
|
||||||
}
|
}
|
||||||
|
@ -584,7 +733,12 @@ void *memset(
|
||||||
int c,
|
int c,
|
||||||
size_t count)
|
size_t count)
|
||||||
{
|
{
|
||||||
RtlFillMemory(dest, count, c);
|
ULONG Index;
|
||||||
|
PUCHAR Block = (PUCHAR)dest;
|
||||||
|
|
||||||
|
for(Index = 0; Index < count; Index++)
|
||||||
|
Block[Index] = c;
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,18 +747,10 @@ void * memcpy(
|
||||||
const void* src,
|
const void* src,
|
||||||
size_t count)
|
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;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *memmove(
|
|
||||||
void* dest,
|
|
||||||
const void* src,
|
|
||||||
size_t count)
|
|
||||||
{
|
|
||||||
RtlMoveMemory(dest, src, count);
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -201,6 +201,7 @@ CreatePinWorkerRoutine(
|
||||||
PFILE_OBJECT RealFileObject = NULL, VirtualFileObject = NULL;
|
PFILE_OBJECT RealFileObject = NULL, VirtualFileObject = NULL;
|
||||||
PSYSAUDIO_CLIENT AudioClient;
|
PSYSAUDIO_CLIENT AudioClient;
|
||||||
PSYSAUDIO_PIN_HANDLE ClientPinHandle;
|
PSYSAUDIO_PIN_HANDLE ClientPinHandle;
|
||||||
|
PKSDATAFORMAT_WAVEFORMATEX InputFormat;
|
||||||
PKSDATAFORMAT_WAVEFORMATEX OutputFormat = NULL;
|
PKSDATAFORMAT_WAVEFORMATEX OutputFormat = NULL;
|
||||||
PKSPIN_CONNECT MixerPinConnect = NULL;
|
PKSPIN_CONNECT MixerPinConnect = NULL;
|
||||||
PPIN_WORKER_CONTEXT WorkerContext = (PPIN_WORKER_CONTEXT)Context;
|
PPIN_WORKER_CONTEXT WorkerContext = (PPIN_WORKER_CONTEXT)Context;
|
||||||
|
@ -216,6 +217,11 @@ CreatePinWorkerRoutine(
|
||||||
ASSERT(WorkerContext->Entry->Pins);
|
ASSERT(WorkerContext->Entry->Pins);
|
||||||
ASSERT(WorkerContext->Entry->NumberOfPins > WorkerContext->PinConnect->PinId);
|
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 */
|
/* Let's try to create the audio irp pin */
|
||||||
Status = KsCreatePin(WorkerContext->Entry->Handle, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle);
|
Status = KsCreatePin(WorkerContext->Entry->Handle, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle);
|
||||||
|
|
||||||
|
@ -258,6 +264,8 @@ CreatePinWorkerRoutine(
|
||||||
KeBugCheck(0);
|
KeBugCheck(0);
|
||||||
return;
|
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 */
|
/* get pin file object */
|
||||||
|
@ -286,15 +294,10 @@ CreatePinWorkerRoutine(
|
||||||
/* Do we need to transform the audio stream */
|
/* Do we need to transform the audio stream */
|
||||||
if (OutputFormat != NULL)
|
if (OutputFormat != NULL)
|
||||||
{
|
{
|
||||||
PKSDATAFORMAT InputFormat;
|
|
||||||
|
|
||||||
/* Fetch input format */
|
|
||||||
InputFormat = (PKSDATAFORMAT)(WorkerContext->PinConnect + 1);
|
|
||||||
|
|
||||||
/* Now create the mixer pin */
|
/* Now create the mixer pin */
|
||||||
Status = CreateMixerPinAndSetFormat(WorkerContext->DeviceExtension->KMixerHandle,
|
Status = CreateMixerPinAndSetFormat(WorkerContext->DeviceExtension->KMixerHandle,
|
||||||
MixerPinConnect,
|
MixerPinConnect,
|
||||||
InputFormat,
|
(PKSDATAFORMAT)InputFormat,
|
||||||
(PKSDATAFORMAT)OutputFormat,
|
(PKSDATAFORMAT)OutputFormat,
|
||||||
&WorkerContext->DispatchContext->hMixerPin,
|
&WorkerContext->DispatchContext->hMixerPin,
|
||||||
&WorkerContext->DispatchContext->MixerFileObject);
|
&WorkerContext->DispatchContext->MixerFileObject);
|
||||||
|
@ -583,6 +586,7 @@ ComputeCompatibleFormat(
|
||||||
AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize);
|
AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize);
|
||||||
}
|
}
|
||||||
/* Select best quality available */
|
/* Select best quality available */
|
||||||
|
|
||||||
MixerFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX);
|
MixerFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX);
|
||||||
MixerFormat->DataFormat.Flags = 0;
|
MixerFormat->DataFormat.Flags = 0;
|
||||||
MixerFormat->DataFormat.Reserved = 0;
|
MixerFormat->DataFormat.Reserved = 0;
|
||||||
|
@ -591,9 +595,23 @@ ComputeCompatibleFormat(
|
||||||
MixerFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
|
MixerFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
|
||||||
MixerFormat->DataFormat.SampleSize = 4;
|
MixerFormat->DataFormat.SampleSize = 4;
|
||||||
MixerFormat->WaveFormatEx.wFormatTag = ClientFormat->WaveFormatEx.wFormatTag;
|
MixerFormat->WaveFormatEx.wFormatTag = ClientFormat->WaveFormatEx.wFormatTag;
|
||||||
MixerFormat->WaveFormatEx.nChannels = min(2, AudioRange->MaximumChannels); /* AC97 does not support mono render / record */
|
#ifndef NO_AC97_HACK
|
||||||
MixerFormat->WaveFormatEx.nSamplesPerSec = AudioRange->MaximumSampleFrequency;
|
/* 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;
|
MixerFormat->WaveFormatEx.wBitsPerSample = AudioRange->MaximumBitsPerSample;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef KMIXER_RESAMPLING_IMPLEMENTED
|
||||||
|
MixerFormat->WaveFormatEx.nSamplesPerSec = AudioRange->MaximumSampleFrequency;
|
||||||
|
#else
|
||||||
|
MixerFormat->WaveFormatEx.nSamplesPerSec = max(AudioRange->MinimumSampleFrequency, min(ClientFormat->WaveFormatEx.nSamplesPerSec, AudioRange->MaximumSampleFrequency));
|
||||||
|
#endif
|
||||||
|
|
||||||
MixerFormat->WaveFormatEx.cbSize = 0;
|
MixerFormat->WaveFormatEx.cbSize = 0;
|
||||||
MixerFormat->WaveFormatEx.nBlockAlign = (MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.wBitsPerSample) / 8;
|
MixerFormat->WaveFormatEx.nBlockAlign = (MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.wBitsPerSample) / 8;
|
||||||
MixerFormat->WaveFormatEx.nAvgBytesPerSec = MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.nSamplesPerSec * (MixerFormat->WaveFormatEx.wBitsPerSample / 8);
|
MixerFormat->WaveFormatEx.nAvgBytesPerSec = MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.nSamplesPerSec * (MixerFormat->WaveFormatEx.wBitsPerSample / 8);
|
||||||
|
|
Loading…
Reference in a new issue