### Example filterbank usage Source: https://siggigue.github.io/pyfilterbank/_modules/gammatone.html Demonstrates how to initialize a Gammatone filterbank, analyze an impulse, and plot the results. ```python def example_filterbank(): from pylab import plt import numpy as np x = _create_impulse(2000) gfb = GammatoneFilterbank(density=1) analyse = gfb.analyze(x) imax, slopes = gfb.estimate_max_indices_and_slopes() fig, axs = plt.subplots(len(gfb.centerfrequencies), 1) for (band, state), imx, ax in zip(analyse, imax, axs): ax.plot(np.real(band)) ax.plot(np.imag(band)) ax.plot(np.abs(band)) ax.plot(imx, 0, 'o') ax.set_yticklabels([]) [ax.set_xticklabels([]) for ax in axs[:-1]] axs[0].set_title('Impulse responses of gammatone bands') fig, ax = plt.subplots() def plotfun(x, y): ax.semilogx(x, 20*np.log10(np.abs(y)**2)) plt.hold(True) gfb.freqz(nfft=2*4096, plotfun=plotfun) plt.grid(True) plt.title('Absolute spectra of gammatone bands.') plt.xlabel('Normalized Frequency (log)') plt.ylabel('Attenuation /dB(FS)') plt.axis('Tight') plt.ylim([-90, 1]) plt.xlim([0.001, 0.1]) # plt.show() return gfb ``` -------------------------------- ### Initialize CFFI interface Source: https://siggigue.github.io/pyfilterbank/_modules/sosfiltering.html Setup of the CFFI interface and loading of the shared library based on the operating system. ```python import os from sys import platform from platform import architecture import numpy as np from cffi import FFI from scipy.signal import lfilter ffi = FFI() ffi.cdef(""" void sosfilter(float*, int, float*, int, float*); void sosfilter_double(double*, int, double*, int, double*); void sosfilter_double_mimo(double*, int, int, double*, int, int, double*); """) if platform == 'win32' and architecture()[0] == '64bit': _dl = 'sosfilt64.dll' elif platform == 'win32' and architecture()[0] == '32bit': _dl = 'sosfilt32.dll' else: _dl = 'sosfilt.so' if __name__ != '__main__': _mylibpath = os.path.join('.', os.path.dirname(__file__)) else: _mylibpath = os.curdir _mylibpath = os.path.join(_mylibpath, _dl) _c = ffi.dlopen(_mylibpath) ``` -------------------------------- ### Visualize Gammatone Filter Examples Source: https://siggigue.github.io/pyfilterbank/_modules/gammatone.html Demonstrates usage of the gammatone filter and filterbank examples via plot directives. ```python import pyfilterbank.gammatone pyfilterbank.gammatone.example_filter() ``` ```python import pyfilterbank.gammatone pyfilterbank.gammatone.example_filterbank() ``` -------------------------------- ### Example plot function Source: https://siggigue.github.io/pyfilterbank/_modules/pyfilterbank/octbank.html Demonstrates how to initialize a FractionalOctaveFilterbank and use the freqz function to generate frequency response data. ```python def example_plot(): """Creates a plot with :func:`freqz` of the default :class:`FractionalOctaveFilterbank`. """ ofb = FractionalOctaveFilterbank() x, y, f, Y = freqz(ofb) ``` -------------------------------- ### Plotting an example filter bank Source: https://siggigue.github.io/pyfilterbank/_modules/pyfilterbank/octbank.html Visualizes the filter bank response using matplotlib. ```python from pylab import plt import octbank octbank.example_plot() plt.show() ``` -------------------------------- ### Visualize Mel Filter Bank Source: https://siggigue.github.io/pyfilterbank/_modules/melbank.html Example usage of compute_melmat to generate and plot a mel filter bank matrix. ```python from pylab import plt import melbank f1, f2 = 1000, 8000 melmat, (melfreq, fftfreq) = melbank.compute_melmat(6, f1, f2, num_fft_bands=4097) fig, ax = plt.subplots(figsize=(8, 3)) ax.plot(fftfreq, melmat.T) ax.grid(True) ax.set_ylabel('Weight') ax.set_xlabel('Frequency / Hz') ax.set_xlim((f1, f2)) ax2 = ax.twiny() ax2.xaxis.set_ticks_position('top') ax2.set_xlim((f1, f2)) ax2.xaxis.set_ticks(melbank.mel_to_hertz(melfreq)) ax2.xaxis.set_ticklabels(['{:.0f}'.format(mf) for mf in melfreq]) ax2.set_xlabel('Frequency / mel') plt.tight_layout() fig, ax = plt.subplots() ax.matshow(melmat) plt.axis('equal') plt.axis('tight') plt.title('Mel Matrix') plt.tight_layout() ``` -------------------------------- ### Get frequency response Source: https://siggigue.github.io/pyfilterbank/_modules/gammatone.html Returns frequency and impulse responses, supporting custom plotting functions. ```python def freqz(self, nfft=4096, plotfun=None): """Returns frequency and impulse responses. Accepts `plotfun` function for cusomized plotting. """ def gen_freqz(): for b, a in self._coeffs: yield freqz_fos(b, a, self.order, nfft, plotfun) return list(gen_freqz()) ``` -------------------------------- ### Initialize delay estimation Source: https://siggigue.github.io/pyfilterbank/_modules/gammatone.html Sets up delay variables and memory buffers to optimize the impulse response. ```python def init_delay(self, desired_delay_sec): """Initializes delay estimation and variables for delay bands to achieve a optimized impulse response. """ self.desired_delay_sec = desired_delay_sec self.desired_delay_samples = int(self.samplerate*desired_delay_sec) self.max_indices, self.slopes = self.estimate_max_indices_and_slopes( delay_samples=self.desired_delay_samples) self.delay_samples = self.desired_delay_samples - self.max_indices self.delay_memory = np.zeros((len(self.centerfrequencies), np.max(self.delay_samples))) ``` -------------------------------- ### Initialize ThirdOctFFTLevel class Source: https://siggigue.github.io/pyfilterbank/_modules/pyfilterbank/octbank.html Sets up the frequency bands and FFT mapping matrix for third-octave level estimation. ```python class ThirdOctFFTLevel: """Third octave levels by fft. TODO: rename variables TODO: Write Documentation """ def __init__(self, fmin=30, fmax=17000, nfft=16384, fs=44100, flag_mean=False): self.nfft = nfft self.fs = fs # following should go into some functions: kmin = 11 + int(10*np.log10(fmin)) kmax = 11 + int(10*np.log10(fmax)) f_terz = standardized_nominal_frequencies[kmin:kmax] n = int(1 + kmax - kmin) halfbw = 2**(1.0/6) df = fs/nfft idx_lower = np.zeros(n) idx_lower[0] = 10 + np.round((standardized_nominal_frequencies[kmin]/halfbw)/df) idx_upper = 10 + np.round(halfbw*standardized_nominal_frequencies[kmin:kmax]/df) idx_lower[1:n] = idx_upper[0:n-1] + 1 upperedge = halfbw *standardized_nominal_frequencies[kmax] print(idx_upper[0]-idx_lower[0]) #if idx_upper(1) - idx_lower(1) < 4: # raise ValueError('Too few FFT lines per frequency band') M = np.zeros((n, nfft/2+1)) for cc in range(n-1): kk = range(int(idx_lower[cc]), int(idx_upper[cc])) if not flag_mean: M[cc, kk] = 1.0 else: M[cc, kk] = 1.0 / len(kk) self.M = M self.f_terz = f_terz ``` -------------------------------- ### Initialize and Apply Fractional Octave Filter Bank Source: https://siggigue.github.io/pyfilterbank/octbank.html Demonstrates creating a filter bank object, processing a random noise signal, and plotting the resulting band levels. ```python >>> from pyfilterbank import FractionalOctaveFilterbank >>> from pylab import plt, np >>> >>> sample_rate = 44100 >>> ofb = FractionalOctaveFilterbank(sample_rate, order=4) >>> >>> x = np.random.randn(4*sample_rate) >>> y, states = ofb.filter(x) >>> L = 10 * np.log10(np.sum(y*y,axis=0)) >>> plt.plot(L) ``` -------------------------------- ### example_plot() Source: https://siggigue.github.io/pyfilterbank/_modules/pyfilterbank/octbank.html Creates a plot illustrating the frequency response of the default FractionalOctaveFilterbank. ```APIDOC ## Function: example_plot() ### Description Creates a plot using `freqz` for the default `FractionalOctaveFilterbank` instance. This is a utility function for visualizing filter characteristics. ``` -------------------------------- ### Execute Plotting Script Source: https://siggigue.github.io/pyfilterbank/_modules/splweighting.html Entry point to generate and display the weighting plots. ```python if __name__ == '__main__': fig, ax = plot_weightings() fig.show() ``` -------------------------------- ### Initialize band gains Source: https://siggigue.github.io/pyfilterbank/_modules/gammatone.html Initializes gains for weighting bands to achieve an equalized frequency response during synthesis. ```python def init_gains(self): """Initializes gains for weighting bands leading to a equalized freqresponse when summing (synthesizing) bands. """ self.gains = np.ones(len(self.centerfrequencies)) # not correct until now: # x, s = list(zip(*self.analyze(_create_impulse(self.samplerate/10)))) # rss = [np.sqrt(np.sum(np.real(b)**2)) for b in x] # self.gains = 1/np.array(rss) ``` -------------------------------- ### Design and Test Gammatone Filter Source: https://siggigue.github.io/pyfilterbank/_modules/gammatone.html Demonstrates designing a 4th-order gammatone filter and plotting its impulse response using pylab. ```python def example_filter(): from pylab import plt, np sample_rate = 44100 order = 4 b, a = design_filter( sample_rate=sample_rate, order=order, centerfrequency=1000.0, attenuation_half_bandwidth_db=-3, band_width_factor=1.0) x = _create_impulse(1000) y, states = fosfilter(b, a, order, x) y = y[:800] plt.plot(np.real(y), label='Re(z)') plt.plot(np.imag(y), label='Im(z)') plt.plot(np.abs(y), label='|z|') plt.legend() # plt.show() return y, b, a if __name__ == '__main__': from pylab import plt gfb = example_filterbank() y = example_filter() plt.show() ``` -------------------------------- ### OctBank Class Initialization Source: https://siggigue.github.io/pyfilterbank/_modules/pyfilterbank/octbank.html The constructor sets up the filter bank parameters and initializes the filter structure. ```python def __init__(self, sample_rate=44100, order=4, nth_oct=3.0, norm_freq=1000.0, start_band=-19, end_band=13, edge_correction_percent=0.01, filterfun='cffi'): self._sample_rate = sample_rate self._order = order self._nth_oct = nth_oct self._norm_freq = norm_freq self._start_band = start_band self._end_band = end_band self._edge_correction_percent = edge_correction_percent self._initialize_filter_bank() self.set_filterfun(filterfun) ``` -------------------------------- ### Filter method implementation Source: https://siggigue.github.io/pyfilterbank/_modules/pyfilterbank/octbank.html Calculates the filter output using rfft and a dot product with the filter matrix M. ```python def filter(self, x): X = rfft(x, self.nfft/2+1) return 20*np.log10(np.dot(self.M, np.abs(X))) ``` -------------------------------- ### Apply delay to bands Source: https://siggigue.github.io/pyfilterbank/_modules/gammatone.html Returns delayed bands for an optimized impulse response at synthesis. ```python def delay(self, bands): """Returns delayed bands for an optimized impulseresponse at synthesis. """ self.phase_factors = np.abs(self.slopes)*1j / self.slopes for i, band in enumerate(bands): phase_factor = self.phase_factors[i] delay_samples = self.delay_samples[i] if delay_samples == 0: yield np.real(band) * phase_factor else: yield np.concatenate( (self.delay_memory[i, :delay_samples], np.real(band[:-delay_samples])), axis=0) self.delay_memory[i, :delay_samples] = np.real( band[-delay_samples:]) ``` -------------------------------- ### Compiling the C source for SOS filtering Source: https://siggigue.github.io/pyfilterbank/sosfiltering.html Commands to compile the C source code into a shared library for use with Python CFFI on Linux or Windows. ```bash $ gcc -c -std=c99 -O3 sosfilter.c $ gcc -shared -o sosfilter.so sosfilter.o $ or the last line for windows users: $ gcc -shared -o sosfilter.dll sosfilter.o ``` -------------------------------- ### Calculate Gammatone Filter Coefficients Source: https://siggigue.github.io/pyfilterbank/_modules/gammatone.html Calculates filter coefficients based on bandwidth and attenuation parameters. ```python else: raise ValueError( 'You need to specify either `band_width` or `band_width_factor!`') alpha = 10**(0.1 * attenuation_half_bandwidth_db / order) p = (-2 + 2 * alpha * cos(phi)) / (1 - alpha) lambda_ = -p/2 - sqrt(p*p/4 - 1) beta = 2*pi * centerfrequency / sample_rate coef = lambda_ * exp(1j*beta) factor = 2 * (1 - abs(coef))**order b, a = array([factor]), array([1., -coef]) return b, a ``` -------------------------------- ### Synthesize signal from bands Source: https://siggigue.github.io/pyfilterbank/_modules/gammatone.html Returns the summed, delayed, and weighted signal bands. ```python def synthesize(self, bands): """Returns summed dleayed and weighted bands. """ return np.array(list(self.delay( [b*g for b, g in zip(bands, self.gains)]))).sum(axis=0) ``` -------------------------------- ### Plotting Weighting Filter Responses Source: https://siggigue.github.io/pyfilterbank/_modules/splweighting.html Visualize the frequency response of the implemented weighting filters. ```python import splweighting fig, ax = splweighting.plot_weightings() fig.show() ``` -------------------------------- ### FractionalOctaveFilterbank Source: https://siggigue.github.io/pyfilterbank/octbank.html Constructor for creating a fractional octave filter bank object. ```APIDOC ## class FractionalOctaveFilterbank(sample_rate=44100, order=4, nth_oct=3.0, norm_freq=1000.0, start_band=-19, end_band=13, edge_correction_percent=0.01, filterfun='cffi') ### Description Initializes a fractional octave filter bank with second-order section Butterworth band passes. ### Parameters - **sample_rate** (int) - Sampling rate of the signals to be filtered. - **order** (int) - Filter order of the bands (must be even). - **nth_oct** (scalar) - Number of bands per octave. - **norm_freq** (scalar) - Reference frequency for all fractional octaves. - **start_band** (int) - First band number below norm_freq. - **end_band** (int) - Last band number above norm_freq. - **edge_correction_percent** (scalar) - Percentage of widening or narrowing the bands. - **filterfun** ({'cffi', 'py', 'cprototype'}) - Function used by the filter() method. ``` -------------------------------- ### Python Prototype for MIMO SOS Filter Source: https://siggigue.github.io/pyfilterbank/_modules/sosfiltering.html A pure Python implementation of the MIMO IIR DF-II biquad filter structure for prototyping. ```python [docs]def sosfilter_mimo_cprototype_py(signal_in, sos_in, states_in=None): """Prototype for the mimo c-filter function. Implements a IIR DF-II biquad filter strucure. But with multiple input und multiple bands.""" signal = signal_in.copy().flatten('F') shape_signal = signal_in.shape print(len(signal)) nframes = int(signal_in.shape[0]) print(nframes) nchan = int(signal_in.shape[2]) print(nchan) sos = np.tile(sos_in.copy().flatten('F'), (nchan)) ksos = int(sos_in.shape[0]/6) print(ksos) kbands = int(sos_in.shape[1]) print(kbands) if not states_in: states = np.zeros(nchan*ksos*kbands*2) else: states = states_in ii = 0 for c in range(nchan): for b in range(kbands): for k in range(ksos): w1 = states[c*ksos*kbands*2 + b*ksos*2 + k*2] w2 = states[c*ksos*kbands*2 + b*ksos*2 + k*2 + 1] b0 = sos[ii] ii += 1 b1 = sos[ii] ii += 1 b2 = sos[ii] ii += 1 a0 = sos[ii] ii += 1 a1 = sos[ii] ii += 1 a2 = sos[ii] ii += 1 for n in range(nframes): w0 = signal[c*nframes*kbands + b*nframes + n] w0 = w0 - a1*w1 - a2*w2 yn = b0*w0 + b1*w1 + b2*w2 w2 = w1 w1 = w0 signal[c*nframes*kbands + b*nframes + n] = yn ``` -------------------------------- ### Applying Weighting Filters to Signals Source: https://siggigue.github.io/pyfilterbank/_modules/splweighting.html Use the weight_signal function to apply A, B, or C weighting to an input signal. ```python def weight_signal(data, sample_rate=44100, weighting='A'): """Returns filtered signal with a weighting filter. Parameters ---------- data : ndarray Input signal to be filtered. sample_rate : int Sample rate of the signal. weighting : {'A', 'B', 'C'} Specify the weighting function by a string. Returns ------- outdata : ndarray Filtered output signal. The output will be weighted by the specified filter function. """ b, a = _weighting_coeff_design_funsd[weighting](sample_rate) return lfilter(b, a, x) ``` -------------------------------- ### Calculating fractional octave frequencies Source: https://siggigue.github.io/pyfilterbank/_modules/pyfilterbank/octbank.html Computes center and band edge frequencies for fractional octave bands. ```python def frequencies_fractional_octaves(start_band, end_band, norm_freq, nth_oct): """Return center and band edge frequencies of fractional octaves. Parameters ---------- start_band : int The starting center frequency at `norm_freq`*2^(`start_band`/`nth_oct`). end_band : int The last center frequency at `norm_freq`*2^(`end_band`/`nth_oct`). norm_freq : scalar The center frequency of the band number 0. nth_oct : scalar The distance between the center frequencies. For third octaves `nth_oct=3`. Returns ------- center_frequencies : ndarray Frequencies spaced in `nth_oct` from `start_band` to `end_band` with the `norm_freq` at band number 0. band_edges : ndarray Edge frequencies (-3 dB points) of the fractional octave bands. With constant relative Bandwidth. """ k = arange(start_band-1, end_band+2) frequencies = norm_freq * 2.0**(k/nth_oct) band_edges = sqrt(frequencies[:-1] * frequencies[1:]) center_frequencies = frequencies[1:-1] return center_frequencies, band_edges ``` -------------------------------- ### Design band-pass filter matrix Source: https://siggigue.github.io/pyfilterbank/_modules/pyfilterbank/octbank.html Generates a matrix of second-order section coefficients for band-pass filters based on specified order and band edges. ```python def design_sosmat_band_passes(order, band_edges, sample_rate, edge_correction_percent=0.0): """Return matrix containig sos coeffs of bandpasses. Parameters ---------- order : int Order of the band pass filters. band_edges : ndarray Band edge frequencies for the bandpasses. sample_rate : scalar Sample frequency. edge_correction_percent : scalar Percentage for the correction of the bandedges. Float between -100 % and 100 %. It can be helpfull dependent on the used filter order. p > 0 widens the band passes. Returns ------- sosmat : ndarray Second order section coefficients. Each column is one band pass cascade of coefficients. """ num_coeffs_biquad_bandpass = 6 num_coeffs_cascade = order * num_coeffs_biquad_bandpass num_bands = len(band_edges) - 1 sosmat = zeros((num_coeffs_cascade, num_bands)) band_edges_normalized = to_normalized_frequencies(band_edges, sample_rate) p_lower = (1 - edge_correction_percent*1e-2) p_upper = (1 + edge_correction_percent*1e-2) for i, (lower_freq, upper_freq) in enumerate(zip( band_edges_normalized[:-1], band_edges_normalized[1:])): sos = butter_sos('bandpass', order, p_lower*lower_freq, p_upper*upper_freq) sosmat[:, i] = sos.flatten() return sosmat ``` -------------------------------- ### Generate Gammatone Bank Frequencies Source: https://siggigue.github.io/pyfilterbank/_modules/gammatone.html Calculates center frequencies and auditory bandwidths for a range of filters. ```python def frequencies_gammatone_bank(start_band, end_band, norm_freq, density): norm_erb = hertz_to_erbscale(norm_freq) centerfrequencies = erbscale_to_hertz( arange(start_band, end_band, density) + norm_erb) return centerfrequencies ``` -------------------------------- ### Bilinear Transformation for SOS Source: https://siggigue.github.io/pyfilterbank/_modules/sosfiltering.html Performs bilinear transformation of analog filter weights to digital weights in cascade form. ```python def bilinear_sos(d, c): """Bilinear transformation of analog weights to digital weights. >>>>>>> 8d01abb1e1f252834c0666d50c645dd3d35a1f52 Bilinear transformation of analog weights to digital weights. Weights of IIR digital filter in cascade form with 2-pole sections; H(z)=H(z,1)H(z,2)...H(z,L/2) where L is the number of poles and each section is a ratio of quadratics. Parameters ---------- d : ndarray Numerator weights of analog filter in 1-pole sections. d is dimensioned (L/2 x 2). c : ndarray Denominator weights, dimensioned same as d. Returns ------- b : ndarray Digital numerator weights, dimensioned (L/2 x 3). a : ndarray Digital denominator weights, dimensioned the same. """ L2, ncd = d.shape nr, ncc = c.shape # Check for errors. if(nr != L2 or ncd != 2 or ncc != 2): raise Exception('Inputs d and c must both be L/2 x 2 arrays.') # Bilinear transformation of H(s) to H(z) using z and p vectors. a = np.zeros((L2, 3), dtype=np.double) a[:, 0] = np.abs(c[:, 0] + c[:, 1])**2 if np.min(a[:, 0]) == 0: raise Exception('"c" should not have a row of zeros.') a[:, 1] = 2*np.real((c[:, 0] + c[:, 1]) * np.conj(c[:, 1] - c[:, 0])) a[:, 2] = np.abs(c[:, 1] - c[:, 0])**2 b = np.zeros((L2, 3), dtype=np.double) b[:, 0] = np.abs(d[:, 0] + d[:, 1])**2 b[:, 1] = 2*np.real((d[:, 0] + d[:, 1]) * np.conj(d[:, 1] - d[:, 0])) b[:, 2] = np.abs(d[:, 1] - d[:, 0])**2 # Scale H(z) so a(:,1)=1: sa = np.kron(np.ones((3, 1)), a[:, 0]).T a = a / sa b = b / sa return b, a ``` -------------------------------- ### splweighting.weight_signal(data, sample_rate=44100, weighting='A') Source: https://siggigue.github.io/pyfilterbank/splweighting.html Applies a specified weighting filter to an input signal. ```APIDOC ## splweighting.weight_signal(data, sample_rate=44100, weighting='A') ### Description Returns a filtered signal using the specified weighting filter. ### Parameters - **data** (ndarray) - Required - Input signal to be filtered. - **sample_rate** (int) - Optional - Sample rate of the signal (default: 44100). - **weighting** (string) - Optional - Specify the weighting function: 'A', 'B', or 'C' (default: 'A'). ### Returns - **outdata** (ndarray) - Filtered output signal. ``` -------------------------------- ### Calculate Frequency Response of FOS Source: https://siggigue.github.io/pyfilterbank/_modules/gammatone.html Computes the frequency and impulse response for first-order section coefficients. ```python [docs]def freqz_fos(b, a, order, nfft, plotfun=None): """Returns Frequency Response and impulse response of first order section coeffs. Parameters ---------- b : arraylike a : arraylike order : int nfft : int plotfun : function(frequencies, response) Returns ------- freqresponse : arraylike frequencies : arraylike response : arraylike """ impulse = _create_impulse(nfft) response, states = fosfilter(b, a, order, impulse) freqresponse = rfft(np.real(response)) frequencies = rfftfreq(nfft) if plotfun: plotfun(frequencies, freqresponse) return freqresponse, frequencies, response ``` -------------------------------- ### Apply Weighting Filter to Signal Source: https://siggigue.github.io/pyfilterbank/splweighting.html Use scipy.signal.lfilter to apply the generated filter coefficients to an input signal. ```python >>> from scipy.signal import lfilter >>> y = lfilter(b, a, x) ``` -------------------------------- ### Design A-Weighting Filter Coefficients Source: https://siggigue.github.io/pyfilterbank/splweighting.html Generate filter coefficients for A-weighting based on the provided sample rate. ```python >>> b, a = a_weighting_coeff_design(sample_rate) ``` -------------------------------- ### Calculate ERB Properties Source: https://siggigue.github.io/pyfilterbank/_modules/gammatone.html Functions to calculate ERB counts, bandwidths, and frequency conversions. ```python def erb_count(centerfrequency): return 21.4 * log10(4.37 * 0.001 * centerfrequency + 1) ``` ```python def erb_aud(centerfrequency): return _ERB_L + centerfrequency / _ERB_Q ``` ```python def hertz_to_erbscale(frequency): return _ERB_Q * np.log(1 + frequency / (_ERB_L * _ERB_Q)) ``` ```python def erbscale_to_hertz(erb): return (exp(erb/_ERB_Q) - 1) * _ERB_L * _ERB_Q ``` -------------------------------- ### Design C-Weighting Filter Coefficients Source: https://siggigue.github.io/pyfilterbank/splweighting.html Generate filter coefficients for C-weighting based on the provided sample rate. ```python b, a = c_weighting_coeffs_design(sample_rate) To Filter a signal use scipy lfilter: from scipy.signal import lfilter y = lfilter(b, a, x) ``` -------------------------------- ### Compute Mel Transformation Matrix Source: https://siggigue.github.io/pyfilterbank/_modules/melbank.html Generates a transformation matrix to convert FFT spectra to mel spectra. ```python def compute_melmat(num_mel_bands=12, freq_min=64, freq_max=8000, num_fft_bands=513, sample_rate=16000): """Returns tranformation matrix for mel spectrum. Parameters ---------- num_mel_bands : int Number of mel bands. Number of rows in melmat. Default: 24 freq_min : scalar Minimum frequency for the first band. Default: 64 freq_max : scalar Maximum frequency for the last band. Default: 8000 num_fft_bands : int Number of fft-frequenc bands. This ist NFFT/2+1 ! number of columns in melmat. Default: 513 (this means NFFT=1024) sample_rate : scalar Sample rate for the signals that will be used. Default: 44100 Returns ------- melmat : ndarray Transformation matrix for the mel spectrum. Use this with fft spectra of num_fft_bands_bands length and multiply the spectrum with the melmat this will tranform your fft-spectrum to a mel-spectrum. frequencies : tuple (ndarray , ndarray ) Center frequencies of the mel bands, center frequencies of fft spectrum. """ center_frequencies_mel, lower_edges_mel, upper_edges_mel = \ melfrequencies_mel_filterbank( num_mel_bands, freq_min, freq_max, num_fft_bands ) len_fft = float(num_fft_bands) / sample_rate center_frequencies_hz = mel_to_hertz(center_frequencies_mel) lower_edges_hz = mel_to_hertz(lower_edges_mel) upper_edges_hz = mel_to_hertz(upper_edges_mel) freqs = linspace(0.0, sample_rate/2.0, num_fft_bands) melmat = zeros((num_mel_bands, num_fft_bands)) for imelband, (center, lower, upper) in enumerate(zip( center_frequencies_hz, lower_edges_hz, upper_edges_hz)): left_slope = (freqs >= lower) == (freqs <= center) melmat[imelband, left_slope] = ( (freqs[left_slope] - lower) / (center - lower) ) right_slope = (freqs >= center) == (freqs <= upper) melmat[imelband, right_slope] = ( (upper - freqs[right_slope]) / (upper - center) ) return melmat, (center_frequencies_mel, freqs) ``` -------------------------------- ### Design Gammatone Filter Source: https://siggigue.github.io/pyfilterbank/_modules/gammatone.html Returns filter coefficients for a gammatone filter based on Hohmann (2002). ```python def design_filter( sample_rate=44100, order=4, centerfrequency=1000.0, band_width=None, band_width_factor=1.0, attenuation_half_bandwidth_db=-3): if band_width: phi = pi * band_width / sample_rate elif band_width_factor: erb_audiological = band_width_factor * erb_aud(centerfrequency) phi = pi * erb_audiological / sample_rate ``` -------------------------------- ### splweighting.c_weighting_coeffs_design(sample_rate) Source: https://siggigue.github.io/pyfilterbank/splweighting.html Returns the b and a coefficients for a C-weighting filter based on the provided sample rate. ```APIDOC ## splweighting.c_weighting_coeffs_design(sample_rate) ### Description Returns b and a coefficients of a C-weighting filter. ### Parameters - **sample_rate** (scalar) - Required - Sample rate of the signals that will be filtered. ### Returns - **b, a** (ndarray) - Filter coefficients for a digital weighting filter. ``` -------------------------------- ### frequencies_fractional_octaves Source: https://siggigue.github.io/pyfilterbank/octbank.html Calculates center and band edge frequencies for fractional octave bands. ```APIDOC ## frequencies_fractional_octaves(start_band, end_band, norm_freq, nth_oct) ### Description Returns center and band edge frequencies of fractional octaves based on the provided band range and reference frequency. ### Parameters - **start_band** (int) - Required - The starting center frequency index. - **end_band** (int) - Required - The last center frequency index. - **norm_freq** (scalar) - Required - The center frequency of the band number 0. - **nth_oct** (scalar) - Required - The distance between the center frequencies (e.g., 3 for third octaves). ### Returns - **center_frequencies** (ndarray) - Frequencies spaced in nth_oct from start_band to end_band. - **band_edges** (ndarray) - Edge frequencies (-3 dB points) of the fractional octave bands. ``` -------------------------------- ### SOS Filter C-style Prototype Source: https://siggigue.github.io/pyfilterbank/_modules/sosfiltering.html Implements an IIR DF-II biquad filter structure as a Python prototype. ```python def sosfilter_cprototype_py(signal, sos, states): """Prototype for second order section filtering c function. Implements a IIR DF-II biquad filter strucure. """ N = int(len(signal)) K = int(sos.size/6) if isinstance(states, type(None)): states = np.zeros(K*2).astype(np.double) signal = signal.copy() # only python specific sos = sos.copy().flatten() yn = 0.0 # buffer for output w0 = 0.0 # signal states for k in range(K): # get coefficients of current biquad w1 = states[k*2] w2 = states[k*2+1] b0 = sos[k*6] b1 = sos[k*6+1] b2 = sos[k*6+2] a0 = sos[k*6+3] a1 = sos[k*6+4] a2 = sos[k*6+5] for n in range(N): # get a sample w0 = signal[n].copy() # recursive path w0 = w0 - a1*w1 - a2*w2 # transversal path yn = b0*w0 + b1*w1 + b2*w2 # delays w2 = w1 w1 = w0 # write output signal signal[n] = yn states[k*2] = w1 states[k*2+1] = w2 return signal, states ``` -------------------------------- ### splweighting.b_weighting_coeffs_design(sample_rate) Source: https://siggigue.github.io/pyfilterbank/splweighting.html Returns the b and a coefficients for a B-weighting filter based on the provided sample rate. ```APIDOC ## splweighting.b_weighting_coeffs_design(sample_rate) ### Description Returns b and a coefficients of a B-weighting filter. Note: B-Weighting is no longer described in DIN61672. ### Parameters - **sample_rate** (scalar) - Required - Sample rate of the signals that will be filtered. ### Returns - **b, a** (ndarray) - Filter coefficients for a digital weighting filter. ``` -------------------------------- ### filter(self, x, ffilt=False, states=None) Source: https://siggigue.github.io/pyfilterbank/_modules/pyfilterbank/octbank.html Filters an input signal using the settings of the filterbank object. ```APIDOC ## filter(self, x, ffilt=False, states=None) ### Description Filters the input signal by the settings of the filterbank object. ### Parameters - **x** (ndarray) - Required - Input signal (Nx0). - **ffilt** (bool) - Optional - Forward and backward filtering if True. - **states** (dict) - Optional - States of all filter sections in the filterbank. Initial state can be None. ### Returns - **y** (ndarray) - Fractional octave signals of the filtered input x. - **states** (dict) - Dictionary containing all filter section states. ``` -------------------------------- ### GammatoneFilterbank Class Source: https://siggigue.github.io/pyfilterbank/gammatone.html A class for initializing and managing a Gammatone filterbank for signal processing tasks. ```APIDOC ## class GammatoneFilterbank(samplerate=44100, order=4, startband=-12, endband=12, normfreq=1000.0, density=1.0, bandwidth_factor=1.0, desired_delay_sec=0.02) ### Description Initializes a GammatoneFilterbank instance for filtering signals. ### Parameters - **samplerate** (scalar) - Default: 44100 - **order** (scalar) - Default: 4 - **startband** (scalar) - Default: -12 - **endband** (scalar) - Default: 12 - **normfreq** (scalar) - Default: 1000.0 - **density** (scalar) - Default: 1.0 - **bandwidth_factor** (scalar) - Default: 1.0 - **desired_delay_sec** (scalar) - Default: 0.02 ``` -------------------------------- ### splweighting.plot_weightings() Source: https://siggigue.github.io/pyfilterbank/splweighting.html Plots all weighting functions defined in the splweighting module. ```APIDOC ## splweighting.plot_weightings() ### Description Plots all weighting functions defined in the module. ``` -------------------------------- ### Frequency Response Plotting Source: https://siggigue.github.io/pyfilterbank/_modules/sosfiltering.html Plots the frequency response of an SOS matrix. ```python def freqz(sosmat, nsamples=44100, sample_rate=44100, plot=True): """Plots Frequency response of sosmat.""" from pylab import np, plt, fft, fftfreq x = np.zeros(nsamples) x[nsamples/2] = 0.999 y, states = sosfilter_double_c(x, sosmat) Y = fft(y) f = fftfreq(len(x), 1.0/sample_rate) if plot: plt.grid(True) plt.axis([0, sample_rate / 2, -100, 5]) L = 20*np.log10(np.abs(Y[:len(x)/2]) + 1e-17) plt.semilogx(f[:len(x)/2], L, lw=0.5) plt.hold(True) plt.title(u'freqz sos filter') plt.xlabel('Frequency / Hz') plt.ylabel(u'Damping /dB(FS)') plt.xlim((10, sample_rate/2)) plt.hold(False) return x, y, f, Y ``` -------------------------------- ### Multi-Channel C-accelerated SOS Filter Source: https://siggigue.github.io/pyfilterbank/_modules/sosfiltering.html Handles multi-channel input signals for second-order section filtering using CFFI. ```python [docs]def sosfilter_double_mimo_c(signal, sos, states=None): """Second order section filter function for multi channel input using cffi, double precision signal_out, states = sosfilter_c(signal_in, sos, states=None) Parameters ---------- signal : ndarray Signal array of shape (N x C). sos : ndarray Second order section filter coefficients (K*6 x B x C) np-array. states : ndarray Filter states, initial can be None. Otherwise shape is (K*2 x B x C) Returns ------- signal : ndarray Filtered signal of shape (N x B x C). Where N is the number of samples, B is th number of filter bands and C is the number of signal channels. states : ndarray Filter states of shape (K*2 x B x C). """ shape_signal = signal.shape nframes = int(shape_signal[0]) if len(shape_signal) > 1: nchan = int(shape_signal[1]) else: nchan = int(1) shape_sos = sos.shape ksos = int(shape_sos[0]/6) if len(shape_sos) > 1: kbands = int(shape_sos[1]) if len(shape_sos) == 2 and nchan > 1: sos = np.tile(sos.flatten('F'), (nchan)) else: kbands = int(1) if isinstance(states, type(None)): states = np.zeros(nchan*kbands*ksos*2).astype(np.double) states_c = ffi.new( 'char[]', np.array(states, dtype=np.double).flatten('F').tostring()) sos_c = ffi.new( 'char[]', np.array(sos, dtype=np.double).flatten('F').tostring()) if nchan > 1: signal = np.tile(signal, (kbands, 1)) else: signal = np.tile(signal, (kbands)) shape_signal = signal.shape signal_c = ffi.new( 'char[]', np.array(signal, dtype=np.double).T.flatten().tostring()) _c.sosfilter_double_mimo( ffi.cast("double*", signal_c), nframes, nchan, ffi.cast("double*", sos_c), ksos, kbands, ffi.cast("double*", states_c) ) out = np.fromstring( ffi.buffer(signal_c), dtype=np.double, count=signal.size ) states = np.fromstring( ffi.buffer(states_c), dtype=np.double, count=len(states) ) return out.reshape((nframes, kbands, nchan), order='F'), states ``` -------------------------------- ### Designing B-Weighting Coefficients Source: https://siggigue.github.io/pyfilterbank/_modules/splweighting.html Generate filter coefficients for B-weighting and apply them using scipy.signal.lfilter. ```python >>> b, a = b_weighting_coeff_design(sample_rate) To Filter a signal use :function: scipy.lfilter: >>> from scipy.signal import lfilter >>> y = lfilter(b, a, x) ``` -------------------------------- ### splweighting.a_weighting_coeffs_design(sample_rate) Source: https://siggigue.github.io/pyfilterbank/splweighting.html Returns the b and a coefficients for an A-weighting filter based on the provided sample rate. ```APIDOC ## splweighting.a_weighting_coeffs_design(sample_rate) ### Description Returns b and a coefficients of an A-weighting filter. ### Parameters - **sample_rate** (scalar) - Required - Sample rate of the signals that will be filtered. ### Returns - **b, a** (ndarray) - Filter coefficients for a digital weighting filter. ``` -------------------------------- ### Create impulse signal Source: https://siggigue.github.io/pyfilterbank/_modules/gammatone.html Generates a complex impulse signal of a specified length. ```python def _create_impulse(num_samples): sig = zeros(num_samples) + 0j sig[0] = 1.0 return sig ``` -------------------------------- ### Filter input signal with filterbank Source: https://siggigue.github.io/pyfilterbank/_modules/pyfilterbank/octbank.html Filters an input signal using the filterbank's center frequencies and SOS matrices. Supports forward-backward filtering via the ffilt parameter. ```python def filter(self, x, ffilt=False, states=None): """Filters the input by the settings of the filterbank object. Parameters ---------- x : ndarray Input signal (Nx0) ffilt : bool Forward and backward filtering, if Ture. states : dict States of all filter sections in the filterbank. Initial you can states=None before block process. Returns ------- y : ndarray Fractional octave signals of the filtered input x states : dict Dictionary containing all filter section states. """ # in the next version this will be turne to a multi dimensional np array y_data = zeros((len(x), len(self.center_frequencies))) if not isinstance(states, dict): states_allbands = dict() for f in self.center_frequencies: states_allbands[f] = None else : states_allbands = states for i, f in enumerate(self.center_frequencies): states = states_allbands[f] sos = reshape(self.sosmat[:, i], (self.order, 6)) if not ffilt: y, states = self.sosfilterfun(x.copy(), sos, states) elif ffilt: y, states = self.sosfilterfun(x.copy()[::-1], sos, states) y, states = self.sosfilterfun(y[::-1], sos, states) y_data[:, i] = y states_allbands[f] = states return y_data, states_allbands ``` -------------------------------- ### Apply First Order Section Filtering Source: https://siggigue.github.io/pyfilterbank/_modules/gammatone.html Filters a signal using cascaded complex gammatone filters by applying first-order sections. ```python [docs]def fosfilter(b, a, order, signal, states=None): """Return signal filtered with `b` and `a` (first order section) by filtering the signal `order` times. This Function was created for filtering signals by first order section cascaded complex gammatone filters. Parameters ---------- b, a : ndarray, ndarray Filter coefficients of a first order section filter. Can be complex valued. order : int Order of the filter to be applied. This will be the count of refiltering the signal order times with the given coefficients. signal : ndarray Input signal to be filtered. states : ndarray, default None Array with the filter states of length `order`. Initial you can set it to None. Returns ------- signal : ndarray Output signal, that is filtered and complex valued (analytical signal). states : ndarray Array with the filter states of length `order`. You need to loop it back into this function when block processing. """ if not states: states = zeros(order, dtype=np.complex128) for i in range(order): state = [states[i]] signal, state = lfilter(b, a, signal, zi=state) states[i] = state[0] b = ones_like(b) return signal, states ```