/// <summary> /// /// </summary> /// <param name="audio"></param> /// <param name="samplingRate"></param> /// <param name="passbandFrequency"></param> /// <param name="stopbandFrequency"></param> /// <param name="passbandAttenuation"></param> /// <param name="stopbandAttenuation"></param> /// <returns></returns> public static double[] LowpassFilteringType1(double[] audio, uint samplingRate, uint passbandFrequency, uint stopbandFrequency, float passbandAttenuation, float stopbandAttenuation) { const double PI = Math.PI; double wPass = (2 * PI * passbandFrequency) / samplingRate; //same problem with negative N's as with the highpass filter double wStop = (2 * PI * stopbandFrequency) / samplingRate; double omegaPass = Math.Tan(wPass / 2); double omegaStop = Math.Tan(wStop / 2); double ePass = Math.Sqrt(Math.Pow(10, (passbandAttenuation / 10)) - 1); double eStop = Math.Sqrt(Math.Pow(10, (stopbandAttenuation / 10)) - 1); double w = omegaStop / omegaPass; double e = eStop / ePass; double nExact = (Math.Log(e + Math.Sqrt(Math.Pow(e, 2) - 1))) / (Math.Log(w + Math.Sqrt(Math.Pow(w, 2) - 1))); int nUsed = (int)Math.Ceiling(nExact); int k = (int)Math.Floor(nUsed / 2d); double a = 1d / (double)nUsed * Math.Log(1d / ePass + Math.Sqrt(1d / Math.Pow(ePass, 2) + 1)); double omega0 = omegaPass * Math.Sinh(a); double[] omega = new double[k]; double[] theta = new double[k]; for (int i = 0; i < k; i++) { theta[i] = (PI / (2 * nUsed)) * (nUsed - 1 + (2 * (i + 1))); omega[i] = omegaPass * Math.Sin(theta[i]); } double[] filterCoefficientG = new double[(int)k + 1]; double[,] filterCoefficientA = new double[(int)k + 1, 2]; double[,] filterCoefficientB = new double[(int)k + 1, 3]; double[] matrixBHelp = { 1, 1, 0 }; for (int i = 0; i < k; i++) { filterCoefficientG[i + 1] = (Math.Pow(omega0, 2) + Math.Pow(omega[i], 2)) / (1 - 2 * omega0 * Math.Cos(theta[i]) + Math.Pow(omega0, 2) + Math.Pow(omega[i], 2)); filterCoefficientA[i + 1, 0] = (2 * (Math.Pow(omega0, 2) + Math.Pow(omega[i], 2) - 1)) / (1 - 2 * omega0 * Math.Cos(theta[i]) + Math.Pow(omega0, 2) + Math.Pow(omega[i], 2)); filterCoefficientA[i + 1, 1] = (1 + 2 * omega0 * Math.Cos(theta[i]) + Math.Pow(omega0, 2) + Math.Pow(omega[i], 2)) / (1 - 2 * omega0 * Math.Cos(theta[i]) + Math.Pow(omega0, 2) + Math.Pow(omega[i], 2)); filterCoefficientB[i + 1, 0] = filterCoefficientG[i + 1] * 1; filterCoefficientB[i + 1, 1] = filterCoefficientG[i + 1] * 2; filterCoefficientB[i + 1, 2] = filterCoefficientG[i + 1] * 1; } if (nUsed % 2 != 0) { filterCoefficientG[0] = omega0 / (omega0 + 1); filterCoefficientA[0, 0] = (omega0 - 1) / (omega0 + 1); filterCoefficientA[0, 1] = 0; for (int i = 0; i < 2; i++) { filterCoefficientB[0, i] = filterCoefficientG[0] * matrixBHelp[i]; } } return(FilteringClass.SOSFiltering(audio, filterCoefficientA, filterCoefficientB, nUsed)); }
/// <summary> /// Butterworth lowpass filtering with parameters calculated from /// <paramref name="passbandFrequency"/>, <paramref name="stopbandFrequency"/>, <paramref name="passbandAttenuation"/> and <paramref name="stopbandAttenuation"/>. /// </summary> /// <param name="audio">Audio to filter.</param> /// <param name="samplingRate">Sampling Rate of the audio to be processed.</param> /// <param name="passbandFrequency">The ordinary frequency of the passband.</param> /// <param name="stopbandFrequency">The ordinary frequency of the stopband.</param> /// <param name="passbandAttenuation">The attenuation in dB of the passband.</param> /// <param name="stopbandAttenuation">The attenuation in dB of the stopband.</param> /// <returns>Returns the filtered version of <paramref name="audio"/></returns> static public double[] LowpassFiltering(double[] audio, uint samplingRate, uint passbandFrequency, uint stopbandFrequency, float passbandAttenuation, float stopbandAttenuation) { const double PI = Math.PI; uint fPass = passbandFrequency; uint fStop = stopbandFrequency; float aPass = passbandAttenuation; float aStop = stopbandAttenuation; double wPass; double wStop; double omegaPass; double omegaStop; double ePass; double eStop; double w; double passE; double nExact; int nUsed; double omega0; double[] theta; double[] thetaD; double[] filterCoefficientG; double[,] filterCoefficientA; double[,] filterCoefficientB; wPass = (2 * PI * fPass) / samplingRate; //same problem with negative N's as with the highpass filter wStop = (2 * PI * fStop) / samplingRate; omegaPass = Math.Tan(wPass / 2); omegaStop = Math.Tan(wStop / 2); ePass = Math.Sqrt(Math.Pow(10, (aPass / 10)) - 1); eStop = Math.Sqrt(Math.Pow(10, (aStop / 10)) - 1); w = omegaStop / omegaPass; passE = eStop / ePass; nExact = Math.Abs(Math.Log(passE) / Math.Log(w)); nUsed = (int)Math.Ceiling(nExact); int k = (int)Math.Floor(nUsed / 2d); theta = new double[k]; omega0 = omegaPass / (Math.Pow(ePass, 1d / (double)nUsed)); thetaD = new double[2 * nUsed - 1]; for (int i = 0; i < k; i++) { theta[i] = (PI / (2 * nUsed)) * (nUsed - 1 + (2 * (i + 1))); } for (int t = 0; t < k; t++) { thetaD[t] = -2 * Math.Cos(theta[t]); } if (nUsed % 2 == 1) { thetaD[0] = 1 + omega0; } filterCoefficientG = new double[(int)k + 1]; filterCoefficientA = new double[(int)k + 1, 2]; filterCoefficientB = new double[(int)k + 1, 3]; double[] matrixBHelp = { 1, 1, 0 }; for (int i = 0; i < k; i++) { filterCoefficientG[i + 1] = Math.Pow(omega0, 2) / (1 - 2 * omega0 * Math.Cos(theta[i]) + Math.Pow(omega0, 2)); filterCoefficientA[i + 1, 0] = (2 * (Math.Pow(omega0, 2) - 1)) / (1 - 2 * omega0 * Math.Cos(theta[i]) + Math.Pow(omega0, 2)); filterCoefficientA[i + 1, 1] = (1 + 2 * omega0 * Math.Cos(theta[i]) + Math.Pow(omega0, 2)) / (1 - 2 * omega0 * Math.Cos(theta[i]) + Math.Pow(omega0, 2)); filterCoefficientB[i + 1, 0] = filterCoefficientG[i + 1] * 1; filterCoefficientB[i + 1, 1] = filterCoefficientG[i + 1] * 2; filterCoefficientB[i + 1, 2] = filterCoefficientG[i + 1] * 1; } if (nUsed % 2 != 0) { filterCoefficientG[0] = omega0 / (omega0 + 1); filterCoefficientA[0, 0] = (omega0 - 1) / (omega0 + 1); filterCoefficientA[0, 1] = 0; for (int i = 0; i < 2; i++) { filterCoefficientB[0, i] = filterCoefficientG[0] * matrixBHelp[i]; } } return(FilteringClass.SOSFiltering(audio, filterCoefficientA, filterCoefficientB, nUsed)); }
/// <summary> /// /// </summary> /// <param name="audio"></param> /// <param name="samplingRate"></param> /// <param name="passbandFrequencyA"></param> /// <param name="passbandFrequencyB"></param> /// <param name="stopbandFrequencyA"></param> /// <param name="stopbandFrequencyB"></param> /// <param name="passbandAttenuation"></param> /// <param name="stopbandAttenuation"></param> /// <returns></returns> public static double[] BandpassFiltering(double[] audio, uint samplingRate, uint passbandFrequencyA, uint passbandFrequencyB, uint stopbandFrequencyA, uint stopbandFrequencyB, float passbandAttenuation, float stopbandAttenuation) { //page 753 const double PI = Math.PI; double wPassA = 2 * PI * passbandFrequencyA / samplingRate; double wPassB = 2 * PI * passbandFrequencyB / samplingRate; double c = (Math.Sin(wPassA + wPassB)) / (Math.Sin(wPassA) + Math.Sin(wPassB)); double omegaPass = Math.Abs((c - Math.Cos(wPassB)) / (Math.Sin(wPassB))); double wStopA = 2 * PI * stopbandFrequencyA / samplingRate; double wStopB = 2 * PI * stopbandFrequencyB / samplingRate; double omegaStopA = (c - Math.Cos(wStopA)) / (Math.Sin(wStopA)); double omegaStopB = (c - Math.Cos(wStopB)) / (Math.Sin(wStopB)); double omegaStop = Math.Abs(omegaStopA) < Math.Abs(omegaStopB) ? Math.Abs(omegaStopA) : Math.Abs(omegaStopB); double ePass = Math.Sqrt(Math.Pow(10, (passbandAttenuation / 10)) - 1); double eStop = Math.Sqrt(Math.Pow(10, (stopbandAttenuation / 10)) - 1); double passE = eStop / ePass; double w = omegaStop / omegaPass; double nExact = Math.Abs(Math.Log(passE) / Math.Log(w)); int nUsed = (int)Math.Ceiling(nExact); int k = (int)Math.Floor(nUsed / 2d); double omega0 = omegaPass / (Math.Pow(ePass, 1d / (double)nUsed)); double[] theta = new double[k]; for (int i = 0; i < k; i++) { theta[i] = (PI / (2 * nUsed)) * (nUsed - 1 + (2 * (i + 1))); } double[] filterCoefficientG = new double[(int)k + 1]; double[,] filterCoefficientA = new double[(int)k + 1, 4]; double[,] filterCoefficientB = new double[(int)k + 1, 5]; for (int i = 0; i < k; i++) { filterCoefficientG[i + 1] = Math.Pow(omega0, 2) / (1 - 2 * omega0 * Math.Cos(theta[i]) + Math.Pow(omega0, 2)); } for (int i = 0; i < k; i++) { filterCoefficientA[i + 1, 0] = (4 * c * (omega0 * Math.Cos(theta[i]) - 1)) / (1 - 2 * omega0 * Math.Cos(theta[i]) + Math.Pow(omega0, 2)); filterCoefficientA[i + 1, 1] = (2 * (2 * Math.Pow(c, 2) + 1 - Math.Pow(omega0, 2))) / (1 - 2 * omega0 * Math.Cos(theta[i]) + Math.Pow(omega0, 2)); filterCoefficientA[i + 1, 2] = -(4 * c * (omega0 * Math.Cos(theta[i]) + 1)) / (1 - 2 * omega0 * Math.Cos(theta[i]) + Math.Pow(omega0, 2)); filterCoefficientA[i + 1, 3] = (1 + 2 * omega0 * Math.Cos(theta[i]) + Math.Pow(omega0, 2)) / (1 - 2 * omega0 * Math.Cos(theta[i]) + Math.Pow(omega0, 2)); double[] filter = { 1, 0, //(s-1)*c -1 //-s }; double[] vector = { 1, 0, //(s-1)*c -1 //-s }; double[] result = MathSupport.Convolution(vector, filter); filterCoefficientB[i + 1, 0] = filterCoefficientG[i + 1] * result[0]; filterCoefficientB[i + 1, 1] = filterCoefficientG[i + 1] * result[1]; filterCoefficientB[i + 1, 2] = filterCoefficientG[i + 1] * result[2]; filterCoefficientB[i + 1, 3] = filterCoefficientG[i + 1] * result[3]; filterCoefficientB[i + 1, 4] = filterCoefficientG[i + 1] * result[4]; } double[] matrixBHelp = { 1, 0, //(s-1)*c -1, //-s, s is 1 for band, -1 for stop 0, 0 }; if (nUsed % 2 != 0) { filterCoefficientG[0] = omega0 / (omega0 + 1); filterCoefficientA[0, 0] = -(2 * c) / (omega0 + 1); filterCoefficientA[0, 1] = (1 - omega0) / (1 + omega0); filterCoefficientA[0, 2] = 0; filterCoefficientA[0, 3] = 0; for (int i = 0; i < 5; i++) { filterCoefficientB[0, i] = filterCoefficientG[0] * matrixBHelp[i]; } } return(FilteringClass.FOSFiltering(audio, filterCoefficientA, filterCoefficientB, nUsed)); }