Exemplo n.º 1
0
        public ReverbState(ref ReverbParameter parameter, ulong workBuffer, bool isLongSizePreDelaySupported)
        {
            FdnDelayLines  = new DelayLine[4];
            DecayDelays    = new DecayDelay[4];
            EarlyDelayTime = new uint[EarlyModeCount];
            EarlyGain      = new float[EarlyModeCount];
            HighFrequencyDecayDirectGain   = new float[4];
            HighFrequencyDecayPreviousGain = new float[4];
            PreviousFeedbackOutput         = new float[4];

            ReadOnlySpan <float> fdnDelayTimes   = GetFdnDelayTimesByLateMode(ReverbLateMode.Limit);
            ReadOnlySpan <float> decayDelayTimes = GetDecayDelayTimesByLateMode(ReverbLateMode.Limit);

            uint sampleRate = (uint)FixedPointHelper.ToFloat((uint)parameter.SampleRate, FixedPointPrecision);

            for (int i = 0; i < 4; i++)
            {
                FdnDelayLines[i] = new DelayLine(sampleRate, fdnDelayTimes[i]);
                DecayDelays[i]   = new DecayDelay(new DelayLine(sampleRate, decayDelayTimes[i]));
            }

            float preDelayTimeMax = 150.0f;

            if (isLongSizePreDelaySupported)
            {
                preDelayTimeMax = 350.0f;
            }

            PreDelayLine         = new DelayLine(sampleRate, preDelayTimeMax);
            FrontCenterDelayLine = new DelayLine(sampleRate, 5.0f);

            UpdateParameter(ref parameter);
        }
