PDL-DSP-Windows is Copyright (C) 2012, John Lapeyre. =head1 OVERVIEW A module for PDL providing window functions for signal processing. This module is currently not on CPAN. =cut =head1 NAME PDL::DSP::Windows - Window functions for signal processing =head1 SYNOPSIS use PDL; use PDL::DSP::Windows('window'); my $samples = window( 10, 'tukey', { params => .5 }); use PDL; use PDL::DSP::Windows; my $win = new PDL::DSP::Windows(10, 'tukey', { params => .5 }); print $win->coherent_gain , "\n"; $win->plot; =head1 DESCRIPTION This module provides symmetric and periodic (DFT-symmetric) window functions for use in filtering and spectral analysis. It provides a high-level access subroutine L. This functional interface is sufficient for getting the window samples. For analysis and plotting, etc. an object oriented interface is provided. The functional subroutines must be either explicitly exported, or fully qualified. In this document, the word I refers only to the mathematical window functions, while the word I is used to describe code. Window functions are also known as apodization functions or tapering functions. In this module, each of these functions maps a sequence of C<$N> integers to values called a B. (To confuse matters, the word I also has other meanings when describing window functions.) The functions are often named for authors of journal articles. Be aware that across the literature and software, some functions referred to by several different names, and some names refer to several different functions. As a result, the choice of window names is somewhat arbitrary. The L window function requires L. The L window function requires L. But the remaining window functions may be used if these modules are not installed. The most common and easiest usage of this module is indirect, via some higher-level filtering interface, such as L. The next easiest usage is to return a pdl of real-space samples with the subroutine L. Finally, for analyzing window functions, object methods, such as L, L, L are provided. In the following, first the functional interface (non-object oriented) is described in L. Next, the object methods are described in L. Next the low-level subroutines returning samples for each named window are described in L. Finally, some support routines that may be of interest are described in L. =head1 FUNCTIONAL INTERFACE =head2 window $win = window({OPTIONS}); $win = window($N,{OPTIONS}); $win = window($N,$name,{OPTIONS}); $win = window($N,$name,$params,{OPTIONS}); $win = window($N,$name,$params,$periodic); Returns an C<$N> point window of type C<$name>. The arguments may be passed positionally in the order C<$N,$name,$params,$periodic>, or they may be passed by name in the hash C. =head3 EXAMPLES # Each of the following return a 100 point symmetric hamming window. $win = window(100); $win = window(100, 'hamming'); $win = window(100, { name => 'hamming' ); $win = window({ N=> 100, name => 'hamming' ); # Each of the following returns a 100 point symmetric hann window. $win = window(100, 'hann'); $win = window(100, { name => 'hann' ); # Returns a 100 point periodic hann window. $win = window(100, 'hann', { periodic => 1 } ); # Returns a 100 point symmetric Kaiser window with alpha=2. $win = window(100, 'kaiser', { params => 2 }); =head3 OPTIONS The options follow default PDL::Options rules-- They may be abbreviated, and are case-insensitive. =over =item B (string) name of window function. Default: C. This selects one of the window functions listed below. Note that the suffix '_per', for periodic, may be ommitted. It is specified with the option C<< periodic => 1 >> =item B ref to array of parameter or parameters for the window-function subroutine. Only some window-function subroutines take parameters. If the subroutine takes a single parameter, it may be given either as a number, or a list of one number. For example C<3> or C<[3]>. =item B number of points in window function (the same as the order of the filter) No default value. =item B If value is true, return a periodic rather than a symmetric window function. Default: 0 (that is, false. that is, symmetric.) =back =cut =head2 list_windows list_windows list_windows STR C prints the names all of the available windows. C prints only the names of windows matching the string C. =cut =head1 METHODS =head2 new =for usage my $win = new PDL::DSP::Windows(ARGS); =for ref Create an instance of a Windows object. If C are given, the instance is initialized. C are interpreted in exactly the same way as arguments the subroutine L. =for example For example: my $win1 = new PDL::DSP::Windows(8,'hann'); my $win2 = new PDL::DSP::Windows( { N => 8, name => 'hann' } ); =cut =head2 init =for usage $win->init(ARGS); =for ref Initialize (or reinitialize) a Windows object. ARGS are interpreted in exactly the same way as arguments the subroutine L. =for example For example: my $win = new PDL::DSP::Windows(8,'hann'); $win->init(10,'hamming'); =cut =head2 samples =for usage $win->samples(); =for ref Generate and return a reference to the piddle of $N samples for the window C<$win>. This is the real-space representation of the window. The samples are stored in the object C<$win>, but are regenerated every time C is invoked. See the method L below. =for example For example: my $win = new PDL::DSP::Windows(8,'hann'); print $win->samples(), "\n"; =cut =head2 get =for usage my $windata = $win->get('samples'); =for ref Get an attribute (or list of attributes) of the window C<$win>. If attribute C is requested, then the samples are created with the method L if they don't exist. =for example For example: my $win = new PDL::DSP::Windows(8,'hann'); print $win->get('samples'), "\n"; =cut =head2 get_samples =for usage my $windata = $win->get_samples =for ref Return a reference to the pdl of samples for the Window instance C<$win>. The samples will be generated with the method L if and only if they have not yet been generated. =cut =head2 get_modfreqs =for usage my $winfreqs = $win->get_modfreqs =for ref Return a reference to the pdl of the frequency response (modulus of the DFT) for the Window instance C<$win>. The data are created with the method L if they don't exist. =cut =head2 get_params =for usage my $params = $win->get_params =for ref Create a new array containing the parameter values for the instance C<$win> and return a reference to the array. Note that not all window types take parameters. =cut =head2 get_name =for usage print $win->get_name , "\n"; =for ref Return a name suitable for printing associated with the window $win. This is something like the name used in the documentation for the particular window function. This is static data and does not depend on the instance. =cut =head2 plot =for usage $win->plot; =for ref Plot the samples. Currently, only PDL::Graphics::Gnuplot is supported. The default display type is used. =cut =head2 plot_freq =for usage Can be called like this $win->plot_freq; Or this $win->plot_freq( {ordinate => ORDINATE }); =for ref Plot the frequency response (magnitude of the DFT of the window samples). The response is plotted in dB, and the frequency (by default) as a fraction of the Nyquist frequency. Currently, only PDL::Graphics::Gnuplot is supported. The default display type is used. =head3 options =over =item coord => COORD This sets the units of frequency of the co-ordinate axis. C must be one of C, for fraction of the nyquist frequency (range C<-1,1>), C, for fraction of the sampling frequncy (range C<-.5,.5>), or C for frequency bin number (range C<0,$N-1>). The default value is C. =back =cut =head2 enbw =for usage $win->enbw; =for ref Compute and return the equivalent noise bandwidth of the window. =cut =head2 coherent_gain =for usage $win->coherent_gain; =for ref Compute and return the coherent gain (the dc gain) of the window. This is just the average of the samples. =cut =head2 process_gain =for usage $win->coherent_gain; =for ref Compute and return the processing gain (the dc gain) of the window. This is just the multiplicative inverse of the C. =cut =head2 scallop_loss =for usage $win->scallop_loss; =for ref **BROKEN**. Compute and return the scalloping loss of the window. =cut =head1 WINDOW FUNCTIONS These window-function subroutines return a pdl of $N samples. For most windows, there are a symmetric and a periodic version. The symmetric versions are functions of $N points, uniformly spaced, and taking values from x_lo through x_hi. Here, a periodic function of C< $N > points is equivalent to its symmetric counterpart of C<$N+1> points, with the final point omitted. The name of a periodic window-function subroutine is the same as that for the corresponding symmetric function, except it has the suffix C<_per>. The descriptions below describe the symmetric version of each window. The term 'Blackman-Harris family' is meant to include the Hamming family and the Blackman family. These are functions of sums of cosines. Unless otherwise noted, the arguments in the cosines of all symmetric window functions are multiples of C<$N> numbers uniformly spaced from C<0> through C<2 pi>. =cut =head1 Symmetric window functions =head2 bartlett($N) The Bartlett window. (Ref 1). Another name for this window is the fejer window. This window is defined by 1 - abs arr, where the points in arr range from -1 through 1. See also L. =cut =head2 bartlett_hann($N) The Bartlett-Hann window. Another name for this window is the Modified Bartlett-Hann window. This window is defined by 0.62 - 0.48 * abs arr + 0.38* arr1, where the points in arr range from -1/2 through 1/2, and arr1 are the cos of points ranging from -PI through PI. =cut =head2 blackman($N) The 'classic' Blackman window. (Ref 1). One of the Blackman-Harris family, with coefficients a0 = 0.42, a1 = 0.5, a2 = 0.08 =cut =head2 blackman_bnh($N) The Blackman-Harris (bnh) window. An improved version of the 3-term Blackman-Harris window given by Nuttall (Ref 2, p. 89). One of the Blackman-Harris family, with coefficients a0 = 0.4243801, a1 = 0.4973406, a2 = 0.0782793 =cut =head2 blackman_ex($N) The 'exact' Blackman window. (Ref 1). One of the Blackman-Harris family, with coefficients a0 = 0.426590713671539, a1 = 0.496560619088564, a2 = 0.0768486672398968 =cut =head2 blackman_gen($N,$alpha) The General classic Blackman window. A single parameter family of the 3-term Blackman window. This window is defined by my $cx = arr; (.5 - $alpha) + ($cx * ((-.5) + ($cx * ($alpha)))), where the points in arr are the cos of points ranging from 0 through 2PI. =cut =head2 blackman_gen3($N,$a0,$a1,$a2) The general form of the Blackman family. One of the Blackman-Harris family, with coefficients a0 = $a0, a1 = $a1, a2 = $a2 =cut =head2 blackman_gen4($N,$a0,$a1,$a2,$a3) The general 4-term Blackman-Harris window. One of the Blackman-Harris family, with coefficients a0 = $a0, a1 = $a1, a2 = $a2, a3 = $a3 =cut =head2 blackman_gen5($N,$a0,$a1,$a2,$a3,$a4) The general 5-term Blackman-Harris window. One of the Blackman-Harris family, with coefficients a0 = $a0, a1 = $a1, a2 = $a2, a3 = $a3, a4 = $a4 =cut =head2 blackman_harris($N) The Blackman-Harris window. (Ref 1). One of the Blackman-Harris family, with coefficients a0 = 0.422323, a1 = 0.49755, a2 = 0.07922 Another name for this window is the Minimum three term (sample) Blackman-Harris window. =cut =head2 blackman_harris4($N) The minimum (sidelobe) four term Blackman-Harris window. (Ref 1). One of the Blackman-Harris family, with coefficients a0 = 0.35875, a1 = 0.48829, a2 = 0.14128, a3 = 0.01168 Another name for this window is the Blackman-Harris window. =cut =head2 blackman_nuttall($N) The Blackman-Nuttall window. One of the Blackman-Harris family, with coefficients a0 = 0.3635819, a1 = 0.4891775, a2 = 0.1365995, a3 = 0.0106411 =cut =head2 bohman($N) The Bohman window. (Ref 1). This window is defined by my $x = abs(arr); (1-$x)*cos(PI*$x) +(1/PI)*sin(PI*$x), where the points in arr range from -1 through 1. =cut =head2 cauchy($N,$alpha) The Cauchy window. (Ref 1). Other names for this window are: Abel, Poisson. This window is defined by 1 / (1 + (arr * $alpha)**2), where the points in arr range from -1 through 1. =cut =head2 chebyshev($N,$at) The Chebyshev window. The frequency response of this window has C<$at> dB of attenuation in the stop-band. Another name for this window is the Dolph-Chebyshev window. No periodic version of this window is defined. This routine gives the same result as the routine B in Octave 3.6.2. =cut =head2 cos_alpha($N,$alpha) The Cos_alpha window. (Ref 1). Another name for this window is the Power-of-cosine window. This window is defined by arr**$alpha , where the points in arr are the sin of points ranging from 0 through PI. =cut =head2 cosine($N) The Cosine window. Another name for this window is the sine window. This window is defined by arr, where the points in arr are the sin of points ranging from 0 through PI. =cut =head2 dpss($N,$beta) The Digital Prolate Spheroidal Sequence (DPSS) window. The parameter C<$beta> is the half-width of the mainlobe, measured in frequency bins. This window maximizes the power in the mainlobe for given C<$N> and C<$beta>. Another name for this window is the sleppian window. =cut =head2 exponential($N) The Exponential window. This window is defined by 2 ** (1 - abs arr) - 1, where the points in arr range from -1 through 1. =cut =head2 flattop($N) The flat top window. One of the Blackman-Harris family, with coefficients a0 = 0.21557895, a1 = 0.41663158, a2 = 0.277263158, a3 = 0.083578947, a4 = 0.006947368 =cut =head2 gaussian($N,$beta) The Gaussian window. (Ref 1). Another name for this window is the Weierstrass window. This window is defined by exp (-0.5 * ($beta * arr )**2), where the points in arr range from -1 through 1. =cut =head2 hamming($N) The Hamming window. (Ref 1). One of the Blackman-Harris family, with coefficients a0 = 0.54, a1 = 0.46 =cut =head2 hamming_ex($N) The 'exact' Hamming window. (Ref 1). One of the Blackman-Harris family, with coefficients a0 = 0.53836, a1 = 0.46164 =cut =head2 hamming_gen($N,$a) The general Hamming window. (Ref 1). One of the Blackman-Harris family, with coefficients a0 = $a, a1 = (1-$a) =cut =head2 hann($N) The Hann window. (Ref 1). One of the Blackman-Harris family, with coefficients a0 = 0.5, a1 = 0.5 Another name for this window is the hanning window. See also L. =cut =head2 hann_matlab($N) The Hann (matlab) window. Equivalent to the Hann window of N+2 points, with the endpoints (which are both zero) removed. No periodic version of this window is defined. This window is defined by 0.5 - 0.5 * arr, where the points in arr are the cosine of points ranging from 2PI/($N+1) through 2PI*$N/($N+1). This routine gives the same result as the routine B in Matlab. See also L. =cut =head2 hann_poisson($N,$alpha) The Hann-Poisson window. (Ref 1). This window is defined by 0.5 * (1 + arr1) * exp (-$alpha * abs arr), where the points in arr range from -1 through 1, and arr1 are the cos of points ranging from -PI through PI. =cut =head2 kaiser($N,$beta) The Kaiser window. (Ref 1). The parameter C<$beta> is the approximate half-width of the mainlobe, measured in frequency bins. Another name for this window is the Kaiser-Bessel window. This window is defined by barf "kaiser: PDL::GSLSF not installed" unless $HAVE_BESSEL; $beta *= PI; my @n = PDL::GSLSF::BESSEL::gsl_sf_bessel_In ($beta * sqrt(1 - arr **2),0); my @d = PDL::GSLSF::BESSEL::gsl_sf_bessel_In($beta,0); (shift @n)/(shift @d), where the points in arr range from -1 through 1. =cut =head2 lanczos($N) The Lanczos window. Another name for this window is the sinc window. This window is defined by my $x = PI * arr; my $res = sin($x)/$x; my $mid; $mid = int($N/2), $res->slice($mid) .= 1 if $N % 2; $res;, where the points in arr range from -1 through 1. =cut =head2 nuttall($N) The Nuttall window. One of the Blackman-Harris family, with coefficients a0 = 0.3635819, a1 = 0.4891775, a2 = 0.1365995, a3 = 0.0106411 See also L. =cut =head2 nuttall1($N) The Nuttall (v1) window. A window referred to as the Nuttall window. One of the Blackman-Harris family, with coefficients a0 = 0.355768, a1 = 0.487396, a2 = 0.144232, a3 = 0.012604 This routine gives the same result as the routine B in Octave 3.6.2. See also L. =cut =head2 parzen($N) The Parzen window. (Ref 1). Other names for this window are: Jackson, Valle-Poussin. This function disagrees with the Octave subroutine B, but agrees with Ref. 1. See also L. =cut =head2 parzen_octave($N) The Parzen window. No periodic version of this window is defined. This routine gives the same result as the routine B in Octave 3.6.2. See also L. =cut =head2 poisson($N,$alpha) The Poisson window. (Ref 1). This window is defined by exp (-$alpha * abs arr), where the points in arr range from -1 through 1. =cut =head2 rectangular($N) The Rectangular window. (Ref 1). Other names for this window are: dirichlet, boxcar. =cut =head2 triangular($N) The Triangular window. This window is defined by 1 - abs arr, where the points in arr range from -$N/($N-1) through $N/($N-1). See also L. =cut =head2 tukey($N,$alpha) The Tukey window. (Ref 1). Another name for this window is the tapered cosine window. =cut =head2 welch($N) The Welch window. (Ref 1). Other names for this window are: Riez, Bochner, Parzen, parabolic. This window is defined by 1 - arr**2, where the points in arr range from -1 through 1. =cut =head1 AUXILIARY SUBROUTINES These subroutines are used internally, but are also available for export. =head2 cos_mult_to_pow Convert Blackman-Harris coefficients. The BH windows are usually defined via coefficients for cosines of integer multiples of an argument. The same windows may be written instead as terms of powers of cosines of the same argument. These may be computed faster as they replace evaluation of cosines with multiplications. This subroutine is used internally to implement the Blackman-Harris family of windows more efficiently. This subroutine takes between 1 and 7 numeric arguments a0, a1, ... It converts the coefficients of this a0 - a1 cos(arg) + a2 cos( 2 * arg) - a3 cos( 3 * arg) + ... To the cofficients of this c0 + c1 cos(arg) + c2 cos(arg)**2 + c3 cos(arg)**3 + ... =head2 cos_pow_to_mult This function is the inverse of L. This subroutine takes between 1 and 7 numeric arguments c0, c1, ... It converts the coefficients of this c0 + c1 cos(arg) + c2 cos(arg)**2 + c3 cos(arg)**3 + ... To the cofficients of this a0 - a1 cos(arg) + a2 cos( 2 * arg) - a3 cos( 3 * arg) + ... =cut =head2 chebpoly =for usage chebpoly($n,$x) =for ref Returns the value of the C<$n>-th order Chebyshev polynomial at point C<$x>. $n and $x may be scalar numbers, pdl's, or array refs. However, at least one of $n and $x must be a scalar number. All mixtures of pdls and scalars could be handled much more easily as a PP routine. But, at this point PDL::DSP::Windows is pure perl/pdl, requiring no C/Fortran compiler. =cut =head1 REFERENCES =over =item 1 Harris, F.J. C, I, 1978, vol 66, pp 51-83. =item 2 Nuttall, A.H. C, I, 1981, vol. ASSP-29, pp. 84-91. =back =head1 AUTHOR John Lapeyre, C<< >> =head1 ACKNOWLEDGMENTS For study and comparison, the author used documents or output from: Thomas Cokelaer's spectral analysis software; Julius O Smith III's Spectral Audio Signal Processing web pages; André Carezia's chebwin.m Octave code; Other code in the Octave signal package. =head1 LICENSE AND COPYRIGHT Copyright 2012 John Lapeyre. This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See http://dev.perl.org/licenses/ for more information. This software is neither licensed nor distributed by The MathWorks, Inc., maker and liscensor of MATLAB. =cut