View Raw SPL
/*****************************************************************************
*                                                                            *
*   WINFUNC.SPL   Copyright (C) 2000-2012 DSP Development Corporation        *
*                               All Rights Reserved                          *
*                                                                            *
*   Author:       Randy Race                                                 *
*                                                                            *
*   Synopsis:     Multiplies a series with a spectral window                 *
*                                                                            *
*   Revisions:    17 Feb 2000  RRR  Creation                                 *
*                 15 Nov 2008  RRR  added optional beta argument for Kaiser  *
*                 16 Jul 2010  RRR  added optional symmetry flag             *
*                 14 Feb 2012  RRR  added chebwin, and taylorwin             *
*                  7 May 2012  RRR  added blackman-harris                    *
*                                                                            *
*****************************************************************************/

#define HAMMWND 0
#define HANNWND 1
#define RECTWND 2
#define KAISWND 3
#define FLATWND 4
#define BLCKWND 5
#define MLFLATW 6
#define DOLCHEB 7
#define TAYLWND 8
#define BLKHARW 9
#define NUTTALW 10


#if @HELP_WINFUNC

    WINFUNC

    Purpose: Multiplies a series with a spectral window

    Syntax:  WINFUNC(func, s, ampflag, beta, "sym")

                 func - An integer, the window function
 
                         0: Hamming
                         1: Hanning
                         2: Rectangular
                         3: Kasier
                         4: Flattop
                         5: Blackman
                         6: Modified Flattop
                         7: Dolph-Chebyshev
                         8: Taylor
                         9: Blackman-Harris
                        10: Blackman-Nuttall

                    s - A series or array.

              ampflag - Optional. An optional integer,

                         0: do not correct amplitude (default)
                         1: correct amplitude
                         2: correct RMS
                         3: correct sqrt of mean squared
                         4: correct mean squared

                 beta - Optional. A real, the beta value for the Kaiser
                        window.  Defaults to 7.865. Defaults to
                        7.865. For a Flattop window, beta determines
                        the Flattop window coefficients. For a
                        Dolph-Chebyshev, beta determines the
                        attenuation and for a Taylor window, beta
                        determines the number of constant level
                        sidelobes. See GFLATTOP, GCHEBWIN and
                        GTAYLORWIN for details.

                "sym" - Optional. A string, the symmetry mode.

                         "symmetric" : Starting and ending points are equal,
                                       but leading zero and trailing zero are 
                                       removed (default).

                         "periodic"  : Periodic window where the leading zero
                                       is preserved but the trailing zero is
                                       removed. Conforms to ISO standard.

                         "direct"    : Starting and ending points are equal,
                                       leading and trailing zeros are preserved.
                                       Same as "symmetric" for all windows
                                       except Hanning.

    Returns: A series or array

    Example:
             W1: gsin(1000, .001, 45)
             W2: Spectrum(Winfunc(0, W1))
             W3: Spectrum(Winfunc(0, W1, 1))

             The MAX of W2 == 0.539 and the MAX of W3 == 1.0. The amplitude
             of the spectrum in W3 has been corrected to take into account
             amplitude effects of the Hamming window.

    Remarks:
             WINFUNC is the core routine for the Blackman, Flattop,
             Hamming, Hanning and Kaiser SPL functions.

             If ampflag == 1, the correction factor is the mean of
             the spectral window. This assures that the spectrum of a
             sinusoid of amplitude 1.0 has a peak of 1.0.

             If ampflag == 2, the correction is applied as follows:

             w = winfun(s) * rms(s) / rms(winfun(s))

             where winfun is Blackman, Flattop, Hamming, Hanning or Kaiser.
             This assures that:

             sqrt(area(psd(w))) == rms(s)    approximately

             If ampflag == 3, the correction is applied as follows:

             w = winfun(s) / sqrt(mean(win * win))

             If ampflag == 4, the correction is applied as follows:

             w = winfun(s) / mean(win * win)

             where win is the windowing function.

             The "sym" flag controls the window symmetry as follows: 

             "Symmetric" (the default) removes any leading and trailing
             zeros.  For an N point symmetric window, a N-1 point
             periodic window is effectively created and the Nth point
             is set to the same value as the first point.  For the
             Hanning window, a N+1 point periodic window is created and
             the trailing zero is removed.

             "Periodic" or "iso" creates a periodic window function
             useful in spectrum analysis applications where the
             starting zero is preserved and the trailing zero is
             removed.  "Periodic" or "iso" conforms to the ISO 18431-1
             standard for windowing functions.

             "Direct" implements the core window function where any
             leading and trailing zeros are preserved. This mode is the
             same as "symmetric" for all windows except Hanning.

             For a Taylor window, this flag is a real and sets the
             stopband attenuation.

    See Also:
             Blackman
             Chebwin
             Flattop
             Flattopwin
             Hamming
             Hanning
             Kaiser
             Nuttall
             Taylorwin