Exemplo n.º 2
0
        private unsafe void ProcessDelayStereo(ref DelayState state, Span <IntPtr> outputBuffers, ReadOnlySpan <IntPtr> inputBuffers, uint sampleCount)
        {
            const ushort channelCount = 2;

            float delayFeedbackBaseGain  = state.DelayFeedbackBaseGain;
            float delayFeedbackCrossGain = state.DelayFeedbackCrossGain;
            float inGain  = FixedPointHelper.ToFloat(Parameter.InGain, FixedPointPrecision);
            float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision);
            float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision);

            Matrix2x2 delayFeedback = new Matrix2x2(delayFeedbackBaseGain, delayFeedbackCrossGain,
                                                    delayFeedbackCrossGain, delayFeedbackBaseGain);

            for (int i = 0; i < sampleCount; i++)
            {
                Vector2 channelInput = new Vector2
                {
                    X = *((float *)inputBuffers[0] + i) * 64,
                    Y = *((float *)inputBuffers[1] + i) * 64,
                };

                Vector2 delayLineValues = new Vector2()
                {
                    X = state.DelayLines[0].Read(),
                    Y = state.DelayLines[1].Read(),
                };

                Vector2 temp = MatrixHelper.Transform(ref channelInput, ref delayFeedback) + channelInput * inGain;

                state.UpdateLowPassFilter(ref Unsafe.As <Vector2, float>(ref temp), channelCount);

                *((float *)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64;
                *((float *)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64;
            }
        }
Exemplo n.º 3
0
        private void ProcessBiquadFilter(Span <float> outputBuffer, ReadOnlySpan <float> inputBuffer, uint sampleCount)
        {
            const int fixedPointPrecisionForParameter = 14;

            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);

            ref BiquadFilterState state = ref BiquadFilterState.Span[0];
Exemplo n.º 4
0
        private unsafe void ProcessDelaySurround(ref DelayState state, Span <IntPtr> outputBuffers, ReadOnlySpan <IntPtr> inputBuffers, uint sampleCount)
        {
            const ushort channelCount = 6;

            float feedbackGain           = FixedPointHelper.ToFloat(Parameter.FeedbackGain, FixedPointPrecision);
            float delayFeedbackBaseGain  = state.DelayFeedbackBaseGain;
            float delayFeedbackCrossGain = state.DelayFeedbackCrossGain;
            float inGain  = FixedPointHelper.ToFloat(Parameter.InGain, FixedPointPrecision);
            float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision);
            float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision);

            Matrix6x6 delayFeedback = new Matrix6x6(delayFeedbackBaseGain, 0.0f, 0.0f, 0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain,
                                                    0.0f, delayFeedbackBaseGain, 0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain, 0.0f,
                                                    delayFeedbackCrossGain, 0.0f, delayFeedbackBaseGain, delayFeedbackCrossGain, 0.0f, 0.0f,
                                                    0.0f, delayFeedbackCrossGain, delayFeedbackCrossGain, delayFeedbackBaseGain, 0.0f, 0.0f,
                                                    delayFeedbackCrossGain, delayFeedbackCrossGain, 0.0f, 0.0f, delayFeedbackBaseGain, 0.0f,
                                                    0.0f, 0.0f, 0.0f, 0.0f, 0.0f, feedbackGain);

            for (int i = 0; i < sampleCount; i++)
            {
                Vector6 channelInput = new Vector6
                {
                    X = *((float *)inputBuffers[0] + i) * 64,
                    Y = *((float *)inputBuffers[1] + i) * 64,
                    Z = *((float *)inputBuffers[2] + i) * 64,
                    W = *((float *)inputBuffers[3] + i) * 64,
                    V = *((float *)inputBuffers[4] + i) * 64,
                    U = *((float *)inputBuffers[5] + i) * 64
                };

                Vector6 delayLineValues = new Vector6
                {
                    X = state.DelayLines[0].Read(),
                    Y = state.DelayLines[1].Read(),
                    Z = state.DelayLines[2].Read(),
                    W = state.DelayLines[3].Read(),
                    V = state.DelayLines[4].Read(),
                    U = state.DelayLines[5].Read()
                };

                Vector6 temp = MatrixHelper.Transform(ref channelInput, ref delayFeedback) + channelInput * inGain;

                state.UpdateLowPassFilter(ref Unsafe.As <Vector6, float>(ref temp), channelCount);

                *((float *)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64;
                *((float *)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64;
                *((float *)outputBuffers[2] + i) = (channelInput.Z * dryGain + delayLineValues.Z * outGain) / 64;
                *((float *)outputBuffers[3] + i) = (channelInput.W * dryGain + delayLineValues.W * outGain) / 64;
                *((float *)outputBuffers[4] + i) = (channelInput.V * dryGain + delayLineValues.V * outGain) / 64;
                *((float *)outputBuffers[5] + i) = (channelInput.U * dryGain + delayLineValues.U * outGain) / 64;
            }
        }
Exemplo n.º 5
0
        public DelayState(ref DelayParameter parameter, ulong workBuffer)
        {
            DelayLines = new DelayLine[parameter.ChannelCount];
            LowPassZ   = new float[parameter.ChannelCount];

            uint sampleRate = (uint)FixedPointHelper.ToInt(parameter.SampleRate, FixedPointPrecision) / 1000;

            for (int i = 0; i < DelayLines.Length; i++)
            {
                DelayLines[i] = new DelayLine(sampleRate, parameter.DelayTimeMax);
                DelayLines[i].SetDelay(parameter.DelayTime);
            }

            UpdateParameter(ref parameter);
        }
Exemplo n.º 6
0
        private unsafe void ProcessDelayMono(ref DelayState state, float *outputBuffer, float *inputBuffer, uint sampleCount)
        {
            float feedbackGain = FixedPointHelper.ToFloat(Parameter.FeedbackGain, FixedPointPrecision);
            float inGain       = FixedPointHelper.ToFloat(Parameter.InGain, FixedPointPrecision);
            float dryGain      = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision);
            float outGain      = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision);

            for (int i = 0; i < sampleCount; i++)
            {
                float input          = inputBuffer[i] * 64;
                float delayLineValue = state.DelayLines[0].Read();

                float temp = input * inGain + delayLineValue * feedbackGain;

                state.UpdateLowPassFilter(ref temp, 1);

                outputBuffer[i] = (input * dryGain + delayLineValue * outGain) / 64;
            }
        }
