public static void SetResonantLowpass2Coefficients( ResonantLowpass2Rec Filter, double Cutoff, double Q, double SamplingRate) { if ((Cutoff == Filter.OldCutoff) && (Q == Filter.OldQ)) { return; } Filter.OldCutoff = Cutoff; Filter.OldQ = Q; ComputeResonantLowpass2Coefficients( ref Filter.iir0, ref Filter.iir1, ref Filter.iir2, Filter.Order, Cutoff, Q, SamplingRate); }
/* apply filter to an array of values, adding result to output array */ public void Apply( float[] XinVector, int XinVectorOffset, float[] YoutVector, int YoutVectorOffset, int VectorLength, float OutputScaling, SynthParamRec SynthParams) { ResonantLowpass2Rec Filter = this; // ScratchWorkspace1* is used in ApplyUnifiedFilterArray() #if DEBUG Debug.Assert(!SynthParams.ScratchWorkspace2InUse); SynthParams.ScratchWorkspace2InUse = true; #endif float[] ScratchVector = XinVector /*sic*/; int ScratchVectorOffset = SynthParams.ScratchWorkspace2LOffset; int Order2 = Filter.Order / 2; if (Order2 == 1) { IIR2DirectIIMAcc( ref Filter.iir0, XinVector, XinVectorOffset, YoutVector, YoutVectorOffset, VectorLength, OutputScaling); } else { // In the old code there was a bad bug where the last biquad section was applied // from the original input to the output, causing all the intermediate results // from previous biquads to be disregarded. Naturally, this causes a very different // sound, which has already been used. Therefore, there is an option to enable // the old behavior. if (!Filter.broken) { // The correct implementation if (Order2 == 2) { /* first section enters local workspace */ IIR2DirectII( ref Filter.iir0, XinVector, XinVectorOffset, ScratchVector, ScratchVectorOffset, VectorLength); /* final section goes into output */ IIR2DirectIIMAcc( ref Filter.iir1, ScratchVector, // NB: in defective version this was XinVector ScratchVectorOffset, YoutVector, YoutVectorOffset, VectorLength, OutputScaling); } else { #if DEBUG Debug.Assert(Order2 == 3); #endif /* first section enters local workspace */ IIR2DirectII( ref Filter.iir0, XinVector, XinVectorOffset, ScratchVector, ScratchVectorOffset, VectorLength); /* intermediate sections */ IIR2DirectII( ref Filter.iir1, ScratchVector, ScratchVectorOffset, ScratchVector, ScratchVectorOffset, VectorLength); /* final section goes into output */ IIR2DirectIIMAcc( ref Filter.iir2, ScratchVector, // NB: in defective version this was XinVector ScratchVectorOffset, YoutVector, YoutVectorOffset, VectorLength, OutputScaling); } } else { // The old broken buggy defective implementation if (Order2 == 2) { /* final section goes into output */ IIR2DirectIIMAcc( ref Filter.iir1, XinVector, // this should have been Workspace XinVectorOffset, YoutVector, YoutVectorOffset, VectorLength, OutputScaling); } else { #if DEBUG Debug.Assert(Order2 == 3); #endif /* final section goes into output */ IIR2DirectIIMAcc( ref Filter.iir2, XinVector, // this should have been Workspace XinVectorOffset, YoutVector, YoutVectorOffset, VectorLength, OutputScaling); } } } #if DEBUG SynthParams.ScratchWorkspace2InUse = false; #endif }