View Raw SPL
/*****************************************************************************
*                                                                            *
*   CAS2TF.SPL  Copyright (C) 2015 DSP Development Corporation               *
*                               All Rights Reserved                          *
*                                                                            *
*   Author:      Randy Race                                                  *
*                                                                            *
*   Synopsis:    Converts cascade form filter coefficients to direct form    *
*                                                                            *
*   Revisions:   11 Aug 2015  RRR  Creation                                  *
*                                                                            *
*****************************************************************************/


#if @HELP_CAS2TF

    CAS2TF  

    Purpose: 
             Converts cascade form filter coefficients to direct form.
                                                                        
    Format:  
             CAS2TF(c)

             (b, a) = CAS2TF(c)

                c - A series, the filter coefficients in cascade form.

    Returns: 
             A two column series, where the first column contains the
             direct form numerator coefficients and the second column
             contains the direct form denominator coefficients.

             (b, a) = CAS2TF(c) returns the direct form numerator
             and denominator coefficients as two separate series.

    Example:
             c = {1, 1, 0, 0, -0.5, 0.2};
             d = cas2tf(c);

             d == {{1,  1},
                   {0, -0.5},
                   {0,  0.2}}


             The 2nd order cascade filter coefficients represent the
             following Z transform:

                                -1       -2
                        1 + 0.0z   + 0.0z 
             H(z) = 1 * -------------------
                                -1       -2
                        1 - 0.5z   + 0.2z


             The resulting direct form filter coefficients represent the
             equivalent Z transform:


                             1
             H(z) = -------------------
                            -1       -2
                    1 - 0.5z   + 0.2z

             
             Since the original coefficients represent a single 2nd order
             system, the direct form denominator coefficients are identical.

    Example:
             c = {1, 1, 0, 0, -0.754856, 0.392379, 1, 0, 0, 0.254856, 0};
             d = cas2tf(c);

             d == {{1,  1},
                   {0, -0.5},
                   {0,  0.2},
                   {0,  0.1}}

             The 2nd order cascade filter coefficients represent the
             following 2 stage cascaded Z transform:

                                     -1       -2
                             1 + 0.0z   + 0.0z 
             H(z) = 1 * ----------------------------
                                     -1            -2
                        1 - 0.754856z   + 0.392379z


                                     -1       -2
                             1 + 0.0z   + 0.0z 
                      * ------------------------
                                     -1       -2
                        1 - 0.254856z   + 0.0z


             The resulting direct form coefficients represent the equivalent
             Z transform:

                                 1
             H(z) = -----------------------------
                            -1       -2        -3
                    1 - 0.5z   + 0.2z    + 0.1z

    Example:
             c = {1, 1, 0, 0, -0.754856, 0.392379, 1, 0, 0, 0.254856, 0};
             (b, a) = cas2tf(c);

             b == {1, 0, 0, 0}
             a == {1, -0.5, 0.2, 0.1}

             Same as the previous example except the direct form coefficients
             are returned as two separate series.

    Remarks:
             CAS2TF converts cascade form filter coefficients to direct
             form. The cascade form coefficients represent the following
             Z transform: 
  

                               -1       -2                -1       -2
                    b10 + b11 z  + b12 z       b20 + b21 z  + b22 z
         H(z) = G * ________________________ *  ________________________ ...
                               -1       -2                -1       -2
                      1 + a11 z  + a12 z         1 + a21 z  + a22 z


             where the cascade coefficients are represented as a single
             column series with the coefficients in the following order:

             G, b10, b11, b12, a11, a12, b20, b21, b22, a21, a22, ...

             The equivalent direct form coefficients represent the following
             Z transform:

                                        -1                 -Q
                    Y(z)   b[1] + b[2]*z   + ... + b[Q+1]*z
             H(z) = ---- = -------------------------------------
                                        -1                 -P
                    X(z)    1   + a[2]*z   + ... + a[P+1]*z


                        jw
             where z = e    unit circle (frequency response)
                   Q        order of zeros (numerator)
                   P        order of poles (denominator)



             The direct form of the coefficients can be processed by
             the FILTEQ function. However, filtering with direct form
             coefficients can be more prone to numerical roundoff
             errors compared to the same filtering operation in cascade
             form.

             See TF2CAS to convert direct form coefficients to cascade form.

    See Also:
             Cas2tf
             Cascade
             Filteq
#endif


/* convert cascade biquad to direct B(z)/A(z) coefficients */
ITERATE cas2tf(c)
{
        local z, p, k, b, a;
        
        /* check inputs */
        if (argc < 1)         cas2tf_args_err("cas2tf");
        if (not(isarray(c)))  cas2tf_args_err("cas2tf");
        if (length(c) == 0)   cas2tf_args_err("cas2tf");

        if ((length(c) - 1) % 5 != 0)
        {
                error("cas2tf - improper cascade series");
        }

        (z, p, k) = cas2zp(c);

        (b, a) = zp2tf(z, p, k);

        if (outargc > 1)
        {
                return(b, a);
        }
        else
        {
                return(ravel(b, a));
        }
}