public static double[] FirFilter(double[] data, double hz, int n, double threshold0, double threshold1, FirFilterType type = FirFilterType.LowPass, FirWindowType windowType = FirWindowType.Rectangle)
        {
            double[] h = ImpulseCharacteristic(hz, n, threshold0, threshold1, type, windowType);

            return(BaseFirFilter(data, h));
        }
        public static double[] ImpulseCharacteristic(double hz, int n, double threshold, FirFilterType impulseCharacteristicType = FirFilterType.LowPass, FirWindowType windowType = FirWindowType.Rectangle)
        {
            double[] h;
            double[] w  = WindowCoef(windowType, n);
            double   fc = threshold / (hz);

            switch (impulseCharacteristicType)
            {
            case FirFilterType.LowPass:
                h = BaseImpulseCharacteristic(threshold, hz, n);
                break;

            case FirFilterType.HighPass:
                h        = BaseImpulseCharacteristic(threshold, hz, n).Select(x => (-x)).ToArray();
                h[n / 2] = 1 - 2 * fc;
                break;

            default:
                throw new Exception();
            }

            double[] result = new double[n];

            for (int i = 0; i < n; i++)
            {
                result[i] = h[i] * w[i];
            }
            return(result);
        }
        public static double[] ImpulseCharacteristic(double hz, int n, double threshold0, double threshold1, FirFilterType impulseCharacteristicType = FirFilterType.LowPass, FirWindowType windowType = FirWindowType.Rectangle)
        {
            double[] h0, h1, h;
            double[] w   = WindowCoef(windowType, n);
            double   fc0 = threshold0 / (hz);
            double   fc1 = threshold1 / (hz);

            switch (impulseCharacteristicType)
            {
            case FirFilterType.BandPass:
                h  = new double[n];
                h0 = BaseImpulseCharacteristic(threshold0, hz, n);
                h1 = BaseImpulseCharacteristic(threshold1, hz, n);

                for (int i = 0; i < n; i++)
                {
                    h[i]     = h1[i] - h0[i];
                    h[n / 2] = 2 * (fc1 - fc0);
                }
                break;

            case FirFilterType.NotchPass:
                h  = new double[n];
                h0 = BaseImpulseCharacteristic(threshold0, hz, n);
                h1 = BaseImpulseCharacteristic(threshold1, hz, n);

                for (int i = 0; i < n; i++)
                {
                    h[i]     = h0[i] - h1[i];
                    h[n / 2] = 1 - 2 * (fc1 - fc0);
                }
                break;

            default:
                throw new Exception();
            }

            double[] result = new double[n];

            for (int i = 0; i < n; i++)
            {
                result[i] = h[i] * w[i];
            }
            return(result);
        }