コード例 #1
0
        /// <summary>
        /// 連続時間フィルターの伝達関数を離散時間フィルターの伝達関数にBilinear transformする。
        /// Discrete-time signal processing 3rd ed. pp.533
        /// Benoit Boulet, 信号処理とシステムの基礎 pp.681-682
        /// 三谷政昭, ディジタル・フィルタ理論&設計入門 pp.193
        /// </summary>
        /// <param name="ps">連続時間フィルターの伝達関数</param>
        /// <returns>離散時間フィルターの伝達関数</returns>
        public FirstOrderComplexRationalPolynomial StoZ(FirstOrderComplexRationalPolynomial ps)
        {
            /*
             *     n1s + n0
             * ps = ──────────
             *     d1s + d0
             *
             * z^{-1} = zM とする。
             *
             * Bilinear transform:
             *    2     1-zM
             * s → ─── * ──────
             *    Td    1+zM
             *
             * 2/Td = kとすると以下のように書ける。
             *
             *   k(1-zM)
             * s → ───────
             *    1+zM
             *
             *          k(1-zM)          n1*k(1-zM) + n0(1+zM)
             *     n1 * ─────── + n0     ─────────────────────
             *           1+zM                    1+zM              n1*k(1-zM) + n0(1+zM)   (n0-n1*k)zM + n0+n1*k
             * pz = ─────────────────── = ──────────────────────── = ───────────────────── = ─────────────────────
             *          k(1-zM)          d1*k(1-zM) + d0(1+zM)     d1*k(1-zM) + d0(1+zM)   (d0-d1*k)zM + d0+d1*k
             *     d1 * ─────── + d0     ─────────────────────
             *           1+zM                    1+zM
             *
             */

            // 都合により、投入されるアナログフィルターの伝達関数psは、
            // s' == s / ωcとしたs'についての式であることに注意!!

            double twoπ = 2.0 * Math.PI;
            double ωc   = PrewarpωtoΩ(mMatchFreq * twoπ);
            double k    = (1.0 / ωc) * (2.0 * mSampleFreq);

            var n0  = ps.N(0);
            var n1k = WWComplex.Mul(ps.N(1), k);
            var d0  = ps.D(0);
            var d1k = WWComplex.Mul(ps.D(1), k);

            var pz = new FirstOrderComplexRationalPolynomial(
                WWComplex.Sub(n0, n1k), WWComplex.Add(n0, n1k),
                WWComplex.Sub(d0, d1k), WWComplex.Add(d0, d1k));

            return(pz);
        }
コード例 #2
0
        public static FirstOrderComplexRationalPolynomial LowpassToHighpass(FirstOrderComplexRationalPolynomial p)
        {
            /*
             * z^-1 → -z^-1に置き換える。
             *
             * n1 z^-1 + n0     -n1 z^-1 + n0
             * ────────────── → ───────────────
             * d1 z^-1 + d0     -d1 z^-1 + d0
             *
             */

            var r = new FirstOrderComplexRationalPolynomial(
                p.N(1).Minus(), p.N(0),
                p.D(1).Minus(), p.D(0));

            return(r);
        }
コード例 #3
0
        private static WWComplex InverseLaplaceTransformOne(FirstOrderComplexRationalPolynomial p, double t)
        {
            if (t < 0)
            {
                return(WWComplex.Zero());
            }

            if (!p.N(1).EqualValue(WWComplex.Zero()))
            {
                // 約分によって分子が定数になるはずである。
                throw new NotImplementedException();
            }

            if (p.D(1).EqualValue(WWComplex.Zero()) &&
                p.D(0).EqualValue(WWComplex.Unity()))
            {
                // 定数。
                // 1 → δ(t)
                if (t == 0)
                {
                    return(p.N(0));
                }
                return(WWComplex.Zero());
            }

            if (p.D(0).EqualValue(WWComplex.Zero()))
            {
                System.Diagnostics.Debug.Assert(!p.D(1).EqualValue(WWComplex.Zero()));

                // b/s → b*u(t)
                return(p.N(0));
            }

            // b/(s-a) → b * exp(a * t)
            return(WWComplex.Mul(p.N(0),
                                 new WWComplex(Math.Exp(-t * p.D(0).real) * Math.Cos(-t * p.D(0).imaginary),
                                               Math.Exp(-t * p.D(0).real) * Math.Sin(-t * p.D(0).imaginary))));
        }