public static void ProcessBiquadFilter(ReadOnlySpan <BiquadFilterParameter> parameters, Span <BiquadFilterState> states, Span <float> outputBuffer, ReadOnlySpan <float> inputBuffer, uint sampleCount) { for (int stageIndex = 0; stageIndex < parameters.Length; stageIndex++) { BiquadFilterParameter parameter = parameters[stageIndex]; ref BiquadFilterState state = ref states[stageIndex]; float a0 = FixedPointHelper.ToFloat(parameter.Numerator[0], FixedPointPrecisionForParameter); float a1 = FixedPointHelper.ToFloat(parameter.Numerator[1], FixedPointPrecisionForParameter); float a2 = FixedPointHelper.ToFloat(parameter.Numerator[2], FixedPointPrecisionForParameter); float b1 = FixedPointHelper.ToFloat(parameter.Denominator[0], FixedPointPrecisionForParameter); float b2 = FixedPointHelper.ToFloat(parameter.Denominator[1], FixedPointPrecisionForParameter); for (int i = 0; i < sampleCount; i++) { float input = inputBuffer[i]; float output = input * a0 + state.State0 * a1 + state.State1 * a2 + state.State2 * b1 + state.State3 * b2; state.State1 = state.State0; state.State0 = input; state.State3 = state.State2; state.State2 = output; outputBuffer[i] = output; } }
public static void ProcessBiquadFilter(ref BiquadFilterParameter parameter, ref BiquadFilterState state, Span <float> outputBuffer, ReadOnlySpan <float> inputBuffer, uint sampleCount) { float a0 = FixedPointHelper.ToFloat(parameter.Numerator[0], FixedPointPrecisionForParameter); float a1 = FixedPointHelper.ToFloat(parameter.Numerator[1], FixedPointPrecisionForParameter); float a2 = FixedPointHelper.ToFloat(parameter.Numerator[2], FixedPointPrecisionForParameter); float b1 = FixedPointHelper.ToFloat(parameter.Denominator[0], FixedPointPrecisionForParameter); float b2 = FixedPointHelper.ToFloat(parameter.Denominator[1], FixedPointPrecisionForParameter); for (int i = 0; i < sampleCount; i++) { float input = inputBuffer[i]; float output = input * a0 + state.State0; state.State0 = input * a1 + output * b1 + state.State1; state.State1 = input * a2 + output * b2; outputBuffer[i] = output; } }
public static int Decode(Span <short> output, ReadOnlySpan <byte> input, int startSampleOffset, int endSampleOffset, int offset, int count, ReadOnlySpan <short> coefficients, ref AdpcmLoopContext loopContext) { if (input.IsEmpty || endSampleOffset < startSampleOffset) { return(0); } byte predScale = (byte)loopContext.PredScale; byte scale = (byte)(predScale & 0xF); byte coefficientIndex = (byte)((predScale >> 4) & 0xF); short history0 = loopContext.History0; short history1 = loopContext.History1; short coefficient0 = coefficients[coefficientIndex * 2 + 0]; short coefficient1 = coefficients[coefficientIndex * 2 + 1]; int decodedCount = Math.Min(count, endSampleOffset - startSampleOffset - offset); int nibbles = GetNibblesFromSampleCount(offset + startSampleOffset); int remaining = decodedCount; int outputBufferIndex = 0; int inputIndex = 0; ReadOnlySpan <byte> targetInput; targetInput = input.Slice(nibbles / 2); while (remaining > 0) { int samplesCount; if (((uint)nibbles % NibblesPerFrame) == 0) { predScale = targetInput[inputIndex++]; scale = (byte)(predScale & 0xF); coefficientIndex = (byte)((predScale >> 4) & 0xF); coefficient0 = coefficients[coefficientIndex * 2 + 0]; coefficient1 = coefficients[coefficientIndex * 2 + 1]; nibbles += 2; samplesCount = Math.Min(remaining, SamplesPerFrame); } else { samplesCount = 1; } int scaleFixedPoint = FixedPointHelper.ToFixed(1.0f, FixedPointPrecision) << scale; if (samplesCount < SamplesPerFrame) { for (int i = 0; i < samplesCount; i++) { int value = targetInput[inputIndex]; int sample; if ((nibbles & 1) != 0) { sample = (value << 28) >> 28; inputIndex++; } else { sample = (value << 24) >> 28; } nibbles++; int prediction = coefficient0 * history0 + coefficient1 * history1; sample = FixedPointHelper.RoundUpAndToInt(sample * scaleFixedPoint + prediction, FixedPointPrecision); short saturatedSample = Saturate(sample); history1 = history0; history0 = saturatedSample; output[outputBufferIndex++] = saturatedSample; remaining--; } } else { for (int i = 0; i < SamplesPerFrame / 2; i++) { int value = targetInput[inputIndex]; int sample0; int sample1; sample0 = (value << 24) >> 28; sample1 = (value << 28) >> 28; inputIndex++; int prediction0 = coefficient0 * history0 + coefficient1 * history1; sample0 = FixedPointHelper.RoundUpAndToInt(sample0 * scaleFixedPoint + prediction0, FixedPointPrecision); short saturatedSample0 = Saturate(sample0); int prediction1 = coefficient0 * saturatedSample0 + coefficient1 * history0; sample1 = FixedPointHelper.RoundUpAndToInt(sample1 * scaleFixedPoint + prediction1, FixedPointPrecision); short saturatedSample1 = Saturate(sample1); history1 = saturatedSample0; history0 = saturatedSample1; output[outputBufferIndex++] = saturatedSample0; output[outputBufferIndex++] = saturatedSample1; } nibbles += SamplesPerFrame; remaining -= SamplesPerFrame; } } loopContext.PredScale = predScale; loopContext.History0 = history0; loopContext.History1 = history1; return(decodedCount); }