Пример #1
0
        public void Creation()
        {
            const double fd = 0.5;    // Гц // Частота дискретизации
            const double dt = 1 / fd; // 2с // Период дискретизации

            const double fp = 0.05;   // Гц // Граничная частота полосы пропускания
            const double fs = 0.15;   // Гц // Граничная частота полосы запирания

            Assert.IsTrue(fp < fs);
            Assert.IsTrue(fp < fd / 2);

            //const double wp = Consts.pi2 * fp * dt; // 0.628318530717959 рад/с
            //const double ws = Consts.pi2 * fs * dt; // 1.884955592153876 рад/с

            const double Rp = 1;  // Неравномерность в полосе пропускания (дБ)
            const double Rs = 30; // Неравномерность в полосе пропускания (дБ)

            var eps_p = (10d.Pow(Rp / 10) - 1).Sqrt();
            var eps_s = (10d.Pow(Rs / 10) - 1).Sqrt();

            Assert.That.Value(eps_p).IsEqual(0.50884713990958752);
            Assert.That.Value(eps_s).IsEqual(31.606961258558215);

            var Gp = (-Rp).From_dB();
            var Gs = (-Rs).From_dB();

            Assert.That.Value(Gp).IsEqual(0.89125093813374556);
            Assert.That.Value(Gs).IsEqual(0.031622776601683791);

            Assert.That.Value(Gp.In_dB()).IsEqual(-1, 4.67e-15);
            Assert.That.Value(Gs.In_dB()).IsEqual(-30);

            var Fp = DigitalFilter.ToAnalogFrequency(fp, dt);  // Частота пропускания аналогового прототипа
            var Fs = DigitalFilter.ToAnalogFrequency(fs, dt);  // Частота подавления аналогового прототипа

            Assert.That.Value(Fp).IsEqual(0.051712575763384123);
            Assert.That.Value(Fs).IsEqual(0.2190579862253032);

            var Wp = Consts.pi2 * Fp;
            var Ws = Consts.pi2 * Fs;

            var k_eps = eps_s / eps_p;
            var k_W   = Ws / Wp;

            Assert.That.Value(k_eps).GreaterThan(0);
            Assert.That.Value(k_W).GreaterThan(0);

            var double_n = Log(k_eps) / Log(k_W);
            // Порядок фильтра
            var N = (int)double_n;

            if (double_n - N > 0)
            {
                N += 1;
            }

            Assert.That.Value(N).IsEqual(3);

            var L = N / 2;
            var r = N % 2;

            Assert.That.Value(L).IsEqual(1);
            Assert.That.Value(r).IsEqual(1);
            Assert.That.Value(2 * L + r).IsEqual(N);

            var alpha = eps_p.Pow(-1d / N);

            Assert.That.Value(alpha).IsEqual(1.2525763881810263);

            var th0 = PI / N;

            var poles = new Complex[N];

            if (r != 0)
            {
                poles[0] = -alpha;
            }
            for (var i = r; i < poles.Length; i += 2)
            {
                var w = th0 * (i + 1 - r - 0.5);
                poles[i]     = (-alpha * Sin(w), alpha *Cos(w));
                poles[i + 1] = poles[i].ComplexConjugate;
            }

            Assert.That.Collection(poles).IsEqualTo(
                -1.2525763881810263,
                (-0.62628819409051306, 1.0847629723453271),
                (-0.62628819409051306, -1.0847629723453271)
                );

            var translated_poles = poles.ToArray(p => p * Wp)
                                   .AssertThatCollection()
                                   .IsEqualTo(
                -0.40698673955629,
                (-0.20349336977814494, 0.35246085545914824),
                (-0.20349336977814494, -0.35246085545914824))
                                   .ActualValue;

            var z_poles = translated_poles.ToArray(p => DigitalFilter.ToZ(p, dt))
                          .AssertThatCollection()
                          .IsEqualTo(
                0.42147750491999925,
                (0.53055357928176117, 0.44824528113449957),
                (0.53055357928176117, -0.44824528113449957))
                          .AllItems(z_pole => z_pole.Where(z => z.Abs < 1))
                          .ActualValue;

            var kz = DigitalFilter.GetNormalizeCoefficient(translated_poles, dt)
                     .AssertThanValue()
                     .IsEqual(0.45194421873401691)
                     .ActualValue;

            var WpN = Wp.Pow(N)
                      .AssertThanValue()
                      .IsEqual(0.034302685030761955)
                      .ActualValue;

            var k = WpN * kz / eps_p;

            Assert.That.Value(k).IsEqual(0.030466713814017582);

            var b = Range(0, N + 1).ToArray(i => k * BinomialCoefficient(N, i));

            Assert.That.Collection(b).IsEqualTo(new[]
            {
                1 * k,
                3 * k,
                3 * k,
                1 * k
            });

            var a_complex = Polynom.Array.GetCoefficientsInverted((Complex[])z_poles);

            Assert.That.Collection(a_complex)
            .CountEquals(4)
            .AllItems(a_value => a_value.Where(z => z.Im).IsEqual(0, 1e-16));

            var a = a_complex.ToRe() ?? throw new AssertFailedException("Отсутствует ссылка на массив вещественных значений");

            Assert.That.Collection(a).ValuesAreEqual(
                1,
                -1.4825846634835216,
                0.92964373019213786,
                -0.20332535619647568
                );

            var filter = new DSP.Filters.ButterworthLowPass(dt, fp, fs, Gp, Gs);

            Assert.That.Collection(filter.A).IsEqualTo(a, 1e-15);
            Assert.That.Collection(filter.B).IsEqualTo(b, 1e-16);
        }