Exemplo n.º 7
0
        public void UpdateParameter(ref DelayParameter parameter)
        {
            FeedbackGain = FixedPointHelper.ToFloat(parameter.FeedbackGain, FixedPointPrecision) * 0.98f;

            float channelSpread = FixedPointHelper.ToFloat(parameter.ChannelSpread, FixedPointPrecision);

            DelayFeedbackBaseGain = (1.0f - channelSpread) * FeedbackGain;

            if (parameter.ChannelCount == 4 || parameter.ChannelCount == 6)
            {
                DelayFeedbackCrossGain = channelSpread * 0.5f * FeedbackGain;
            }
            else
            {
                DelayFeedbackCrossGain = channelSpread * FeedbackGain;
            }

            LowPassFeedbackGain = 0.95f * FixedPointHelper.ToFloat(parameter.LowPassAmount, FixedPointPrecision);
            LowPassBaseGain     = 1.0f - LowPassFeedbackGain;
        }
Exemplo n.º 8
0
        private unsafe void ProcessDelaySurround(ref DelayState state, Span <IntPtr> outputBuffers, ReadOnlySpan <IntPtr> inputBuffers, uint sampleCount)
        {
            const ushort channelCount = 6;

            Span <float> channelInput    = stackalloc float[channelCount];
            Span <float> delayLineValues = stackalloc float[channelCount];
            Span <float> temp            = stackalloc float[channelCount];

            float delayFeedbackBaseGain  = state.DelayFeedbackBaseGain;
            float delayFeedbackCrossGain = state.DelayFeedbackCrossGain;
            float inGain  = FixedPointHelper.ToFloat(Parameter.InGain, FixedPointPrecision);
            float dryGain = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision);
            float outGain = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision);

            for (int i = 0; i < sampleCount; i++)
            {
                for (int j = 0; j < channelCount; j++)
                {
                    channelInput[j]    = *((float *)inputBuffers[j] + i) * 64;
                    delayLineValues[j] = state.DelayLines[j].Read();
                }

                temp[0] = channelInput[0] * inGain + (delayLineValues[2] + delayLineValues[4]) * delayFeedbackCrossGain + delayLineValues[0] * delayFeedbackBaseGain;
                temp[1] = channelInput[1] * inGain + (delayLineValues[4] + delayLineValues[3]) * delayFeedbackCrossGain + delayLineValues[1] * delayFeedbackBaseGain;
                temp[2] = channelInput[2] * inGain + (delayLineValues[3] + delayLineValues[0]) * delayFeedbackCrossGain + delayLineValues[2] * delayFeedbackBaseGain;
                temp[3] = channelInput[3] * inGain + (delayLineValues[1] + delayLineValues[2]) * delayFeedbackCrossGain + delayLineValues[3] * delayFeedbackBaseGain;
                temp[4] = channelInput[4] * inGain + (delayLineValues[0] + delayLineValues[1]) * delayFeedbackCrossGain + delayLineValues[4] * delayFeedbackBaseGain;
                temp[5] = channelInput[5] * inGain + delayLineValues[5] * delayFeedbackBaseGain;

                for (int j = 0; j < channelCount; j++)
                {
                    float lowPassResult = state.LowPassFeedbackGain * state.LowPassZ[j] + temp[j] * state.LowPassBaseGain;

                    state.LowPassZ[j] = lowPassResult;
                    state.DelayLines[j].Update(lowPassResult);

                    *((float *)outputBuffers[j] + i) = (channelInput[j] * dryGain + delayLineValues[j] * outGain) / 64;
                }
            }
        }
Exemplo n.º 9
0
        private void ProcessBiquadFilter(ref BiquadFilterState state, Span <float> outputBuffer, ReadOnlySpan <float> inputBuffer, uint sampleCount)
        {
            const int fixedPointPrecisionForParameter = 14;

            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.Z1;

                state.Z1 = input * a1 + output * b1 + state.Z2;
                state.Z2 = input * a2 + output * b2;

                outputBuffer[i] = output;
            }
        }
