Kok Chen, W7AY [w7ay (at) arrl (dot) net]
Last updated: November 19, 2010
cocoaFilter is a CW audio peak filter (APF) for Mac OS X.
The application takes audio from a transceiver though an input sound card, applies a bandpass filter that has an adjustable center frequency and Q (or bandwidth), and passes the signal to an output sound card, which can then be fed to speakers or a pair of headphones.
cocoaFilter requires minimally Mac OS X 10.6 (Snow Leopard) to run in. The application can be downloaded from here.
Double click on the downloaded Disk Image (dmg) to open the volume, and drag copy the cocoaFilter application to your Applications folder. The dmg file also contains a settings file (cocoaFilter.pmset) to control cocoaFilter from a PowerMate (the PowerMate installation procedure described below in the Main Window section).
cocoaFilter is completely free and is not a supported program. I wrote it to experiment with a few ideas. If you have other ideas, the Objective-C sources for cocoaFilter are in the Xcode project for further experimentation. See the section that describes technical details further down.
The sound cards are selected in the cocoaFilter Preference panel.
You can choose either the left or the right channel of an input stereo sound card. You can choose to send the output of cocoaFilter to the left, right or both channels of the output sound card. cocoaFilter only supports the first two channels of a sound card that contains more than 2 channels. The channels popup menu is grayed out for sound cards that contain only a single channel (e.g., an Apple iSight).
Sound cards may have multiple sources. The input sound card in the figure above is multiplexed between a microphone input and a line level input, for example, and the rightmost set of sound card popup menus is set to select the line input. Be sure to set the menu to what you have wired the sound card for. For sound cards that contain only a single source, the source menus will be grayed out, showing a Default menu item, and no source selection needs to be made.
So as not to affect other applications that cocoaFilter is sharing a sound card with (e.g., cocoaModem), cocoaFilter neither sets nor changes the sampling rate of a sound card. cocoaFilter will adapt to the sampling rates that other applications have chosen. Please read the later IIR Filter section on preferred sampling rates. If you want to change the sampling rate, you can use the Mac OS X "Audio MIDI Setup" utility that is in the Utilities folder of the Snow Leopard Applications folder.
As seen in the above figure, cocoaFilter has a limiter that clips at a level which is adjustable down to 20 dB below the full scale of the output sound card. The limiter can apply hard clipping or soft clipping (shown above) or be turned completely off.
(See section "IIR Filter" below for a description of the IIR Tilt parameter in the Preference panel.)
The Preference panel is opened by using the "Preferences..." menu item in cocoaFilter's main menu (just to the right of the Apple menu in the main Menu Bar). The Preference panel can also be opened from the "Preferences" menu in cocoaFilter's Window menu in the main Menu Bar:
All parameters from Preferences panel, plus filter parameters, window positions, etc, are saved to a plist when you exit cocoaFilter. The cocoaFilter plist is a file in the Preferences folder of your home directory's Library folder with the name w7ay.cocoaFilter.plist. This is the only file that is created by cocoaFilter. The plist file is in XML format and can be opened with a text editor or the Mac OS X Property List Editor.
The main cocoaFilter window contains the controls and means of selecting filters. By using the tabs, you can select between an IIR (infinite impulse response) filter, an FIR (finite impulse response) filter, a flat filter (input is pass to the output with no filtering) or to turn output sound off completely (sampling stops, and effectively muting the output from cocoaFilter).
The two filters are discussed in detail in the IIR Filter and FIR filter sections below.
Like all Mac OS X sound applications, the cocoaFilter's output is mixed with the output of other applications before it is sent to the sound card. If iTunes is playing to the sound card, for example, cocoaFilter's output will be mixed with it.
Separate attenuation sliders for the input and output sound cards are at the bottom of the main cocoaFilter window. A "VU Meter" in between the two sliders measures the peak input to warn of any clipping of the input sound card.
Please note that the values of these attenuators are also shared with other applications. For example, if iTunes is using the same output sound card, the cocoaFilter output slider will also affect the output volume from iTunes. However, the input slider in cocoaFilter will not affect iTunes output. Neither controls will affect iTunes if the latter application uses a different output sound card than cocoaFilter. Likewise, if the input sound card is shared with cocoaModem, the cocoaFilter slider will affect the input level cocoaModem receives from the sound card.
When lit, the rightmost two bars of the "VU Meter" will appear as yellow and red bars. You must keep the input slider set to a low enough position so that the yellow and red bars never appear. If the input sound card clips, the filters will no longer be linear -- at which point, they no longer behave like bandpass filters, and the output from cocoaFilter can become severely distorted.
Some A/D converters do not come with adjustable digital attenuators. In these cases, the cocoaFilter slider will be grayed out, and you will need some other (e.g., analog pot) methods to keep the input sound card from clipping.
The center frequencies of the IIR and the FIR filter are locked to one another. When you change from an IIR to an FIR filter (and vice versa), the new filter takes the center frequency from the filter you just left. The center frequency can be varied between 300 Hz to 1100 Hz.
The IIR filter has adjustable Q that is between 1 and 30, and the FIR filter has adjustable -10 dB bandwidth that is between 20 Hz and 300 Hz.
The center frequency of the IIR and FIR filters can be adjusted by
- using the Fc sliders in the main window
- directly typing the frequency into the Fc text field
- using the scroll wheel on the mouse
- using the left and right arrow keys on a keyboard
- using the knob of a PowerMate.
The frequency sliders are controlled by the mouse scroll wheel when either the main cocoaFilter window or the transfer function window is active. If you hold down the Command key on the keyboard, the mouse scroll wheel will control the Q of the IIR filter, and the bandwidth of the FIR filter.
You can speed up the keyboard and mouse scroll wheel tuning rate by holding down the Option key.
The left and right arrows on the keyboard can also be used to control the center frequency of the filters. The up and down arrow keys on the keyboard controls the Q of the IIR filter, or the bandwidth of the FIR filter.
The PowerMate gives the smoothest and most intuitive way for adjusting cocoaFilter parameters. To use a PowerMate, you will need to import the PowerMate settings file (cocoaFilter.pmset) that resides in the cocoaFilter disk image, into the PowerMate application. Simply drag and drop the file into PowerMate window's item list (as described here).
If you have a Griffin Technology PowerMate and have installed the cocoaFilter settings, knob rotation controls the center frequency. cocoaFilter looks at how fast you rotate the knob. Faster rotation will change the frequency by a larger step. If you press the knob down towards the table, and rotate the knob, the PowerMate controls the Q or the bandwidth of the filters.
Transfer Function Window
The filter response of the currently selected filter can be viewed in the transfer function window. The transfer function display changes in real time as you adjust filter parameters, so you can get an instantaneous graphical view of the filter response.
The transfer function window is opened by selecting the Transfer Function menu item in cocoaFilter's Window menu. The vertical dashed green markers show a log scale of frequency. The left edge of the transfer function plot represents 100 Hz and the right edge of the plot represents approximately 3200 Hz. The rightmost vertical line that appears in the plot is located at 3000 Hz.
The vertical scale is shown by horizontal dashed lines that are separated by 10 dB. The topmost line show in the plot represents a +10 dB gain. The next line down represents 0 dB gain, etc.
The plot above shows the response of the IIR filter with center frequency set to 500 Hz and Q set to 20.
The transfer function window is closed by using the red close button at the left of the window's title bar. If the window was visible when you last quit cocoaFilter, it will automatically open the next time you launch cocoaFilter and positioned in the computer display where you had earlier left it.
The display updates when you switch between an IIR and an FIR filter.
As mentioned earlier, an IIR filter is selected by selecting the IIR tab in the main cocoaFilter window.
The cocoaFilter IIR filter mimics the behavior of the traditional APF. The center frequency of cocoaFilter's IIR filter can be adjusted between 300 Hz and 1100 Hz and the Q can be adjusted between 1 and 30.
The following figures show the IIR at Q= 20, and center frequency set to 400 Hz (left) and 800 Hz (right).
The gain of the IIR filter is increased slightly as the Q is increased, to a little more than 10 dB at a Q of 30. Even with this gain, the white noise floor is still monotonically reduced as Q is increased, but the gain for the actual centered signal increase gives a better psychoacoustic effect as the Q of the filter is increased.
The following figures show the IIR with a center frequency of 615 Hz, and Q set to 10 (left) and 30 (right). Notice the gain boost.
In addition to the center frequency and Q adjustments, up to about 3 dB/octave of spectrum "tilt" can be applied to the IIR filter (in the Preference panel). This lets you tailor the noise spectrum when the Q of the filter is low. The audible effect is minimal when the Q is raised to 30 but the "color" of the noise is quite evident at a Q of 1 and a tilt might sound more pleasant sounding to some.
A tilt of 0 gives the traditional symmetrical bandpass, and a tilt of 3 dB/octave ("pink noise") suppresses the higher frequencies at the cost of raising low frequency noise. (A side note: the APF of the Yaesu FT-1000D, arguably the best APF known, is not symmetric but has a slight passband tilt.)
The following figures show the IIR filter transfer functions with a Q of 1. The left figure has a 0 dB tilt of a symmetrical bandpass filter, and the right hand figure shows a tilt of 3 dB/octave (more obvious at lower frequencies). (The FT-1000D has a tilt that is not as severe as the 3 dB/octave shown in the figure on the right.)
The IIR filter coefficients are computed on-the-fly when you change the center frequency, Q or tilt of the filter. The filter design uses the bilinear transform methodology to model an analog filter and it requires the sampling rate to be much higher than the filter passband to obtain an accurate digital representation. You can watch the transfer function change when you change the sampling rate. In general, using an input sampling rate of 8000 samples/second will produce a filter that looks a little different (and also sound a little different) from using 16000 samples/second. The second order filter appears to converge after 32000 samples/second, and you should notice only small differences between using 32000, 44100 or 48000 samples/second. There is no reason to go beyond 48000 samples/second for this type of application.
The easiest way to adjust the sampling rate is through the application Audio MIDI Setup in the /Application/Utilities folder of Snow Leopard. You can also change the sampling rate by using an application such as cocoaModem.
The second filter in cocoaFilter is an FIR (finite impulse response) filter. Unlike traditional FIR bandpass design that has a flat top which generally determines the bandwidth of the filter, cocoaFilter's FIR is designed as an infinitesimally narrow filter, but using wider than usual "transition band" (the digital equivalent of the "skirt" of an analog filter). The equivalent noise bandwidth of the filter is therefore determined from the filter's window, not from the non-existent flat top passband.
The following figures show the FIR filter transfer functions with a center frequency of 615 Hz, at a bandwidth of 20 Hz (left) and 40 Hz (right). Notice the purposely "flared" response and a lack of flat top when compared to traditional FIR bandpass filters. But unlike the IIR case, notice that the "flaring" does not start from as high level as in the IIR case.
The reason for picking a transfer function above is to experiment with a conjecture of mine that even though a narrow filter for both signal and noise is optimal in the least squares sense, it is perhaps harder for the human ear-brain system to copy a carrier if the noise spectrum is too similar to the spectrum of the carrier. This could explain why analog audio peaking filters are much better for aural copy of Morse than very narrow FIR filters.
The noise spectrum of the cocoaFilter FIR filter is purposely broadened (but at levels below -20 dB) to give the noise a different characteristics than the signal. Total noise power is not increased significantly, but the noise "color" is aurally different from a narrow bandpass noise.
For the same 10 dB bandwidth, this type of transfer function also appears to produce a filter that is less "hollow sounding" or "DSP sounding" than the typical narrow flat topped bandpass filter. The bandwidth of the FIR filter in cocoaFilter can be set to between 20 Hz and 300 Hz at the -10 dB points. Filter gain is also increased slightly as the filter becomes narrower.
If you program in C, I encourage you to take the Xcode project to experiment further (see below).
The Xcode project is available from the link in the download page.
The cocoaFilter sources can be used as a simple and compact platform for implementing other filters, or for implementing signal generators and modems that require sound card input and/or sound card output.
My primary aim of writing cocoaFilter is to investigate some ideas (e.g., an FIR filter that mimics a high-Q IIR filter, but with a lower filter skirt), but a secondary aim is to provide a project/framework so others can easily modify the code to do further experiments without having to bother with audio or graphics programming.
The existing IIR and FIR filters in cocoaFilter can be very easily modified to support other transfer functions.
The following shows the -filter method in the IIR filter. (cocoaFilter is written in Objective-C, but it should be easily understandable if you already know C). The filter in cocoaFilter accepts one floating point argument and returns one floating point output value:
The IIR filter in cocoaFilter is based on a second order variable Q bandpass filter,
The s-plane transfer function
H(s) is converted into a z-plane transfer function H(z)
using the bilinear transform and normalized to
the sampling period (the sampling rate is taken care of
by the application):
Whenever a user interface parameter such as center frequency or Q of the IIR filter changes, the application calls the -updateFilter method above. This recomputes the z-plane poles (a[i]) and zeros (b[i]) which are then used in the -filter method.
You can therefore alter the behavior of the default 2nd order IIR filter by just changing the -updateFilter method in IIR2.m. If you change it to a higher order filter, you would need to change the array allocation in the header file and modify both the -updateFilter and the -filter methods.
Notice that the spectral "tilt" is created by applying a homotopy between a pure bandpass (a symmetrical filter with a zero at z=0) filter and a lowpass filter (no zero at z=0, with a spectral peak at Fc when Q is high).
The -updateFilter method in the default FIR filter in cocoaFilter looks like this:
This FIR design is not phase linear (notice the exponential decay of FIR coefficients). It also has an extra zero placed at z=0. This mimics the general shape of a symmetrical IIR bandpass filter, but has a lower "skirt" than the IIR filter.
Transfer Function Plots
IIR2.m and FIR.m are subclasses of the Filter.m class.
In addition to -filter and -updateFilter methods of Filter.m, you can provide a method to supply the filter spectral transfer function for the application to draw the plot in the transfer function window. This is not mandatory, but can be quite useful as a visual aid.
For example, the transfer function for the default IIR filter is very simply defined (i.e., using z = jωT) as:
The application calls -frequencyResponse for each frequency it wants to plot. You supply the value and all the plotting is done for you automatically.
There is no restriction on how you can use the source code in the Xcode project. No GPL source is present in cocoaFilter and you are free to take pieces of the code or use cocoaFilter as the platform to build other filters, generators or modems, to build your own applications without having to republish your sources. I simply request that you pay it forward if you include a piece of cocoaFilter code into a GPL body of code by placing an exclusionary note that the cocoaFilter part is free of GPL, so other people can continue to use it freely in a similar manner that you had.