/// <summary> /// Calculate the FIR coefficients realizing the given cutoff-frequency. /// </summary> private void CalculateCoeffs() { double temp; Debug.Assert(_length >= 2); Debug.Assert(_length % 4 == 0); Debug.Assert(_cutoffFreq >= 0); Debug.Assert(_cutoffFreq <= 0.5); ArrayPtr <double> work = new double[_length]; ArrayPtr <TSampleType> coeffs = new TSampleType[_length]; double wc = 2.0 * Math.PI * _cutoffFreq; double tempCoeff = (Math.PI * 2) / _length; double sum = 0; for (int i = 0; i < _length; i++) { double cntTemp = i - ((double)_length / 2); temp = cntTemp * wc; double h; if (temp != 0) { h = Math.Sin(temp) / temp; // sinc function } else { h = 1.0; } double w = 0.54 + 0.46 * Math.Cos(tempCoeff * cntTemp); temp = w * h; work[i] = temp; // calc net sum of coefficients sum += temp; } // ensure the sum of coefficients is larger than zero Debug.Assert(sum > 0); // ensure we've really designed a lowpass filter... Debug.Assert(work[_length / 2] > 0); Debug.Assert(work[_length / 2 + 1] > -1e-6); Debug.Assert(work[_length / 2 - 1] > -1e-6); // Calculate a scaling coefficient in such a way that the result can be // divided by 16384 double scaleCoeff = 16384.0f / sum; for (int i = 0; i < _length; i++) { temp = work[i] * scaleCoeff; // scale & round to nearest integer temp += (temp >= 0) ? 0.5 : -0.5; // ensure no overfloods Debug.Assert(temp >= -32768 && temp <= 32767); coeffs[i] = (TSampleType)Convert.ChangeType(temp, typeof(TSampleType)); } // Set coefficients. Use divide factor 14 => divide result by 2^14 = 16384 _firFilter.SetCoefficients(coeffs, _length, 14); DebugSaveAntiAliasFilterCoefficients(coeffs, _length); }