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.