Filters - Quefumas/gensound GitHub Wiki
Filters are Transforms which modify the frequency content of a Signal.
The filters below are available under gensound.filters
.
Some of these filters rely on scipy
, and the ones that don't will run faster when it's available as well.
SimpleLPF(cutoff)
A simple low-pass filter, receiving the sole argument cutoff
, representing the cutoff frequency in Hz.
This filter gradually attenuates frequencies around the cutoff frequency and above it, with the attenuating growing rapidly for the higher frequencies. When carefully applied, this can make audio have a 'rounder' sound, but when overused can make it sound 'muddy' or 'boomy'.
from gensound import test_wav, WAV
from gensound.filters import SimpleLPF
w = WAV(test_wav)[10e3:30e3]
w *= SimpleLPF(1000)
w.play()
In the code snippet above, cutting off frequencies higher than 1kHz makes the music sounds very different. For example, the hi-hat on the drum kit is barely audible anymore.
SimpleHPF(cutoff)
A simple high-pass filter, also receiving the argument cutoff
, in Hz.
Here the cutoff frequency represents more or less the value for which lower frequencies should be attenuated (as opposed to the LPF, which attenuates frequencies higher than the cutoff frequency).
from gensound import test_wav, WAV
from gensound.filters import SimpleHPF
w = WAV(test_wav)[10e3:30e3]
w *= SimpleHPF(1000)
w.play()
In the code above, cutting off frequencies below 1kHz makes the sound 'airy', and makes the kick drum barely audible.
SimpleLowShelf(cutoff, gain, dB)
and SimpleHighShelf(cutoff, gain, dB)
Shelving filters are filters which uniformly raise/lower frequencies past a certain point (like a shelf), as opposed to low/high-pass filters, which try to remove some frequency ranges entirely. A low shelf typically increases the gain for frequencies below a given cutoff frequency by a certain amount, and a high shelf increases the gain for frequencies above the cutoff frequency.
Both these Transforms receive the same arguments:
cutoff
- cutoff frequency in Hz.gain
- gain applied to the 'shelf' amplitude, i.e., the factor by which the amplitudes in the relevant frequency bands will be multiplied. Positive values less than 1 will make the shelf softer, while values larger than 1 will make it louder. Exactly one of this or thedB
argument must be specified.dB
- gain applied, in dBs. Negative values make the shelf softer, positive values make it louder. Exactly one of this or thegain
argument must be specified.
from gensound.filters import SimpleHighShelf
w = WAV(test_wav)[10e3:30e3]
(w*SimpleHighShelf(1000, gain=4)).play()
This makes the higher frequencies louder, giving more 'air', while still preserving bass drum.
SimpleBandPass(lower, upper)
and SimpleBandStop(lower, upper)
Both these filters have an upper and a lower cutoff frequency. A bandpass filters removes all frequencies outside this range (that is, below the lower cutoff frequency and above the upper one), while a bandstop filter removes all frequencies within the range.
Both Transforms receive the following argument:
lower
- the lower cutoff frequency, in Hz.upper
- the upper cutoff frequency, in Hz.
SimpleNotch(lower, upper, gain, dB)
While bandpass and bandstop filters entirely remove all frequencies within or outside a certain range, a notch filter enables to increase or decrease the level of the frequencies within the range, without removing anything entirely.
This Transform receives the following arguments:
lower
- lower cutoff frequency (start of the affected range).upper
- upper cutoff frequency (end of the affected range).gain
- the gain to be applied to the frequencies in the specified range. Must specify either this ordB
.dB
- the gain to be applied, in decibels. Must specify either this orgain
.
MovingAverage(width)
A Moving Average filter, which works by simply averaging each sample with its neighbours. This is effectively a kind of low-pass filter.
It receives a single argument width
(integer), which is the number of samples averaged to yield each resulting sample. For example, if width=1
, then this will have no effect. If width=3
, then every sample of audio will be averaged with both of its neighbours.
The larger width
is, the more apparent the effect. But the larger it is, the more you have to increase it to make a noticeable difference in the resulting effect.
Also note that since width
expresses a number of samples, this means that the frequency response of this filter is also sensitive to sample rate chosen. The lower the sample rate, the stronger the effect.
ButterworthLowPass(cutoff, order)
and ButterworthHighPass(cutoff, order)
(Requires SciPy)
cutoff
- the cutoff frequency.order
- the order of the filter (integer, 1 or more). Higher orders will result in sharper reduction of frequency above/below the cutoff.
ButterworthBandPass(lower, upper, order)
and ButterworthBandStop(lower, upper, order)
(Requires SciPy)
lower
- lower cutoff frequency.upper
- upper cutoff freequency.order
- the order of the filter (integer, 1 or more). Higher orders will result in sharper reduction of frequency outside/inside the specified range.
IIR(feedforward, feedbackward)
The following sections are recommended for users with experience in digital signal processing.
If you are playing around with IIRs, you can use this Transform to specify the exact feedforward and feedback coefficients for the transfer function.
To do so, call IIR
with the two arguments:
feedforward
- expects a list/tuple of real values, which are the coefficients by which samples of the original signal ('x') are multiplied: the first coefficient will multiplyx[n]
, the secondx[n-1]
, etc.feedback
- expects a list/tuple of real values which are the coefficients of the previously output samples ('y'). For consistency, the first item (often considered redundant) is nevertheless the coefficient ofy[n]
, then followed byy[n-1]
, etc.feedback[0]
is typically 1; if not, Gensound will set it to 1 and scale all other feedforward/feedback coefficients by the given value.
IIR
to create new filters
Subclassing If, instead of directly supplying the numerical coefficients for the IIR, you wish to compute them on the fly from user-specified arguments, it's best to subclass IIR
, as in the template below:
class MyFilter(IIR):
def __init__(self, cutoff, Q, ...):
# overload __init__ to store the user-supplied parameters
self.cutoff = cutoff
self.Q = Q
...
def coefficients(self, sample_rate):
# overload this to compute two series of coefficients, given self.cutoff, etc., and sample_rate
feedforward = (..., ...)
feedback = (1, ...)
return (feedforward, feedback) # return a tuple of the two series
Visualising frequency response
This is still a WIP, expect changes
Subclasses of IIR
have the method plot_frequency_response
available. If you have matplotlib
installed, calling this will show an amplitude vs. frequency (log) graph showing the frequency response of the filter.
For example:
from gensound.filters import SimpleLowShelf
SimpleLowShelf(cutoff=1000, gain=3).plot_frequency_response()
Learn More
If you are unfamiliar with the concept of filters, here are some leads to get you going: EQ, Frequency Response.