/* apply filter to an array of values, modifying the array in place */ public static void ApplyButterworthBandpassVectorModify( ButterworthBandpassRec Filter1, ButterworthBandpassRec Filter2, ButterworthBandpassRec Filter3, ButterworthBandpassRec Filter4, float[] Vector, int VectorOffset1, int VectorOffset2, int VectorOffset3, int VectorOffset4, int VectorLength) { IIR2DirectI_Parallel4( ref Filter1.iir, ref Filter2.iir, ref Filter3.iir, ref Filter4.iir, Vector, VectorOffset1, VectorOffset2, VectorOffset3, VectorOffset4, Vector, VectorOffset1, VectorOffset2, VectorOffset3, VectorOffset4, VectorLength); }
public static void SetResonantLowpassCoefficients( ResonantLowpassRec Filter, double Cutoff, double Bandwidth, double Gain, double SamplingRate) { if ((Cutoff == Filter.OldCutoff) && (Bandwidth == Filter.OldBandwidth) && (Gain == Filter.OldGain)) { return; } Filter.OldCutoff = Cutoff; Filter.OldBandwidth = Bandwidth; Filter.OldGain = Gain; if (Filter.NumLowpassSections != 0) { /* initialize first one */ ButterworthLowpassRec.ComputeButterworthLowpassCoefficients( ref Filter.iir[0], Cutoff, SamplingRate); /* copy to the others */ for (int i = 1; i < Filter.NumLowpassSections; i += 1) { Filter.iir[i].A0 = Filter.iir[0].A0; Filter.iir[i].A1 = Filter.iir[0].A1; Filter.iir[i].A2 = Filter.iir[0].A2; Filter.iir[i].B1 = Filter.iir[0].B1; Filter.iir[i].B2 = Filter.iir[0].B2; } } if (Filter.NumBandpassSections != 0) { /* initialize first one */ ButterworthBandpassRec.ComputeButterworthBandpassCoefficients( ref Filter.iir[Filter.NumLowpassSections + 0], Cutoff, Bandwidth, SamplingRate); /* copy to the others */ for (int i = 1; i < Filter.NumBandpassSections; i += 1) { Filter.iir[Filter.NumLowpassSections + i].A0 = Filter.iir[Filter.NumLowpassSections + 0].A0; Filter.iir[Filter.NumLowpassSections + i].A1 = Filter.iir[Filter.NumLowpassSections + 0].A1; Filter.iir[Filter.NumLowpassSections + i].A2 = Filter.iir[Filter.NumLowpassSections + 0].A2; Filter.iir[Filter.NumLowpassSections + i].B1 = Filter.iir[Filter.NumLowpassSections + 0].B1; Filter.iir[Filter.NumLowpassSections + i].B2 = Filter.iir[Filter.NumLowpassSections + 0].B2; } } Filter.BandpassGain = (float)Gain; }
/* apply filter to an array of values, modifying the array in place */ public static void ApplyButterworthBandpassVectorModify( ButterworthBandpassRec Filter, float[] Vector, int VectorOffset, int VectorLength) { IIR2DirectI( ref Filter.iir, Vector, VectorOffset, Vector, VectorOffset, VectorLength); }
public static void SetButterworthBandpassCoefficients( ButterworthBandpassRec Filter, double Cutoff, double Bandwidth, double SamplingRate) { if ((Cutoff == Filter.OldCutoff) && (Bandwidth == Filter.OldBandwidth)) { return; } Filter.OldCutoff = Cutoff; Filter.OldBandwidth = Bandwidth; ComputeButterworthBandpassCoefficients( ref Filter.iir, Cutoff, Bandwidth, 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) { ButterworthBandpassRec Filter = this; IIR2DirectIMAcc( ref Filter.iir, XinVector, XInVectorOffset, YoutVector, YoutVectorOffset, VectorLength, OutputScaling); }
/* apply filter to an array of values, adding result to output array */ public static void Apply4( ButterworthBandpassRec Filter1, ButterworthBandpassRec Filter2, ButterworthBandpassRec Filter3, ButterworthBandpassRec Filter4, float[] XinVector, int XInVectorOffset1, int XInVectorOffset2, int XInVectorOffset3, int XInVectorOffset4, float[] YoutVector, int YoutVectorOffset, int VectorLength, float OutputScaling1, float OutputScaling2, float OutputScaling3, float OutputScaling4, SynthParamRec SynthParams) { IIR2DirectIMAcc_Parallel4( ref Filter1.iir, ref Filter2.iir, ref Filter3.iir, ref Filter4.iir, XinVector, XInVectorOffset1, XInVectorOffset2, XInVectorOffset3, XInVectorOffset4, YoutVector, YoutVectorOffset, VectorLength, OutputScaling1, OutputScaling2, OutputScaling3, OutputScaling4); }
/* apply filter matrix to vector */ private static void ApplyVocoderMatrix( VocoderRec Vocoder, ButterworthBandpassRec[] BandMatrix, int BandMatrixOffset, float[] CombinedGainFactorVector, int CombinedGainFactorVectorOffset, float[] Vector, int VectorOffset, float[] SourceBase, int SourceOffset, float[] MangleBase, int MangleOffset, int Length, SynthParamRec SynthParams) { int BandCount = Vocoder.BandCount; int OrderCount = Vocoder.OrderCount; /* build source and initialize vector for output */ FloatVectorCopy( Vector, VectorOffset, SourceBase, SourceOffset, Length); FloatVectorZero( Vector, VectorOffset, Length); int i = 0; #if VECTOR if (EnableVector) { #if DEBUG Debug.Assert(!SynthParams.ScratchWorkspace2InUse); Debug.Assert(!SynthParams.ScratchWorkspace4InUse); SynthParams.ScratchWorkspace2InUse = true; SynthParams.ScratchWorkspace4InUse = true; #endif int MangleOffset2 = SynthParams.ScratchWorkspace2LOffset; int MangleOffset3 = SynthParams.ScratchWorkspace2ROffset; int MangleOffset4 = SynthParams.ScratchWorkspace4LOffset; /* process matrix */ for (; i <= BandCount - 4; i += 4) { /* initialize mangle vector with raw data */ FloatVectorCopy( SourceBase, SourceOffset, MangleBase, MangleOffset, Length); FloatVectorCopy( SourceBase, SourceOffset, MangleBase, MangleOffset2, Length); FloatVectorCopy( SourceBase, SourceOffset, MangleBase, MangleOffset3, Length); FloatVectorCopy( SourceBase, SourceOffset, MangleBase, MangleOffset4, Length); /* apply filters to succession, copying out on the last one */ for (int j = 0; j < OrderCount; j++) { if (j != OrderCount - 1) { /* interior filters modify the buffer, with unity gain */ ButterworthBandpassRec.ApplyButterworthBandpassVectorModify( BandMatrix[BandMatrixOffset + (i + 0) * OrderCount + j], BandMatrix[BandMatrixOffset + (i + 1) * OrderCount + j], BandMatrix[BandMatrixOffset + (i + 2) * OrderCount + j], BandMatrix[BandMatrixOffset + (i + 3) * OrderCount + j], MangleBase, MangleOffset, MangleOffset2, MangleOffset3, MangleOffset4, Length); } else { /* final filter adds to output */ ButterworthBandpassRec.Apply4( BandMatrix[BandMatrixOffset + (i + 0) * OrderCount + j], BandMatrix[BandMatrixOffset + (i + 1) * OrderCount + j], BandMatrix[BandMatrixOffset + (i + 2) * OrderCount + j], BandMatrix[BandMatrixOffset + (i + 3) * OrderCount + j], MangleBase, MangleOffset, MangleOffset2, MangleOffset3, MangleOffset4, Vector, VectorOffset, Length, CombinedGainFactorVector[CombinedGainFactorVectorOffset + i + 0], CombinedGainFactorVector[CombinedGainFactorVectorOffset + i + 1], CombinedGainFactorVector[CombinedGainFactorVectorOffset + i + 2], CombinedGainFactorVector[CombinedGainFactorVectorOffset + i + 3], SynthParams); } } } #if DEBUG SynthParams.ScratchWorkspace2InUse = false; SynthParams.ScratchWorkspace4InUse = false; #endif } #endif /* process matrix */ for (; i < BandCount; i++) { /* initialize mangle vector with raw data */ FloatVectorCopy( SourceBase, SourceOffset, MangleBase, MangleOffset, Length); /* apply filters to succession, copying out on the last one */ for (int j = 0; j < OrderCount; j++) { if (j != OrderCount - 1) { /* interior filters modify the buffer, with unity gain */ ButterworthBandpassRec.ApplyButterworthBandpassVectorModify( BandMatrix[BandMatrixOffset + i * OrderCount + j], MangleBase, MangleOffset, Length); } else { /* final filter adds to output */ BandMatrix[BandMatrixOffset + i * OrderCount + j].Apply( MangleBase, MangleOffset, Vector, VectorOffset, Length, CombinedGainFactorVector[CombinedGainFactorVectorOffset + i], SynthParams); } } } }
/* update a filter matrix given a wave table index and matrix base pointer */ /* first element in the list is the lowest ordered element in the wave table. */ /* wave index is scaled from 1 to #waves - 1 */ private static void VocoderUpdateMatrix( VocoderRec Vocoder, ButterworthBandpassRec[] BandMatrix, int BandMatrixOffset, float[] CombinedGainFactorVector, int CombinedGainFactorVectorOffset, SynthParamRec SynthParams) { int BandCount = Vocoder.BandCount; int OrderCount = Vocoder.OrderCount; float[][] WaveMatrix = Vocoder.WaveTableMatrix; float OverallGain = (float)Vocoder.CurrentOutputScaling; #if DEBUG if ((Vocoder.CurrentWaveTableIndex < 0) || (Vocoder.CurrentWaveTableIndex > Vocoder.NumberOfTablesMinus1)) { // table index out of range Debug.Assert(false); throw new InvalidOperationException(); } #endif if (((int)(Vocoder.CurrentWaveTableIndex) == Vocoder.NumberOfTablesMinus1) || !Vocoder.EnableCrossWaveTableInterpolation) { /* end interpolation */ float[] WaveData = WaveMatrix[(int)(Vocoder.CurrentWaveTableIndex)]; /* start at the beginning */ for (int i = 0; i < BandCount; i++) { /* L+F(R-L) */ /* consult wave table for center frequency */ float RawCenterFreq = WaveData[i * VOC_FIELDCOUNT + 0]; /* consult wave table for bandwidth */ float RawBandWidth = WaveData[i * VOC_FIELDCOUNT + 1]; /* consult wave table for gain */ float RawUncombinedGain = WaveData[i * VOC_FIELDCOUNT + 2]; /* do the mappings */ CombinedGainFactorVector[CombinedGainFactorVectorOffset + i] = RawUncombinedGain * OverallGain; double CookedCenterFreq = (VOC_MAXFREQ * 0.5) * (1 + (double)RawCenterFreq); double CookedBandWidth = (VOC_MAXFREQ * 0.5) * (1 + (double)RawBandWidth); /* set the settings */ for (int j = 0; j < OrderCount; j++) { ButterworthBandpassRec.SetButterworthBandpassCoefficients( BandMatrix[BandMatrixOffset + i * OrderCount + j], CookedCenterFreq, CookedBandWidth, SynthParams.dSamplingRate); } } } else { /* compute table weighting */ float Wave1Weight = (float)(Vocoder.CurrentWaveTableIndex - (int)(Vocoder.CurrentWaveTableIndex)); /* full interpolation */ float[] WaveData0 = WaveMatrix[(int)(Vocoder.CurrentWaveTableIndex)]; float[] WaveData1 = WaveMatrix[(int)(Vocoder.CurrentWaveTableIndex) + 1]; /* start at the beginning */ for (int i = 0; i < BandCount; i++) { float Wave0Value, Wave1Value; /* L+F(R-L) */ /* consult wave table for center frequency */ Wave0Value = WaveData0[i * VOC_FIELDCOUNT + 0]; Wave1Value = WaveData1[i * VOC_FIELDCOUNT + 0]; float RawCenterFreq = Wave0Value + (Wave1Weight * (Wave1Value - Wave0Value)); /* consult wave table for bandwidth */ Wave0Value = WaveData0[i * VOC_FIELDCOUNT + 1]; Wave1Value = WaveData1[i * VOC_FIELDCOUNT + 1]; float RawBandWidth = Wave0Value + (Wave1Weight * (Wave1Value - Wave0Value)); /* consult wave table for gain */ Wave0Value = WaveData0[i * VOC_FIELDCOUNT + 2]; Wave1Value = WaveData1[i * VOC_FIELDCOUNT + 2]; float RawUncombinedGain = Wave0Value + (Wave1Weight * (Wave1Value - Wave0Value)); /* do the mappings */ CombinedGainFactorVector[CombinedGainFactorVectorOffset + i] = RawUncombinedGain * OverallGain; double CookedCenterFreq = (VOC_MAXFREQ * 0.5) * (1 + (double)RawCenterFreq); double CookedBandWidth = (VOC_MAXFREQ * 0.5) * (1 + (double)RawBandWidth); /* set the settings */ for (int j = 0; j < OrderCount; j++) { ButterworthBandpassRec.SetButterworthBandpassCoefficients( BandMatrix[BandMatrixOffset + i * OrderCount + j], CookedCenterFreq, CookedBandWidth, SynthParams.dSamplingRate); } } } }