Welcome to Fiview, an FIR/IIR filter design, viewing and comparison tool
------------------------------------------------------------------------
This is the help-text, which can be brought up at any point by
pressing 'h' or F1. This is being viewed in the built-in pager, which
may be controlled using the following keys:
Up/Down arrow Up or down a line at a time
PageUp/PageDn Up or down a page at a time
BackSp/Space Up or down a page at a time
d Down a half-page
Return Down a line
This text can also be viewed using a command line pager, for example:
fiview -h | more
Legal stuff
-----------
Fiview: an FIR/IIR filter design, viewing and comparison tool:
Copyright (c) 2002-2003 Jim Peters, , all rights
reserved. Released under the GNU General Public Licence version 2.
See the file COPYING for details, or visit .
The SDL library code is released under the GNU Lesser General Public
Licence version 2 or later. See file COPYING_LIB for details. See
for more information about this project.
Much of the filter design code was based on 'mkfilter' by Tony
Fisher; see here: .
Dr Fisher died in February 2000 (see his site for a tribute), but
confirmation that his code could be used was given by Anthony Moulds
of the University of York. See file 'fidlib/fidmkf.c'.
"This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation."
"This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details."
"You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA"
Keyboard and mouse control
--------------------------
These keys apply at all times:
1-9 The digits switch between the different loaded filters
Esc or q Quit the program
F1 Switch to this help display
F2 Switch to the filter information display
F3 Switch to the frequency response display
F4 Switch to the time response display
As you've probably noticed, the frequency and time responses are shown
constantly at the top of the screen in miniature. The large area
where this text appears is the area in which the different displays
appear. The filter information and help-text displays use the pager,
whose keys were listed above.
The frequency and time-response displays are controlled as follows:
Left/Right Move the view left or right by 25% of the display width
PageUp/PageDn Move the view left or right by 100% of the display width
BackSp/Space Move the view left or right by 100% of the display width
Up Zoom out
Down Zoom in
a Auto-adjust to the most interesting part of the response
The shaded area in the miniature time or frequency display always
follows the movements in the main display, helping you keep track of
what you are looking at.
Note that the viewing window ranges stay the same as you switch
between different filters using the 1-9 keys. This allows you to
compare the response in a critical area of two filters by simply
switching between them. However, if they are different types of
filters, you'll probably want to press 'A' after switching to get the
interesting bit back into view.
The frequency display
---------------------
This shows the frequency response. The mini display at the top shows
the range from 0.0 to 0.5 of the sampling rate. However, the range
actually goes on beyond that (wrapping around, mirrored). The main
display allows you to view slightly outside the 0.0 to 0.5 range to
make sense of the shape of some filter responses such as low-pass and
high-pass filters.
When the filter is first loaded it is scanned to find its major
features. A guess is made to the type of the filter, and a certain
level is selected as representing the '100%' level for the filter.
This needn't necessarily be the peak response -- for example, for a
low-pass filter, the response at 0Hz (DC) is taken to be the 100%
level, because there may be ripples away from 0Hz.
This is the meaning of the percentage values displayed as the mouse
moves over the display. Also displayed are the frequency of that
pixel and the actual range of response values covered by that pixel.
The blue lines going across the display are the phase values. Note
that when the response is very low (less than 1e-10 compared to the
100% level, for example), the calculated phase can become unreliable
due to the accuracy of 64-bit floating point calculation. This should
help explain any 'noise' areas you see in the phase display. This
noise also shows up as unexpected min/max points in the 'm' display
(see below).
Note that the phase display depends on which point you measure from.
For example, a low pass filter will often show very steep phase
changes in the passband. However, if you take into account the delay
of the filter, these can be made to look flat, moving the steep phase
lines into the stopband.
If you press and hold the 'm' key, a number of rulers appear on the
display. These show all the minima and maxima as calculated for the
current display, along with the -3.01dB/-6.02dB crossing points
(70.71%/50%). The labels for each line are always attached to that
line somewhere, and response labels try to get as close to their
min/max as possible, but if there is reduced space, they might be
forced elsewhere on the display. Zoom in if it is too confusing.
It is also possible to feed test signals to the filter using this
screen, to see how it responds. For example, type 'ts1' to
test the filter with 1Hz/sec upwards-sweeping tones, or 'tw8'
to test it with 8-period wavelets. Type 't' to exit testing
mode. See the "Filter testing mode" section below for full details
of this.
Also log-scale views are possible by pressing the 'L' key and then a
digit to indicate the number of power-of-ten ranges to display, or
some other key to return to the normal linear display.
Summary of special frequency-display keys:
a Auto-adjust to the most interesting part of the response
m Show rulers and min/max/-3.01dB/-6.02dB points
t Set a testing mode
x Expand the vertical range to take in any out-of-range values
z Zoom the vertical range to show low-response areas
l Change to/from log-scale view
The time-response display
-------------------------
The time-response display shows which samples out of your data stream
will be taken into account by this particular filter. Time zero is at
the right of the display, and earlier times come before.
This time-response is actually just the impulse response of the
filter reversed. For an IIR filter, it is also the equivalent FIR
that could be used to emulate it.
When the filters are loaded, the number of data samples required for the
filter to calculate an accurate value are found (see the information
display for these details). This information is also available when
moving the mouse over the display, along with the sample count, time and
response values.
It is useful to see how broad a chunk of data a particular filter works
on, as this will give you an idea of how much it will blur information
across time. For example, filters with very sharp responses will
probably require a great deal of data, but that is not necessarily the
best option, because transient wave-streams might hardly show up with
such filters. Comparing both frequency response and time-response
between different filters should help in judging the balance to make
between these factors for a particular application.
Summary of special time-display keys:
a Auto-adjust to the most interesting part of the response
z Zoom in vertical scale to show any low-amplitude signals
Command-line invocation
-----------------------
Type 'fiview' on its own to get a summary of current options (which
might include some not mentioned here). Here are some example
command-lines:
fiview -i LpBe4/0.01
This loads up a predefined filter type, a low-pass Bessel 4th order
filter, using a cut-off frequency of 0.01 times the sampling rate.
fiview 200 -i LpBe4/2
This loads up exactly the same filter, except in this case the
sampling rate of 200Hz is specified, and the cut-off is now given in
Hz (==2Hz). The sampling rate is also used in the app to display
values in Hz.
fiview 200 -i LpBe2/2, LpBe4/2, LpBe6/2, LpBe8/2
This loads up a set of filters, which are mapped to the keys 1-4.
Actually, this set of filters could be more efficiently written by
specifying the frequency using -f:
fiview 200 -f 2 -i LpBe2,LpBe4,LpBe6,LpBe8
All of the filters above default to the given -f frequency of 2Hz as
no frequency is mentioned after them. This also works for pre-defined
filters that require frequency ranges. For example, the following two
commands are equivalent:
fiview 200 -i BpBe8/2-3
fiview 200 -f 2-3 -i BpBe8
You are not just limited to a single filter stage per display. See
below ("Format of filter specification files") for more information
on this, but as an example this filter combines two band-stop filters
and a low-pass filter in one display:
fiview 200 -i LpBe4/20 x BsBu4/5-6 x BsBu4/9-10
For comparing a number of filters of different types, the auto-adjust
option is useful. This iteratively adjusts the filter half-power
points (-3.01dB or 70.71% response) to meet the frequency values you
specify, instead of using the estimates given by the filter design
routines. Use this by prefixing the frequencies with an '=' sign,
either in the -f option, or in the filter spec themselves. For
example:
fiview 200 -f =10 -i LpBe2,LpBe4,LpBu2,LpBu4
fiview 200 -i BpBu8/3-4, BpBu8/=3-4
In all the above examples, I have been using the -i immediate option,
which allows filters to be specified on the command line. However,
filter specifications can also be read from files, in which case the
-i is omitted and the filenames are listed instead. For example:
fiview 200 test_filters_1 test_filters_2
You can also specify default frequencies using -f as before, in which
case they are used by any filters within the files that don't have
frequencies specified. For example:
fiview 200 -f 12.5 test_filters
@@@ Add notes about -F and -W options
Output files
------------
Fiview creates two output files in the current directory whenever it
runs. The first file 'fiview.log' contains all the text that
appears on the filter information display for each of the filters.
This includes the example code, with the analysis in the comments.
The second file 'fiview.coef' contains all of the filters expressed
purely in terms of their FIR and IIR coefficients, and in a format
which can be re-read into Fiview on a later run as a specification
file. This is intended to allow external tools to use Fiview to
design a filter and then get access to the resulting coefficients for
further processing. For this application, use the -Q option to quit
Fiview once the analysis is complete, before bringing up the user
interface.
Format of filter specification files
------------------------------------
A filter specification file may contain one or more different filters,
separated (or terminated) by ',' or ';' characters. Comments may also
appear, using a line of their own with '#' after any initial white
space.
A specification can be given in terms of IIR/FIR coefficients and the
predefined filter types. For example, just using coefficients:
# Test filter
0.9972 / -1 1.9955 -0.9971 x 1 -1.9985 1
/ -1 1.9959 -0.9973 x 1 -1.9985 1
or using a predefined filter type:
# Low-pass bessel, order 3
LpBe3/0.05
or:
# Band-pass butterworth, order 5
BpBu5/=0.05-0.08
or using combinations:
# Some strange filter
0.9972 / -1 1.9955 -0.9971 x 1 -1.9985 1 x LpBe3/0.05;
# Some other strange filter
LpBe3/0.05 x LpBe5/0.03
When a filter is given in terms of FIR/IIR coefficients, use 'x' to
start an FIR list, and '/' to start an IIR list. The first list is
assumed to be an FIR list if no 'x' or '/' is included. The order of
coefficients compared to time '0' is closest first to farthest last.
So 'x 0 0 1' would be a delay of two samples.
For predefined filter types, remember that the frequency or frequency
range can be omitted if it is given on the command-line. So for
example, this file could generate a selection of Bessel low-pass
filters, assuming the -f option is given on the command-line:
# Bessel low-pass filters of different orders
LpBe1;
LpBe2;
LpBe3;
LpBe4;
See below for the list of predefined filters. Predefined filters can
only be combined using 'x', but beyond that there are no limits -- you
can combine as many as you wish, with any combination of other IIR/FIR
filters.
Filter types
------------
(see below for notes on these filters)
BpRe//
Bandpass resonator, Q= (0 means Inf), frequency
BsRe//
Bandstop resonator, Q= (0 means Inf), frequency
ApRe//
Allpass resonator, Q= (0 means Inf), frequency
Pi/
Proportional-integral filter, frequency
PiZ/
Proportional-integral filter, matched z-transform, frequency
LpBe/
Lowpass Bessel filter, order , -3.01dB frequency
HpBe/
Highpass Bessel filter, order , -3.01dB frequency
BpBe/
Bandpass Bessel filter, order , -3.01dB frequencies
BsBe/
Bandstop Bessel filter, order , -3.01dB frequencies
LpBu/
Lowpass Butterworth filter, order , -3.01dB frequency
HpBu/
Highpass Butterworth filter, order , -3.01dB frequency
BpBu/
Bandpass Butterworth filter, order , -3.01dB frequencies
BsBu/
Bandstop Butterworth filter, order , -3.01dB frequencies
LpCh//
Lowpass Chebyshev filter, order , passband ripple dB,
-3.01dB frequency
HpCh//
Highpass Chebyshev filter, order , passband ripple dB,
-3.01dB frequency
BpCh//
Bandpass Chebyshev filter, order , passband ripple dB,
-3.01dB frequencies
BsCh//
Bandstop Chebyshev filter, order , passband ripple dB,
-3.01dB frequencies
LpBeZ/
Lowpass Bessel filter, matched z-transform, order , -3.01dB
frequency
HpBeZ/
Highpass Bessel filter, matched z-transform, order , -3.01dB
frequency
BpBeZ/
Bandpass Bessel filter, matched z-transform, order , -3.01dB
frequencies
BsBeZ/
Bandstop Bessel filter, matched z-transform, order , -3.01dB
frequencies
LpBuZ/
Lowpass Butterworth filter, matched z-transform, order , -3.01dB
frequency
HpBuZ/
Highpass Butterworth filter, matched z-transform, order , -3.01dB
frequency
BpBuZ/
Bandpass Butterworth filter, matched z-transform, order , -3.01dB
frequencies
BsBuZ/
Bandstop Butterworth filter, matched z-transform, order , -3.01dB
frequencies
LpChZ//
Lowpass Chebyshev filter, matched z-transform, order , passband
ripple dB, -3.01dB frequency
HpChZ//
Highpass Chebyshev filter, matched z-transform, order , passband
ripple dB, -3.01dB frequency
BpChZ//
Bandpass Chebyshev filter, matched z-transform, order , passband
ripple dB, -3.01dB frequencies
BsChZ//
Bandstop Chebyshev filter, matched z-transform, order , passband
ripple dB, -3.01dB frequencies
LpBuBe//
Lowpass Butterworth-Bessel % cross, order , -3.01dB
frequency
LpBq//
Lowpass biquad filter, order , Q=, -3.01dB frequency
HpBq//
Highpass biquad filter, order , Q=, -3.01dB frequency
BpBq//
Bandpass biquad filter, order , Q=, centre frequency
BsBq//
Bandstop biquad filter, order , Q=, centre frequency
ApBq//
Allpass biquad filter, order , Q=, centre frequency
PkBq///
Peaking biquad filter, order , Q=, dBgain=,
frequency
LsBq///
Lowpass shelving biquad filter, S=, dBgain=, frequency
HsBq///
Highpass shelving biquad filter, S=, dBgain=, frequency
LpBl/
Lowpass Blackman window, -3.01dB frequency
LpHm/
Lowpass Hamming window, -3.01dB frequency
LpHn/
Lowpass Hann window, -3.01dB frequency
LpBa/
Lowpass Bartlet (triangular) window, -3.01dB frequency
Filter notes
------------
Bessel: This IIR filter gives a nice domed response in frequency, and
also a nice domed response in time. This is something approaching
the ideal balance between time and frequency response for the
display for applications like BWView (although I'm currently using a
Blackman window there).
Butterworth: This IIR filter gives flat responses away from the
transition areas, and sharp transitions, especially as the order
increases. However, this sharp frequency response is paid for with
a wider and wider (i.e. more blurry) time-response.
Chebychev: This IIR filter exchanges some of the flatness in the
passband of the Butterworth filter for a sharper fall-off at the
cut-off frequency. The resulting filter also takes more time to
settle (see the time response). The amount of permitted passband
ripple is specified in dB, and should be negative, for example:
"LpCh4/-0.1" or "LpCh4/-1".
All of these types come in a matched-Z version (LpBeZ,HpBuZ,etc) which
uses the matched-Z transform instead of the bilinear transform. This
eliminates the FIR part of the filter for low-pass filters, making
them pure IIR. You really need to read what Tony Fisher has to say
about this on his site to understand whether to use it or not.
Briefly he suggests this option is useful for generating Bessel
filters with optimally linear phase response, or for generating
filters that execute slightly faster, but the bilinear transform is
otherwise superior.
Resonators: These IIR filters are based on oscillators, equivalent to
a tuned circuit. The gives the narrowness of the resonator
response. Low values give wider response and faster decay to the
oscillations. Infinity can be represented using a value of '0',
which gives a pure oscillator -- for example: "BpRe/0/0.1". The
all-pass version (ApRe) has unit response, but the phase varies with
frequency, changing rapidly around the resonant frequency. These
are all from mkfilter -- Tony Fisher there suggests that band-stop
and band-pass filters made with resonators are often more efficient
and better-behaved than Butterworth filters. See the mkfilter docs
for more info on all of this (the URL is close to the top of this
file).
Proportional-integral: I don't know what these are for, and they're
not documented on the mkfilter site either. The IIR part, at least,
just totals up all the samples received (an 'integral'). I guess
you'll know if you want this. This is probably the digital version
of some analogue op-amp technique. Also note that they don't
display at all well in either mkfilter or fiview!
Biquad filters: These are based on Robert Bristow-Johnson's audio EQ
cookbook formulae (see the source for more details). The Q factor
selects the shape of the response curve. Order 1 gives the curves
as specified in the original document. Higher orders stack up these
filters. Note that an order one biquad filter is equivalent to an
order two Bessel or Butterworth filter -- compare LpBe2 with LpBu2
and LpBq1/0.5, for instance. The auto-adjust option is useful to
get the required half-power points (-3.01dB, 70.71% response) when
comparing filters from different families like this.
Biquad low-pass and high-pass filters: For a low-pass filter, the
significant values are Q=0.5, which is the maximum value to give no
overshoot in the time response, and Q=0.707, which gives the most
flat-topped frequency response without having a 'lip'.
Biquad band-pass, band-stop, all-pass and peaking filters: For these,
larger Q values are good -- try up to Q=10 or more. The peaking
filter is designed to emphasise a frequency range. The second value
in this case is the peak gain in dB. For example: PkBq1/3/10/0.1
Biquad audio shelving filters: These use a 'shelf slope' parameter
instead of Q. S=1 gives the steepest slope without a lip, and lower
values give lower values of slope. The second parameter is the gain
in the affected area in dB.
Window functions: Bartlett, Hann, Hamming and Blackman window functions
are available here. These act as FIR low-pass filters. To understand
these filters better, it is good to try them with a log display: type
'L5' and adjust to view the full frequency range. Also compare these
filters to Bessel IIR filters (e.g. LpBe6).
Filter testing mode
-------------------
Whilst the frequency response display is active, it is possible to
test the filter by passing test signals through it. Testing mode is
entered by typing 't', then the test-signal spec, and then .
You exit the mode by simply pressing 't' and then . The 'x'
(expand) key may be useful to view any measured points which are off
the top of the display.
Two test signals are provided. These can be useful for getting a more
realistic view of your filter than the idealised calculated frequency
response (which assumes you always have perfect infinitely-long
sine-waves as input).
The first test signal is a sweeping tone, a sine-wave with linearly
increasing or decreasing frequency. By passing a smoothly-varying
sine-wave through the filter, you might expect to get out of the other
end a response matching the shape of the response curve for that
frequency range. However, this is not the case. As the rate of the
tone's frequency change increases, the shape of the output becomes
more and more distorted. This is most noticeable in filters that have
a long time-response because different parts of the filter will catch
different frequencies out of the sweeping tone. Test this by entering
a spec of 's' followed by the rate of change of the tone's frequency
in Hz/sec, either positive or negative (e.g. 's0.1' or 's-1.5'). With
a rate of change of 0 ('s0'), this should give an identical response
to the calculated response.
(Note that the test signals passed to the filter aim to put the target
frequency at the correct centre of the filter time-response, but this
is not always accurate, resulting in a measured response which may be
offset either to the left or right compared to the calculated
response. The shape will be correct, though, even if it has been
offset by a few Hz.)
The second test signal is a wavelet of a given number of wave periods.
This can give you an idea of how transient signals are handled by the
filter. Test with a wavelet by using a spec of 'w' plus the length of
the wavelet in wave-periods, for example 'w8', 'w20' or 'w100'.
(Note that the wavelets are formed by applying a Blackman window to a
sine-wave. The 'length' is the full length of the Blackman window.
For frequencies close to zero, the wavelets can be immensely long, so
the calculation drops out, and the points will be missing from the
display.)
General notes:
Although I've said 'sine-wave' in the descriptions above, I'm actually
running a complex oscillator through the filters, i.e. two independent
sine-waves 90 degrees out of phase. This means that I can work with
continuous output values, without having to watch out for maxima,
giving more accurate results.
Also, regarding accuracy: Sweeps are calculated to the 99.9% point of
the filter, i.e. to roughly 3sf. Wavelets are limited by the
behaviour of the window for very high frequencies. The program
doesn't stop you looking beyond the limits of the accuracy of the
algorithms, so in the extreme limits you may be examining artifacts of
the analysis methods rather than artifacts of your filter. In fact,
by zooming in on very small features, you can even get to see
artifacts of the 64-bit floating point format! Double-check with your
own testing if these things matter to you, or adjust the Fiview code.
TODO
----
Make long impulse-response filter checks time-out after 2 sec each
filter to make performance similar on different-spec machines.
Clean up remaining JIT run-filter bugs, or drop the JIT option; only
gives around 20% speed-up when enabled
Add FIR filters (hamming, blackman, Tony Fisher's ones)
Probably need to put some loops in the generated example code to
handle big FIRs more nicely
Cross-test new generated fid_design code against other types of
generated example code
TO FIX
------
The second filter here comes out with twice the amplitude on the display:
./fiview 200 -f =0.1-0.11 -i BpBe4,BpBe5
MAYBE
-----
Maybe put in code to flatten the phase in the pass-band and display
the equivalent delay. For LP and HP, it would be possible to
calculate the slope of the phase at f=0.0 and 0.5 by substituting in a
small delta and eliminating delta-squared and higher.
Maybe clicking on mini displays shifts within main display
Maybe click on main displays zooms in and out (L + R)
Maybe drag on main display moves display
Maybe add bigger font, and switch automatically to it for larger displays.
Maybe make FidFilter type into a full filter-expression
representation, permitting addition as well as serial combination of
filters, and also special types such as tunable heterodyne filters
in the form Het1(LpBu10) or whatever. Need to write generation and
RunFilter code for these new types as well. Significant work.
Maybe give generated process() and setup() calls names including the
spec, e.g process_LpBu4. Problems with combined filters, but perhaps
we could allow these to be labelled, and carry the label over.