Exemplo n.º 10
0
        public void UpdateParameter(ref ReverbParameter parameter)
        {
            uint sampleRate = (uint)FixedPointHelper.ToFloat((uint)parameter.SampleRate, FixedPointPrecision);

            float preDelayTimeInMilliseconds = FixedPointHelper.ToFloat(parameter.PreDelayTime, FixedPointPrecision);
            float earlyGain  = FixedPointHelper.ToFloat(parameter.EarlyGain, FixedPointPrecision);
            float coloration = FixedPointHelper.ToFloat(parameter.Coloration, FixedPointPrecision);
            float decayTime  = FixedPointHelper.ToFloat(parameter.DecayTime, FixedPointPrecision);

            for (int i = 0; i < 10; i++)
            {
                EarlyDelayTime[i] = Math.Min(IDelayLine.GetSampleCount(sampleRate, EarlyDelayTimes[i] + preDelayTimeInMilliseconds), PreDelayLine.SampleCountMax) + 1;
                EarlyGain[i]      = EarlyGainBase[i] * earlyGain;
            }

            if (parameter.ChannelCount == 2)
            {
                EarlyGain[4] = EarlyGain[4] * 0.5f;
                EarlyGain[5] = EarlyGain[5] * 0.5f;
            }

            PreDelayLineDelayTime = Math.Min(IDelayLine.GetSampleCount(sampleRate, PreDelayTimes[(int)parameter.EarlyMode] + preDelayTimeInMilliseconds), PreDelayLine.SampleCountMax);

            ReadOnlySpan <float> fdnDelayTimes   = GetFdnDelayTimesByLateMode(parameter.LateMode);
            ReadOnlySpan <float> decayDelayTimes = GetDecayDelayTimesByLateMode(parameter.LateMode);

            float highFrequencyDecayRatio   = FixedPointHelper.ToFloat(parameter.HighFrequencyDecayRatio, FixedPointPrecision);
            float highFrequencyUnknownValue = FloatingPointHelper.Cos(1280.0f / sampleRate);

            for (int i = 0; i < 4; i++)
            {
                FdnDelayLines[i].SetDelay(fdnDelayTimes[i]);
                DecayDelays[i].SetDelay(decayDelayTimes[i]);

                float tempA = -3 * (DecayDelays[i].CurrentSampleCount + FdnDelayLines[i].CurrentSampleCount);
                float tempB = tempA / (decayTime * sampleRate);
                float tempC;
                float tempD;

                if (highFrequencyDecayRatio < 0.995f)
                {
                    float tempE = FloatingPointHelper.Pow10((((1.0f / highFrequencyDecayRatio) - 1.0f) * 2) / 100 * (tempB / 10));
                    float tempF = 1.0f - tempE;
                    float tempG = 2.0f - (tempE * 2 * highFrequencyUnknownValue);
                    float tempH = MathF.Sqrt((tempG * tempG) - (tempF * tempF * 4));

                    tempC = (tempG - tempH) / (tempF * 2);
                    tempD = 1.0f - tempC;
                }
                else
                {
                    // no high frequency decay ratio
                    tempC = 0.0f;
                    tempD = 1.0f;
                }

                HighFrequencyDecayDirectGain[i]   = FloatingPointHelper.Pow10(tempB / 1000) * tempD * 0.7071f;
                HighFrequencyDecayPreviousGain[i] = tempC;
                PreviousFeedbackOutput[i]         = 0.0f;

                DecayDelays[i].SetDecayRate(0.6f * (1.0f - coloration));
            }
        }
