Windowed-sinc filter (steep cut-off filter)

This plugin is a low-pass filter with a very steep high frequency cut-off.
Unlike the low-pass filter that is included with Audacity, it also maintains the phase of the input sound, which can help to reduce “blurring” of transients.

Controls:

  • Filter Type: [default “Low Pass”. Choice: Low Pass / High Pass / Both]
  • Low Pass Frequency (Hz): The cut-off frequency for the low pass filter [default 5000 Hz. 100 to 20000 Hz]
  • High Pass Frequency (Hz): The cut-off frequency for the high pass filter [default 1000 Hz. 100 to 20000 Hz]
  • Window size: The size of the windowing function (in samples). [default 512. Choices between 256 and 16384]
    Higher values will produce a steeper cut-off which can be particularly beneficial for lower frequency settings, but will also make the effect much slower.

For low sample rate tracks, the absolute maximum frequency is half the sample rate.

When both filter types are used, the effect will be either “band pass” or “band stop”.
Example 1:
Low Pass at 1000 Hz and High Pass at 5000 Hz will “stop” frequencies in the range between the two pass-band, thus 1000 Hz to 5000 Hz is stopped.

Example 2:
Low Pass at 5000 Hz and High Pass at 1000 Hz will “pass” only frequencies in the range between these two limits, thus 1000 Hz to 5000 Hz is passed.

Note: This effect will be very slow when using a large window size.

Tip: To produce a steep cut-off for long tracks, use “Tracks menu > Resample” to resample the track to twice the desired cut-off frequency, then (optionally) resample back to the original sample rate. This method uses the sync filter that is built into Audacity, which is much faster than this effect (though can only be used on whole tracks).

Tip: If a very low cut-off frequency is required (much below 100 Hz), the regular “Low Pass Filter” is likely to work better and quicker.


Installation instructions: Missing features - Audacity Support
When installed this effect will be listed as “Sinc Filter…”

Obsolete version:
win-sinc.ny (2.69 KB)
Latest version: sinc-filter.ny

Terrific. Now lets fix a documentation problem. Start Here:

http://manual.audacityteam.org/o/man/index_of_effects_generators_and_analyzers.html

…and go to Optional Plugins in one step. I got to the above link by following “Effects” from the main manual page. Nothing wrong with that. The only link I was able to find from there was an oblique trip down: “If you want to make your own plugin”.

No, actually. I want a good, clear link to the ones you already made.

Koz

You missed the bit highlighted right at the top of that page:

This page is a quick index to the Effects, Generators and Analyzers shipped with Audacity. You may also > add new plug-ins > in various popular formats.

That link takes you to:

Plug-ins

Audacity can be customized by the addition of plug-ins.

  • Nyquist: > A number of > Nyquist > plug-ins are already included with Audacity which you’ll see in the Audacity plug-ins folder with a file name ending in “.ny”. Nyquist is a dialect of LISP specially developed for audio processing. It can generate or process sound effects, or analyze audio content. You can > download > additional Nyquist plug-ins from us, or create new ones in any text editor.
  • Other plug-in formats: > > LADSPA > and > VST effects > are other types of plug-in which can be added to Audacity - see the > Audacity plug-ins page > for details. It’s also now possible to add > VAMP > plug-ins to Audacity – these are used to output descriptive information about the selected audio. Mac users can also add > Audio Unit > plug-ins. > LV2 > plug-ins can also be added and used in Audacity.

I guess that this effect is a bit “specialist”, so I’ve added an additional feature which is to have both a high pass and a low pass filter in this effect.

As that is not about this windowed-sync filter, it should really be a new topic.

Let’s start from here: does the effect work OK on Mac OS X?

Hi Steve

Here’s another version, that is slightly different in regard to the parameters.

  • uses the spectral selection
  • you’ll define the transition width (% of spectral selection)
  • ripples
  • gain in the stop band (how much to attenuate audio in this band)
  • bandpass, bandstop, lowpass, highpass.
  • Kaiser or sync window with variable parameters, i.e. you’ll get a wide vriety of different windows, depending on the “alpha” parameter.
    The filter order is calculated according to the specified transition width and ripple amount (max. 44099).
    Pressing debug shows those calculated values.
    SpectralEditFir.ny (6.1 KB)

