private T ApplyFilters(T source, FilterChain filters) { // Fetch all colors IEnumerable <Color> colors = _handler.GetColors(source); // Apply filters IEnumerable <Color> filteredColors = filters.ApplyTo(colors); // #if DEBUG var watch = new Stopwatch(); watch.Start(); // #endif // replace original colors with filtered ones var result = _handler.ReplaceColors(source, filteredColors); // #if DEBUG watch.Stop(); Console.WriteLine("Colors processed in " + watch.ElapsedMilliseconds + "ms"); // #endif return(result); }
/// <summary> /// Method creates overlapping ERB filters (ported from Malcolm Slaney's MATLAB code). /// </summary> /// <param name="erbFilterCount">Number of ERB filters</param> /// <param name="fftSize">Assumed size of FFT</param> /// <param name="samplingRate">Assumed sampling rate</param> /// <param name="lowFreq">Lower bound of the frequency range</param> /// <param name="highFreq">Upper bound of the frequency range</param> /// <param name="normalizeGain">True if gain should be normalized; false if all filters should have same height 1.0</param> /// <returns>Array of ERB filters</returns> public static float[][] Erb( int erbFilterCount, int fftSize, int samplingRate, double lowFreq = 0, double highFreq = 0, bool normalizeGain = true) { if (lowFreq < 0) { lowFreq = 0; } if (highFreq <= lowFreq) { highFreq = samplingRate / 2.0; } const double earQ = 9.26449; const double minBw = 24.7; const double bw = earQ * minBw; const int order = 1; var t = 1.0 / samplingRate; var frequencies = new double[erbFilterCount]; for (var i = 1; i <= erbFilterCount; i++) { frequencies[erbFilterCount - i] = -bw + Math.Exp(i * (-Math.Log(highFreq + bw) + Math.Log(lowFreq + bw)) / erbFilterCount) * (highFreq + bw); } var ucirc = new Complex[fftSize / 2 + 1]; for (var i = 0; i < ucirc.Length; i++) { ucirc[i] = Complex.Exp((2 * Complex.ImaginaryOne * i * Math.PI) / fftSize); } var rootPos = Math.Sqrt(3 + Math.Pow(2, 1.5)); var rootNeg = Math.Sqrt(3 - Math.Pow(2, 1.5)); var fft = new Fft(fftSize); var erbFilterBank = new float[erbFilterCount][]; for (var i = 0; i < erbFilterCount; i++) { var cf = frequencies[i]; var erb = Math.Pow(Math.Pow(cf / earQ, order) + Math.Pow(minBw, order), 1.0 / order); var b = 1.019 * 2 * Math.PI * erb; var theta = 2 * cf * Math.PI * t; var itheta = Complex.Exp(2 * Complex.ImaginaryOne * theta); var a0 = t; var a2 = 0.0; var b0 = 1.0; var b1 = -2 * Math.Cos(theta) / Math.Exp(b * t); var b2 = Math.Exp(-2 * b * t); var common = -t *Math.Exp(-b *t); var k1 = Math.Cos(theta) + rootPos * Math.Sin(theta); var k2 = Math.Cos(theta) - rootPos * Math.Sin(theta); var k3 = Math.Cos(theta) + rootNeg * Math.Sin(theta); var k4 = Math.Cos(theta) - rootNeg * Math.Sin(theta); var a11 = common * k1; var a12 = common * k2; var a13 = common * k3; var a14 = common * k4; var gainArg = Complex.Exp(Complex.ImaginaryOne * theta - b * t); var gain = Complex.Abs( (itheta - gainArg * k1) * (itheta - gainArg * k2) * (itheta - gainArg * k3) * (itheta - gainArg * k4) * Complex.Pow(t * Math.Exp(b * t) / (-1.0 / Math.Exp(b * t) + 1 + itheta * (1 - Math.Exp(b * t))), 4.0)); var filter1 = new IirFilter(new[] { a0, a11, a2 }, new[] { b0, b1, b2 }); var filter2 = new IirFilter(new[] { a0, a12, a2 }, new[] { b0, b1, b2 }); var filter3 = new IirFilter(new[] { a0, a13, a2 }, new[] { b0, b1, b2 }); var filter4 = new IirFilter(new[] { a0, a14, a2 }, new[] { b0, b1, b2 }); var ir = new DiscreteSignal(1, fftSize); ir[0] = 1.0f; var chain = new FilterChain(new[] { filter1, filter2, filter3, filter4 }); var kernel = chain.ApplyTo(ir); erbFilterBank[i] = fft.PowerSpectrum(kernel, false).Samples; } // normalize gain (by default) if (!normalizeGain) { return(erbFilterBank); } foreach (var filter in erbFilterBank) { var sum = 0.0; for (var j = 0; j < filter.Length; j++) { sum += Math.Abs(filter[j] * filter[j]); } var weight = Math.Sqrt(sum * samplingRate / fftSize); for (var j = 0; j < filter.Length; j++) { filter[j] = (float)(filter[j] / weight); } } return(erbFilterBank); }