Exemplo n.º 11
0
        private unsafe void ProcessReverbGeneric(ref ReverbState state, ReadOnlySpan <IntPtr> outputBuffers, ReadOnlySpan <IntPtr> inputBuffers, uint sampleCount, ReadOnlySpan <int> outputEarlyIndicesTable, ReadOnlySpan <int> targetEarlyDelayLineIndicesTable, ReadOnlySpan <int> targetOutputFeedbackIndicesTable, ReadOnlySpan <int> outputIndicesTable)
        {
            bool isSurround = Parameter.ChannelCount == 6;

            float reverbGain = FixedPointHelper.ToFloat(Parameter.ReverbGain, FixedPointPrecision);
            float lateGain   = FixedPointHelper.ToFloat(Parameter.LateGain, FixedPointPrecision);
            float outGain    = FixedPointHelper.ToFloat(Parameter.OutGain, FixedPointPrecision);
            float dryGain    = FixedPointHelper.ToFloat(Parameter.DryGain, FixedPointPrecision);

            Span <float> outputValues         = stackalloc float[Constants.ChannelCountMax];
            Span <float> feedbackValues       = stackalloc float[4];
            Span <float> feedbackOutputValues = stackalloc float[4];
            Span <float> channelInput         = stackalloc float[Parameter.ChannelCount];

            for (int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)
            {
                outputValues.Fill(0);

                for (int i = 0; i < targetEarlyDelayLineIndicesTable.Length; i++)
                {
                    int earlyDelayIndex = targetEarlyDelayLineIndicesTable[i];
                    int outputIndex     = outputEarlyIndicesTable[i];

                    float tapOutput = state.PreDelayLine.TapUnsafe(state.EarlyDelayTime[earlyDelayIndex], 0);

                    outputValues[outputIndex] += tapOutput * state.EarlyGain[earlyDelayIndex];
                }

                if (isSurround)
                {
                    outputValues[5] *= 0.2f;
                }

                float targetPreDelayValue = 0;

                for (int channelIndex = 0; channelIndex < Parameter.ChannelCount; channelIndex++)
                {
                    channelInput[channelIndex] = *((float *)inputBuffers[channelIndex] + sampleIndex) * 64;
                    targetPreDelayValue       += channelInput[channelIndex] * reverbGain;
                }

                state.PreDelayLine.Update(targetPreDelayValue);

                float lateValue = state.PreDelayLine.Tap(state.PreDelayLineDelayTime) * lateGain;

                for (int i = 0; i < state.FdnDelayLines.Length; i++)
                {
                    feedbackOutputValues[i]         = state.FdnDelayLines[i].Read() * state.HighFrequencyDecayDirectGain[i] + state.PreviousFeedbackOutput[i] * state.HighFrequencyDecayPreviousGain[i];
                    state.PreviousFeedbackOutput[i] = feedbackOutputValues[i];
                }

                feedbackValues[0] = feedbackOutputValues[2] + feedbackOutputValues[1];
                feedbackValues[1] = -feedbackOutputValues[0] - feedbackOutputValues[3];
                feedbackValues[2] = feedbackOutputValues[0] - feedbackOutputValues[3];
                feedbackValues[3] = feedbackOutputValues[1] - feedbackOutputValues[2];

                for (int i = 0; i < state.FdnDelayLines.Length; i++)
                {
                    feedbackOutputValues[i] = state.DecayDelays[i].Update(feedbackValues[i] + lateValue);
                    state.FdnDelayLines[i].Update(feedbackOutputValues[i]);
                }

                for (int i = 0; i < targetOutputFeedbackIndicesTable.Length; i++)
                {
                    int targetOutputFeedbackIndex = targetOutputFeedbackIndicesTable[i];
                    int outputIndex = outputIndicesTable[i];

                    if (targetOutputFeedbackIndex >= 0)
                    {
                        outputValues[outputIndex] += feedbackOutputValues[targetOutputFeedbackIndex];
                    }
                }

                if (isSurround)
                {
                    outputValues[4] += state.FrontCenterDelayLine.Update((feedbackOutputValues[2] - feedbackOutputValues[3]) * 0.5f);
                }

                for (int channelIndex = 0; channelIndex < Parameter.ChannelCount; channelIndex++)
                {
                    *((float *)outputBuffers[channelIndex] + sampleIndex) = (outputValues[channelIndex] * outGain + channelInput[channelIndex] * dryGain) / 64;
                }
            }
        }