Пример #2
0
        public void Creation_fp500_ps1500_fd_5000()
        {
            const double fp = 500;    // Гц // Граничная частота полосы пропускания
            const double fs = 1500;   // Гц // Граничная частота полосы запирания
            const double fd = 5000;   // Гц // Частота дискретизации
            const double dt = 1 / fd; // 2с // Период дискретизации
            const double Rp = 1;      // Неравномерность в полосе пропускания (дБ)
            const double Rs = 30;     // Неравномерность в полосе пропускания (дБ)
            var          Gp = (-Rp).From_dB();
            var          Gs = (-Rs).From_dB();

            var eps_p = (10d.Pow(Rp / 10) - 1).Sqrt();
            var eps_s = (10d.Pow(Rs / 10) - 1).Sqrt();

            var Fp = DigitalFilter.ToAnalogFrequency(fp, dt);  // Частота пропускания аналогового прототипа
            var Fs = DigitalFilter.ToAnalogFrequency(fs, dt);  // Частота подавления аналогового прототипа

            var k_eps = eps_s / eps_p;
            var k_W   = Fs / Fp;

            var double_n = Log(k_eps) / Log(k_W);

            var N = (int)double_n;

            if (double_n - N > 0)
            {
                N += 1;
            }

            var L = N / 2;
            var r = N % 2;

            var alpha = eps_p.Pow(-1d / N);

            var th0 = PI / N;

            var poles = new Complex[N];

            if (r != 0)
            {
                poles[0] = -alpha;
            }
            for (var i = r; i < poles.Length; i += 2)
            {
                var w = th0 * (i + 1 - r - 0.5);
                poles[i]     = (-alpha * Sin(w), alpha *Cos(w));
                poles[i + 1] = poles[i].ComplexConjugate;
            }

            var translated_poles = poles.ToArray(p => p * Consts.pi2 * Fp);
            var z_poles          = translated_poles.ToArray(p => DigitalFilter.ToZ(p, dt));
            var kz        = DigitalFilter.GetNormalizeCoefficient(translated_poles, dt);
            var WpN       = (Consts.pi2 * Fp).Pow(N);
            var k         = WpN * kz / eps_p;
            var b         = Range(0, N + 1).ToArray(i => k * BinomialCoefficient(N, i));
            var a_complex = Polynom.Array.GetCoefficientsInverted(z_poles);
            var a         = a_complex.ToRe() ?? throw new AssertFailedException("Отсутствует ссылка на массив вещественных значений");

            var filter = new DSP.Filters.ButterworthLowPass(dt, fp, fs, Gp, Gs);

            Assert.That.Value(filter.Order).IsEqual(N);

            var tr_k = filter.GetTransmissionCoefficient(fs, dt).Abs.In_dB();

            Assert.That.Collection(filter.A).IsEqualTo(a, 3e-12);
            Assert.That.Collection(filter.B).IsEqualTo(b, 1e-16);
        }