Oooh lots of options :slight_smile:
Funnily enough, my first version had quite a few options, but I decided to strip it down to a minimalistic effect.

As it is using the spectral selection, I think it would be more intuitive to allow the spectral selection to determine the filter type (though “band pass” would require an option if that is to be included. Also, it errors if the spectral selection does not define both upper and lower bounds. Error message below:

error: bad argument type - NIL
Function: #<Subr-MIN: #a05b3cc>
Arguments:
  22050
  NIL
Function: #<FSubr-LET*: #a05b990>
Arguments:
  ((F0 (MAX 1 F0)) (F1 (MIN (/ SR 2) F1)) (FC (/ (+ F0 F1) 2)) (BW (- F1 F0)) (FROM% (IF (MEMBER TYPE (QUOTE (2 3))) 0.01 0.005)) (TW (* FROM% TRANSITION-WIDTH BW)))
  (DISPLAY "" F0 F1 FC TW BW)
  (CASE TYPE (0 (FIR SIG 2 RIPPLES FC TW BW)) (1 (DIFF SIG (FIR SIG 2 RIPPLES FC TW BW))) (2 (FIR SIG 0 RIPPLES (MIN (/ SR 2.1) (+ F0 (/ TW 8))) (* TW 0.875))) (3 (FIR SIG 1 RIPPLES (MAX 20 (- F1 (/ TW 8))) (* TW 0.875))))
Function: #<Closure-WET: #a1223f0>
Arguments:
  #<Sound: #b23b1450>
Function: #<FSubr-LET*: #a05b990>
Arguments:
  ((TN (TRUNCATE LEN)) (WET (WET SIG)) (TRANSITION (ROUND (MAX (* 0 SR) (* 0.1 TRANSITION)))) (T1 (MIN TRANSITION (/ TN 2))) (T2 (MAX (- TN TRANSITION) (/ TN 2))) (LEVEL (IF (<= CONTROL-GAIN -120) 1 (- 1 (DB-TO-LINEAR CONTROL-GAIN)))) (BREAKPOINTS (LIST 0 0 T1 LEVEL T2 LEVEL TN 0 TN)) (ENV (SND-PWL 0 SR BREAKPOINTS)))
  (DISPLAY "" T1 T2 LEVEL)
  (SUM (PROD ENV WET) (PROD (DIFF 1 ENV) SIG))
Function: #<Closure-RESULT: #a121c34>
Arguments:
  #<Sound: #b23b1450>
Function: #<Subr-APPLY: #a05c95c>
Arguments:
  #<Closure-RESULT: #a121c34>
  (#<Sound: #b23b1450>)
Function: #<FSubr-COND: #a05ba80>
Arguments:
  (LEN (SETF RESULT (MAKE-ARRAY LEN)) (DOTIMES (I LEN) (SETF (AREF RESULT I) (APPLY FN (MAPCAR (FUNCTION (LAMBDA (A) (COND ((ARRAYP A) (AREF A I)) (T A)))) ARGS)))) RESULT)
  (T (APPLY FN ARGS))
Function: #<FSubr-LET: #a05b9c0>
Arguments:
  (LEN NEWLEN RESULT)
  (DOLIST (A ARGS) (COND ((ARRAYP A) (SETF NEWLEN (LENGTH A)) (COND ((AND LEN (/= LEN NEWLEN)) (ERROR (FORMAT NIL "In ~A, two arguments are vectors of differing length." FN)))) (SETF LEN NEWLEN))))
  (COND (LEN (SETF RESULT (MAKE-ARRAY LEN)) (DOTIMES (I LEN) (SETF (AREF RESULT I) (APPLY FN (MAPCAR (FUNCTION (LAMBDA (A) (COND ((ARRAYP A) (AREF A I)) (T A)))) ARGS)))) RESULT) (T (APPLY FN ARGS)))
Function: #<Closure-MULTICHAN-EXPAND: #a0886fc>
Arguments:
  #<Closure-RESULT: #a121c34>
  #<Sound: #b23b1450>
Function: #<FSubr-CATCH: #a05b720>
Arguments:
  (QUOTE DEBUG-MESSAGE)
  (MULTICHAN-EXPAND (FUNCTION RESULT) *TRACK*)
Function: #<FSubr-IF: #a05b960>
Arguments:
  (= CONTROL-GAIN 0)
  "Gain is zero. Nothing to do."
  (CATCH (QUOTE DEBUG-MESSAGE) (MULTICHAN-EXPAND (FUNCTION RESULT) *TRACK*))
Function: #<FSubr-COND: #a05ba80>
Arguments:
  ((NOT (GET (QUOTE *TRACK*) (QUOTE VIEW))) (SETF P-ERR (FORMAT NIL "This effect requires a frequency selection in the~%~n                              'Spectrogram' or 'Spectrogram (log f)' track view.~%~%")) (CATCH (QUOTE DEBUG-MESSAGE) (MULTICHAN-EXPAND (FUNCTION RESULT) *TRACK*)))
  ((STRING-NOT-EQUAL (GET (QUOTE *TRACK*) (QUOTE VIEW)) "spectrogram" :END1 4 :END2 4) "Use this effect in the 'Spectrogram'nor 'Spectrogram (log f)' view.")
  (T (SETF P-ERR "") (IF (= CONTROL-GAIN 0) "Gain is zero. Nothing to do." (CATCH (QUOTE DEBUG-MESSAGE) (MULTICHAN-EXPAND (FUNCTION RESULT) *TRACK*))))
1>

The error checking is taken from the spectral tools of the next version. There have some alterations been made since, that I’ve not worked in yet.

Personally, I find it to be a bad decision to let the frequencies be undefined (instead of 0 Hz and Nyquist frequency).
The Spectral Edit Multi-tool has already your proposed low-/high-pass behaviour.
The approach is only “intuitively” if you don’t care about the transition width and the steepness of the filter, i.e. if it is constant.
My effect should in contrast control the transition with from pass to stop band and lower and upper frequency play both a important role in the definition of the shape.
There should actually also the filter types “Lowcut” and “Highcut” be listed as type choice–just the perfect counterpart to the other simple types.

As to the options, there’s only one control more than in your effect (3 with the frequency sliders discarded).
I’m not yet sure which window is “better”, the Kaiser or the Sinc (Lanczos), I guess the differences are marginal.
Therefore, this control could be left off.
The -70 dB ripple default (= about 0.04 % deviation from unity) seems acceptable.

For the application in the spectral environment, some parameters could be calculated more automatically (longer selections, lower order).

[/quote]

The main reason that I wrote this plugin was because I was reading this book online: The Scientist and Engineer's Guide to Digital Signal Processing's Table of Content and I find that I understand better by “doing” rather than just reading. In other words, it was an interesting exercise, with a result that may be useful to others. As a practical tool this would be very much faster by using Audacity’s Equalization effect code (in C++).

I don’t think that its too late to change that if we want to. Feel free to raise that as a new topic and make your case for how you think it should work.

If it is doing that, does it really need to have two “controls”? The spectral selection is, in effect, a “control” for setting the transition width, so I’m wondering, does it need the “Transition width” control in the GUI (it could be “always 100%”)?

Would they be aliases for High Pass and Low Pass, or would they be different in some way?


I wasn’t complaining :smiley: I was just commenting that I decided to take it down one road, and you took the other.

In my version, I originally had options to apply Hamming or Hann windows to the Sinc impulse, but took those options out because the practical difference was so small.
It may be educational to include more window choices.
Have you noticed any difference between the three (Kaiser, Lanczos, Blackman) windows that we currently have?

Quite so. However, controls can’t be greyed out, depending on another control (Something for Version 5?).
I would like to have all those spectral edit effects gathered in a separate menu, where they could be split up into the different types.
Currently, all effects have the “Spectral Edit” prefix to them. It would be rather cumbersome to find the right effect if they were individual; especially if one navigates by keyboard.
There is a wide variety of types:

  • lowpass
  • highpass
  • bandstop
  • bandpass
  • notch
  • comb (multiple notch)
  • allpass
  • Hilbert transform (90 degree shift)
  • band compressor
  • pitch quantization
  • formant modification (hat–>hut–>hood–>hit)
  • several non-linear types (salt&pepper, repair, edge detection)
  • voice/music/percussion separation
  • and so on

and most of those can be either IIR or FIR.

Imagine two identical tracks and we apply lp and hp respectively (with the same spectral selection).
The result is similar to a bandstop over the selection.
In contrast, applying lowpass and lowcut will result in the original audio.
That is, they form a complementary crossover pair.
Thus, you can play with the gain slider to adjust the tone balance (bass/treble).
It is rather complicated to achieve this with e.g. the Spectral Edit Multi tool. The user has to draw different selections or to invert the processed track, render both tracks into one and delete the original afterwards. :open_mouth:
Side-note: Those built-in spectral effects are not linear. And this can result in unwanted effects during the fading-periods (comb effect).
Alternatively, the FIR high/lowpass filter can take the (geom.) center of the selection as cut-off frequency, which will also result in a complementary pair.

The Kaiser Window is actually a compilation of different windows.
The similarity is given thru the beta parameter (also referred to as alpha/alpha*PI in other definitions)

Beta	window shape
0	Rectangular shape
5	Similar to the Hamming window
6	Similar to the Hann window
8.6	Similar to the Blackman window

You can steer the shape indirectly by the “Ripples” parameter, -86 dB comes nigh to beta=8.6.
The Lanczos is not very well documented/analysed in order to make such direct comparisons. However, it is an extraordinary resampling filter (for e.g. graphics).
What I’ve not done so far is to adjust the transition width/ripples if a gain value is set.
This would require that the original Kaiser parameter calculation has to be expanded somehow.


For your effect, different windows could quite easily be applied, according to the choice of taps (512, 1024, … 16384) by just providing different alpha values to the two cosine terms + offset.

In any case, the importance of the window fades away for very large impulse responses since the sinc function approaches zero and quantization noise meddles in a great deal.

That’s something that I am very much hoping for in version 5 :wink:

Something that has been talked about on many occasions is to allow users to customise their effect menu, so that they can group effects any way that they wish.
You may like to group all of your “spectral effects” together, whereas someone else might prefer to group all their “filter effects” together. If the menu is customisable then you can both be happy. I am very much in favour of being able to customise the Effect menu.

I like that idea. That would make a good effect all on its own - possibly called “Spectral Crossover Filter”? - where the crossover region (filter slope) is defined by the upper and lower frequencies of the spectral selection, and the crossover frequency defined by the centre line. The only required control would be to select High Pass or Low Pass. It could of course be used to split the audio into as many bands as the user wants.

Attached: Before, After, Settings, Clip.

Mac Mini. OS-X 10.9.5 (not Yosemite)
Audacity 2.0.6

Koz

Screen Shot 2015-02-24 at 21.01.37.png
Screen Shot 2015-02-24 at 21.01.11.png
Screen Shot 2015-02-24 at 21.00.00.png

Looks like a pretty effective 3kHz brick wall to me. Thanks for testing koz.

I love the idea of a linear phase highpass and lowpass filter. Great work!
But I’m wondering if it’s possible to implement a plugin that is basically the exact same as the standard highpass and lowpass filters, but using linear phase instead? Personally,I think this Sinc filter has too steep a cutoff, and I like the idea of adjustable rolloff. But I don’t like the idea of analog, non-linear phase filters. What would be a possible way to change the code of this Sinc filter so it uses rolloffs instead of windows sizes? Just curious.

You would need to calculate the correct filter kernel to create the response that you require. In this plug-in I’m only interested in creating a sinc filter, so the majority of the code in this plug-in is to generate the impulse response of the sinc filter. Your suggestion wouldn’t be a “modification”, it would be a rewrite - a different plug-in altogether.

An updated version that supports the “fast convolution” function in the latest version of Nyquist. The “fast convolution” function is not yet available in Audacity, but will hopefully be available in Audacity 2.4.0 next year. This version still supports Audacity 2.2.1 and later, but will be very much faster when Audacity’s Nyquist is updated.
win-sinc.ny (2.72 KB)

I’ve just noticed a bug!
The filter has positive gain. This means that it amplifies sound in the pass-band.

Fix to follow.

I think this fixes all of the bugs.

This version dispenses with the band-pass / pand-pass options so as to simplify the interface. For band-pass just apply the effect twice (once as low-pass and once as high pass). For band-stop, duplicate the track and use band-stop on one and band-pass on the other.
If there’s demand, I may make a band-pass / band-stop version.

Another variation that I’m considering is a “Spectral Delete” effect, which uses spectral selection.
sinc-filter.ny (2.84 KB)

The latest version is a dead link, and the obsolete version does NOT work on Audacity 3.3.3. Please help.