mirror of
https://github.com/reactos/reactos.git
synced 2025-05-29 05:58:13 +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
2 changed files with 193 additions and 29 deletions
|
@ -10,6 +10,140 @@
|
|||
|
||||
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(
|
||||
PUCHAR Buffer,
|
||||
|
@ -502,7 +636,7 @@ Pin_fnFastWrite(
|
|||
StreamHeader->DataUsed,
|
||||
InputFormat->WaveFormatEx.nChannels,
|
||||
OutputFormat->WaveFormatEx.nChannels,
|
||||
InputFormat->WaveFormatEx.wBitsPerSample,
|
||||
OutputFormat->WaveFormatEx.wBitsPerSample,
|
||||
&BufferOut,
|
||||
&BufferLength);
|
||||
|
||||
|
@ -516,9 +650,20 @@ Pin_fnFastWrite(
|
|||
|
||||
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 @@ CreatePin(
|
|||
|
||||
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 @@ void *memset(
|
|||
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 @@ void * memcpy(
|
|||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -201,6 +201,7 @@ CreatePinWorkerRoutine(
|
|||
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;
|
||||
|
@ -216,6 +217,11 @@ CreatePinWorkerRoutine(
|
|||
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 @@ CreatePinWorkerRoutine(
|
|||
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 @@ CreatePinWorkerRoutine(
|
|||
/* 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 @@ ComputeCompatibleFormat(
|
|||
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 @@ ComputeCompatibleFormat(
|
|||
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 */
|
||||
MixerFormat->WaveFormatEx.nSamplesPerSec = AudioRange->MaximumSampleFrequency;
|
||||
#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;
|
||||
#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);
|
||||
|
|
Loading…
Reference in a new issue