#endif


/* multiples s by windowing function */
SERIES winfunc(func, s, ampflag, beta, sym)
{
        local win, len, dx, islen;

        (func, s, ampflag, beta, sym, win) = 
                winfunc_parse_args(func, s, ampflag, beta, sym);


        if (isscalar(s))
        {
                /* e.g. hanning(1000) */
                len   = s;
                dx    = 1.0;
                islen = 1;
        }
        else 
        {
                if (win > 0)
                {
                        s = castwindow(win);
                }

                /* e.g. hanning(w1) */
                len   = length(s);
                dx    = deltax(s);
                islen = 0;
        }

        /* window function */
        switch (func)
        {
                case HAMMWND:
                        win = ghamming(len, dx, sym);
                        break;

                case HANNWND:
                        win = ghanning(len, dx, sym);
                        break;

                case KAISWND:
                        win = gkaiser(len, dx, beta);
                        break;

                case FLATWND:
                        win = gflattop(len, dx, beta, sym);
                        break;

                case MLFLATW:
                        win = gflattopwin(len, dx, sym);
                        break;

                case BLCKWND:
                        win = gblackman(len, dx, sym);
                        break;

                case DOLCHEB:
                        win = gchebwin(len, dx, beta);
                        break;

                case TAYLWND:
                        win = gtaylorwin(len, dx, beta, sym);
                        break;

                case BLKHARW:
                        win = gblackmanharris(len, dx, sym);
                        break;

                case NUTTALW:
                        win = gnuttall(len, dx, sym);
                        break;

                case RECTWND:
                default:
                        if (islen)
                        {
                                s = ones(len, 1);
                        }
                        return(s);
                        break;
        }

        if (islen)
        {
                s = {1};
        }

        switch (ampflag)
        {
                case 1:
                        /* amplitude correction */
                        return(s * win / mean(win));

                case 2:
                        /* rms correction */
                        w = s * win;
                        return(w * rms(s) / rms(w));

                case 3:
                        /* sqrt of mean squared correction */
                        return(s * win / sqrt(mean(win*win)));

                case 4:
                        /* mean squared correction */
                        return(s * win / mean(win*win));

                default:
                        /* no correction */
                        return(s * win);
        }
}


/* parse input args */
winfunc_parse_args(func, s, ampflag, beta, sym)
{
        local win = -1, temp, defbeta;

        switch (func)
        {
                case KAISWND:
                        defbeta = 7.865;
                        break;

                case DOLCHEB:
                        /* attn */
                        defbeta = -100;
                        break;

                case TAYLWND:
                        /* nbar */
                        defbeta = 4;
                        break;

                default:
                        defbeta = 0;
                        break;
        }

        if (argc < 5)
        {
                if (argc < 4)
                {
                        if (argc < 3)
                        {
                                if (argc < 2) error("winfunc - window function and input series required");

                                ampflag = 0;
                        }

                        beta = defbeta;
                }

                sym = (func == 4) ? "periodic" : "symmetric";
        }

        if (isstring(ampflag))
        {
                temp    = ampflag;
                ampflag = beta;

                if (func != TAYLWND)
                {
                        beta = (isstring(sym)) ? defbeta : sym;
                }

                sym = temp;
        }
        else if (isstring(beta))
        {
                temp = beta;
                beta = (isstring(sym) || func == TAYLWND) ? defbeta : sym;
                sym  = temp;
        }

        if (func == TAYLWND)
        {
                if (isstring(sym))
                {
                        /* attn */
                        sym = 30;
                }
        }

        if (iswindow(s))
        {
                if (iswinempty(s))
                {
                        win = getwnum(s);
                        s   = {};
                }
        }

        return(func, s, ampflag, beta, sym, win);
}



winfunc_error(errnum, errmes)
{
        local mes;

        /* setup error message for caller */
        mes = strget(2, errmes, ":");
        error(__CALLER__ + ":" + mes);
}