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;
            }
        }
Exemple #3
0
        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);
        }