Transfer functions (dsptoolbox.transfer_functions)

Transfer functions

In this module there are functions used to obtain, modify or analyze transfer functions (TF)/impulse responses (IR).

Acquire TF/IR from signals:

  • spectral_deconvolve() (direct deconvolution)

  • compute_transfer_function() (using welch’s method for estimating auto- and cross correlation spectra from measurements of stochastic signals)

Modify TF/IR:

  • window_ir() (Windows a TF in time domain)

  • apply_tukey_like_window() (Windows a TF in time domain)

  • min_phase_ir() (returns a minimum-phase version of the IR)

  • combine_ir_with_dirac() (combines an IR with a time-aligned dirac impulse)

  • average_irs() (averages all channels into a single IR)

  • trim_ir() (trims the IR pruning it from noise samples before and after the impulse)

Generate TF/IR from magnitude spectrum:

  • min_phase_from_mag() (generate an IR with minimum phase from a magnitude spectrum using the distcrete hilbert transform)

  • lin_phase_from_mag() (generate an IR with linear phase from a magnitude spectrum)

Analyze TF/IR:

  • group_delay()

  • minimum_group_delay()

  • excess_group_delay()

  • minimum_phase()

  • window_frequency_dependent() (obtain a spectrum with a frequency-dependent window)

  • find_ir_latency()

  • harmonics_from_chirp_ir()

  • harmonic_distortion_analysis()

  • complex_smoothing()

class dsptoolbox.transfer_functions.SmoothingDomain(*values)

Bases: Enum

These are the different domains to realize smoothing:

  • RealImaginary: smoothing directly on spectrum (real and imaginary).

  • PowerPhase: Smoothing on power and phase separately.

  • MagnitudePhase: Smoothing on magnitude and phase separately.

  • Power: smoothing on power response, phase response is maintained.

  • Magnitude: smoothing on magnitude response, phase response is maintained.

  • EquivalentComplex: smoothing on power response, phase is obtained from the smoothed RealImaginary variant. This is the scheme proposed as equivalent complex smoothing by [1].

References

  • [1]: GENERALIZED FRACTIONAL OCTAVE SMOOTHING OF AUDIO / ACOUSTIC RESPONSES. PANAGIOTIS D. HATZIANTONIOU AND JOHN N. MOURJOPOULOS.

EquivalentComplex = 6
Magnitude = 5
MagnitudePhase = 3
Power = 4
PowerPhase = 2
RealImaginary = 1
class dsptoolbox.transfer_functions.TransferFunctionType(*values)

Bases: Enum

Types of transfer functions for stochastic signals:

  • H1: for noise in the output signal. Gxy/Gxx.

  • H2: for noise in the input signal. Gyy/Gyx.

  • H3: for noise in both signals. G_xy / abs(G_xy) * (G_yy/G_xx)**0.5.

H1 = 1
H2 = 2
H3 = 3
dsptoolbox.transfer_functions.average_irs(signal: ImpulseResponse, time_average: bool = True, normalize_energy: bool = True) ImpulseResponse

Averages all channels of a given IR. It can either use a time domain average while time-aligning all channels to the one with the longest latency, or average directly their magnitude and phase responses.

Parameters:
signalImpulseResponse

Signal with channels to be averaged over.

time_averagebool, optional

When True, the IRs are time-aligned to the channel with the largest (minimum-phase) latency and then averaged in the time domain. False averages directly the magnitude and phase of each IR. Default: True.

normalize_energybool, optional

When True, the energy of all spectra is normalized to the first channel’s energy and then averaged. Beware that normalization factors might be clipped if the impulses are already at or close to 0 dBFS. Default: True.

Returns:
avg_sigImpulseResponse

Averaged impulse response.

dsptoolbox.transfer_functions.combine_ir_with_dirac(ir: ImpulseResponse, crossover_frequency: float, take_lower_band: bool, order: int = 8, normalization: str | float | None = None) ImpulseResponse

Combine an IR with a perfect impulse at a given crossover frequency using a linkwitz-riley crossover. Forward-Backward filtering is done so that no phase distortion occurs. They can optionally be energy matched using RMS or peak value.

Parameters:
irdsp.Signal

Impulse Response.

crossover_frequencyfloat

Frequency at which to combine the impulse response with the perfect impulse.

take_lower_bandbool

When True, the part below the crossover frequency corresponds to the passed impulse response and above corresponds to the perfect impulse. False delivers the opposite result.

orderint, optional

Crossover order. Default: 8.

normalizationstr, float, optional

‘energy’ means that the band of the perfect dirac impulse is normalized so that it matches the energy contained in the band of the impulse response. ‘peak’ means that peak value is matched for both bands. None avoids any normalization (Impulse response is always normalized prior to computation). Alternatively, a value in dB can be passed in order to scale the dirac part of the resulting impulse. Default: None.

Returns:
combined_irdsp.Signal

New IR.

Notes

  • The algorithm checks for the fractional delay of the IR and adds a fractional delayed dirac. For ensuring good results, it is recommended that the IR has some delay, so that the first part of the added dirac impulse has time to grow smoothly.

dsptoolbox.transfer_functions.complex_smoothing(ir: ImpulseResponse, octave_fraction: float, smoothing_domain: SmoothingDomain, window: Window = Window.Hann) Spectrum

Complex smoothing of an impulse response using logarithmic spacing given in octaves. This is done according to [1].

Parameters:
irImpulseResponse

Impulse response to apply smoothing to.

octave_fractionfloat

Width of smoothing range in fraction of octaves.

smoothing_domainSmoothingDomain

Domain to use during the smoothing step.

windowWindow

Type of window to use.

Returns:
Spectrum

References

  • [1]: GENERALIZED FRACTIONAL OCTAVE SMOOTHING OF AUDIO / ACOUSTIC RESPONSES. PANAGIOTIS D. HATZIANTONIOU AND JOHN N. MOURJOPOULOS.

dsptoolbox.transfer_functions.compute_transfer_function(output: Signal, input: Signal, window_length_samples: int, mode: TransferFunctionType = TransferFunctionType.H2) Spectrum

Gets transfer function H1, H2 or H3 (for stochastic signals). If the input signal only has one channel, it is assumed to be the input for all of the channels of the output.

The spectrum parameters for the input will be used for the computation.

Parameters:
outputSignal

Signal with output channels.

inputSignal

Signal with input channels.

window_length_samplesint

Window length for the IR. Spectrum has the length.

modeTransferFunction, optional

Type of transfer function. Default: H2.

Returns:
specSpectrum

Transfer functions as Spectrum. Coherences are also computed and saved as coherence attribute.

Notes

  • SNR can be gained from the coherence: snr = coherence / (1 - coherence)

dsptoolbox.transfer_functions.excess_group_delay(signal: ImpulseResponse, smoothing: int = 0, remove_ir_latency: bool = False, analytic_computation: bool = False) tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]]

Computes excess group delay of an IR.

Parameters:
signalImpulseResponse

IR for which to compute minimal group delay.

smoothingint, optional

Octave fraction by which to apply smoothing. 0 avoids any smoothing of the group delay. Default: 0.

remove_ir_latencybool, optional

When True, the impulse delay will be removed by checking the peak latency. Default: False.

analytic_computationbool, optional

When True, the analytic computation of group delay is performed instead of the numerical one. This is significantly slower. Default: False.

Returns:
fNDArray[np.float64]

Frequency vector.

ex_gdNDArray[np.float64]

Excess group delays in seconds with shape (excess_gd, channel).

References

dsptoolbox.transfer_functions.filter_to_ir(fir: Filter | FilterBank) ImpulseResponse

Takes in an FIR filter or multiple filters in a filter bank and converts them into an IR by taking its b coefficients.

Parameters:
firFilter or FilterBank

Filter containing an FIR filter. In case of a FilterBank, all filters should be FIR.

Returns:
new_sigImpulseResponse

New IR. If the input was a FilterBank, the ImpulseResponse has multiple channels. Its length always corresponds to the longest filter.

dsptoolbox.transfer_functions.find_ir_latency(ir: ImpulseResponse, compare_to_min_phase_ir: bool = True) ndarray[tuple[Any, ...], dtype[float64]]

Find the subsample maximum of each channel of the IR.

Parameters:
irImpulseResponse

Impulse response to find the maximum.

compare_to_min_phase_irbool, optional

When True, the latency is found by comparing the latency of the IR in relation to its minimum phase equivalent. When False, the peak in the time data is searched. Both cases are done with subsample accuracy. For the former, the padding factor 8 is used. Default: True.

Returns:
latency_samplesNDArray[np.float64]

Array with the position of each channel’s latency in samples.

dsptoolbox.transfer_functions.group_delay(signal: Signal, analytic_computation: bool = True, smoothing: int = 0, remove_ir_latency: bool = False) tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]]

Computes and returns group delay.

Parameters:
signalSignal

Signal for which to compute group delay.

analytic_computationbool, optional

When True, this implementation is used: https://www.dsprelated.com/freebooks/filters/Phase_Group_Delay.html. Otherwise, the numerical gradient of the unwrapped phase response is used. Default: True.

smoothingint, optional

Octave fraction by which to apply smoothing. 0 avoids any smoothing of the group delay. Default: 0.

remove_ir_latencybool, optional

If the signal is of type “ir” or “rir”, the impulse delay can be removed by analyzing the minimum phase equivalent. This uses the padding factor 8 by default. Default: False.

Returns:
freqsNDArray[np.float64]

Frequency vector in Hz.

group_delaysNDArray[np.float64]

Matrix containing group delays in seconds with shape (gd, channel).

dsptoolbox.transfer_functions.harmonic_distortion_analysis(ir: ImpulseResponse | list[ImpulseResponse], chirp_range_hz: list | None = None, chirp_length_s: float | None = None, n_harmonics: int | None = 8, smoothing: int = 12, generate_plot: bool = True) dict

Analyze non-linear distortion coming from an IR measured with an exponential chirp. The range of the chirp and its length must be known. The distortion spectra of each harmonic, as well as THD+N and THD, are returned. Optionally, a plot can be generated.

Parameters:
irImpulseResponse or list[ImpulseResponse]

Impulse response. It should only have one channel. Alternatively, a list containing the fundamental IR and all harmonics can be passed, in which case chirp_range_hz, chirp_length_s and n_harmonics will be ignored or inferred. In the second case, no windowing or trimming will be applied to either the fundamental or the harmonics.

chirp_range_hzlist

List with length 2 containing the lowest and highest frequency of the exponential chirp.

chirp_length_sfloat

Length of the chirp (time from lowest to highest frequency) in seconds.

n_harmonicsint, optional

Number of harmonics to analyze. Default: 8.

smoothingint, optional

Smoothing as fraction of an octave band to apply to all spectra. Default: 12.

generate_plotbool, optional

When True, a plot with all the distortion spectra is generated. Default: True.

Returns:
dict

A dictionary containing each spectrum is returned. Each item is of type Spectrum. Its keys are:

  • “1”: spectrum of the fundamental.

  • “2”: spectrum of the second harmonic.

  • “3”: …

  • “thd”: Total harmonic distortion. The spectrum is shifted to the frequency that caused the distortion.

  • “thd_percent”: Total harmonic distortion normalized by the linear response. It is shifted as thd and returned in percent.

  • “thd_n”: Total harmonic distortion + noise. This spectrum is not shifted to the frequency that caused the distortion.

  • “plot”: a list with matplotlib’s [figure, axes]. This is only returned if the plot was generated.

Notes

  • The scaling of the spectrum is always done as set with set_spectrum_parameters() of the original IR.

  • THD in percent is usually defined in audio by the amplitude ratios instead of the power ratios, as is common for other fields. See https://de.wikipedia.org/wiki/Total_Harmonic_Distortion.

  • Passing chirp_range_hz with a list of IRs will still have an effect on the upper limit frequency of each harmonic.

dsptoolbox.transfer_functions.harmonics_from_chirp_ir(ir: ImpulseResponse, chirp_range_hz: list, chirp_length_s: float, n_harmonics: int = 5, offset_percentage: float = 0.05) list[ImpulseResponse]

Get the individual harmonics (distortion) IRs of an IR computed with an exponential chirp.

Parameters:
irImpulseResponse

Impulse response obtained through deconvolution with an exponential chirp.

chirp_range_hzlist of length 2

The frequency range of the chirp.

chirp_length_sfloat

Length of chirp in seconds (without zero-padding).

n_harmonicsint, optional

Number of harmonics to analyze. Default: 5.

offset_percentagefloat, optional

When this is larger than zero, each IR will also contain some samples prior to the impulse. Their amount corresponds to a percentage of the time length between that harmonic and their adjacent ones. All samples are gathered in a mutually exclusive manner, such they are never passed to two different harmonics. Default: 0.05.

Returns:
harmonicslist[ImpulseResponse]

List containing the IRs of each harmonic in ascending order. The fundamental is not in the list.

Notes

  • This will only work if the IR was gained utilizing an exponential chirp that has also been zero padded during the deconvolution. This will not be checked in this function.

dsptoolbox.transfer_functions.ir_to_filter(signal: ImpulseResponse, channel: int | None = 0, phase_mode: str = 'direct') Filter | FilterBank

This function takes in an impulse response and turns the selected channel into an FIR filter. With phase_mode it is possible to use minimum phase or minimum linear phase.

Parameters:
signalSignal

Signal to be converted into a filter.

channelint, optional

Channel of the signal to be used. If None, all channels are used and the return is a FilterBank with each channel as an FIR filter. This also applies for a signal with a single channel. Default: 0.

phase_mode{“direct”, “min”, “lin”} str, optional

Phase of the FIR filter. Choose from “direct” (no changes to phase), “min” (minimum phase) or “lin” (minimum linear phase). Default: “direct”.

Returns:
filtFilter or FilterBank

(FIR) Filter from a single channel or FilterBank with FIR filters from each channel.

dsptoolbox.transfer_functions.lin_phase_from_mag(spectrum: Spectrum, sampling_rate_hz: int, group_delay_ms: float | None = None, check_causality: bool = True, minimum_group_delay_factor: float = 1.0) ImpulseResponse

Returns a linear phase signal from a magnitude spectrum. It is possible to return the smallest causal group delay by checking the minimum phase version of the signal and choosing a constant group delay that is never lower than minimum group delay (for each channel). A value for the group delay can be also passed directly and applied to all channels. If check causility is activated, it is assessed that the given group delay is not less than each minimum group delay. If deactivated, the generated phase could lead to a non-causal system!

Parameters:
spectrumSpectrum

Spectrum with only positive frequencies and 0.

sampling_rate_hzint

Sampling rate in Hz for the output impulse response.

group_delay_msfloat, None, optional

Constant group delay that the phase should have for all channels (in ms). Pass None to create a signal with the minimum linear phase possible by regarding the minimum-phase response (it is different for each channel). Default: None.

check_causalitybool, optional

When True, it is assessed for each channel that the given group delay is not lower than the minimum group delay. Default: True.

minimum_group_delay_factorfloat, optional

When computing from the group delay from the minimum group delay, the magnitude response can be distorted for low frequencies. Increase this factor to add delay and correct this distortion. Default: 1.

Returns:
ImpulseResponse

Impulse response with same magnitude spectrum but linear phase. Its length is always twice the delay.

dsptoolbox.transfer_functions.min_phase_from_mag(spectrum: Spectrum, sampling_rate_hz: int, ir_length_samples: int | None = None) ImpulseResponse

Returns a minimum-phase signal from a magnitude spectrum using the discrete hilbert transform.

Parameters:
spectrumSpectrum

Spectrum with only positive frequencies.

sampling_rate_hzint

Sampling rate in Hz for output impulse response.

ir_length_samplesint, None, optional

Pass to define the frequency resolution during computation and the final length of the impulse response. Pass None to use some estimate which might suffice for most cases. Default: None.

Returns:
ImpulseResponse

Signal with same magnitude spectrum but minimum phase.

References

dsptoolbox.transfer_functions.min_phase_ir(sig: ImpulseResponse, use_real_cepstrum: bool = True, padding_factor: int = 8, alpha: float = 1.0) ImpulseResponse

Returns same IR with minimum phase. Two methods are available for computing the minimum phase version of the IR: ‘real cepstrum’ (using filtering the real-cepstral domain) and ‘equiripple’ (for symmetric IR, uses scipy.signal.minimum_phase).

Parameters:
sigImpulseResponse

IR for which to compute minimum phase IR.

use_real_cepstrumbool, optional

Set to True for general cases. If the IR is symmetric (like a linear-phase filter), False is recommended. Default: True.

padding_factorint, optional

Zero-padding to a length corresponding to current_length * padding_factor can be done, in order to avoid time aliasing errors. Default: 8.

alphafloat, optional

This value can be used to premultiply the IR with alpha**n, where n is the index of the time sample. This is done such that the zeroes of the transfer function are pushed towards the origin of the z-plane, thus ensuring minimum phase outputs. This value should be very close to 1. Useful values are around 1-1e-4 and 1-1e-8. See [1] and [2] for details. Default: 1. (No scaling is used).

Returns:
ImpulseResponse

Minimum-phase IR as time signal.

References

  • [1]: Adrian D. Smith, Robert J. Ferguson. Minimum-phase signal calculation using the real cepstrum.

  • [2]: Soo-Chang Pei, Huei-Shan Lin. MINIMUM-PHASE FIR FILTER DESIGN USING REAL CEPSTRUM.

dsptoolbox.transfer_functions.minimum_group_delay(signal: ImpulseResponse, smoothing: int = 0, padding_factor: int = 8) tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]]

Computes minimum group delay of given IR using the real cepstrum method.

Parameters:
signalImpulseResponse

IR for which to compute minimal group delay.

smoothingint, optional

Octave fraction by which to apply smoothing. 0 avoids any smoothing of the group delay. Default: 0.

padding_factorint, optional

Zero-padding to a length corresponding to at least current_length * padding_factor can be done in order to avoid time aliasing errors. Default: 8.

Returns:
fNDArray[np.float64]

Frequency vector.

min_gdNDArray[np.float64]

Minimum group delays in seconds as matrix with shape (gd, channel).

References

dsptoolbox.transfer_functions.minimum_phase(signal: ImpulseResponse, use_real_cepstrum: bool = True, padding_factor: int = 8) tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]]

Gives back a matrix containing the minimum phase signal for each channel. Two methods are available for computing the minimum phase of a system: ‘real cepstrum’ (windowing in the cepstral domain) or ‘equiripple’ (for symmetric IR’s, uses scipy.signal.minimum_phase).

Parameters:
signalSignal

IR for which to compute the minimum phase.

use_real_cepstrumbool, optional

Set to True for general cases. If the IR is symmetric (like a linear-phase filter), False is recommended. Default: True.

padding_factorint, optional

Zero-padding to a length corresponding to at least current_length * padding_factor can be done in order to avoid time aliasing errors. Default: 8.

Returns:
fNDArray[np.float64]

Frequency vector.

min_phasesNDArray[np.float64]

Minimum phases as matrix with shape (phase, channel).

dsptoolbox.transfer_functions.spectral_deconvolve(output: Signal, input: Signal, apply_regularization: bool = True, start_stop_hz=None, threshold_db: float = -30.0, padding: bool = False, keep_original_length: bool = False) ImpulseResponse

Deconvolution by spectral division of two signals. If the denominator signal only has one channel, the deconvolution is done using that channel for all channels of the numerator.

Parameters:
outputSignal

Numerator during deconvolution. It corresponds to the output in the measurement of a linear system.

inputSignal

Denominator during deconvolution. This corresponds to the input in a linear system measurement.

apply_regularizationbool, optional

When True, a regularization window is applied for avoiding noise outside the excitation frequency region. Default: True.

start_stop_hzarray-like or None, optional

This is a vector of length 2 or 4 with frequency values that define the frequency region of the input (denominator) that has some energy during the deconvolution, i.e., this is the regularization range. If length is 2, the outer bounds are computed with half an octave distance. Pass None to use an automatic mode that recognizes the start and stop of the denominator (it assumes a pink-like spectrum). Default: None.

threshold_dbfloat, optional

Threshold in dBFS for the automatic creation of the frequency window for the regularization during deconvolution. Default: -30.

paddingbool, optional

Pads the time data with 2 length. Done for separating distortion in negative time bins when deconvolving sweep measurements. Default: False.

keep_original_lengthbool, optional

Only regarded when padding is True. It trims the newly deconvolved data to its original length. Default: False.

Returns:
new_sigSignal

Deconvolved signal.

Notes

  • The deconvolution delivers an impulse response for the linear system that is not constrained in amplitude since some linear systems might amplify an input significantly and the true peak value should be preserved. This is also highly dependent on the phase response.

dsptoolbox.transfer_functions.trim_ir(ir: ImpulseResponse, channel: int | None = None, start_offset_s: float | None = 0.02) tuple[ImpulseResponse, int, int]

Trim an IR in the beginning and end. This method acts only on one channel and returns it trimmed. For defining the ending, a smooth envelope of the energy time curve (ETC) is used, as well as the assumption that the energy should decay monotonically after the impulse arrives. See notes for details.

Parameters:
irImpulseResponse

Impulse response to trim.

channelint, None, optional

Channel to take from rir. Pass None to apply to all channels and return a multichannel signal that has the largest time boundaries found across all channels. Default: None.

start_offset_sfloat, None, optional

This is the time prior to the peak value that is left after trimming. Pass 0 to start the IR one sample prior to peak value or a very big offset (or None) to avoid any trimming at the beginning. Default: 20e-3 (20 milliseconds).

Returns:
trimmed_irImpulseResponse

IR with the new length.

startint

Start index of the trimmed IR in the original vector.

stopint

Stop index of the trimmed IR in the original vector.

Notes

  • The method employed for finding the ending of the IR works as follows:
    • A (hilbert) envelope is computed in dB (energy time curve). This is smoothed by exponential averaging with 20 ms.

    • Non-overlapping windows with lengths 10, 30, 50 and 80 ms are checked starting from the impulse and going forwards. The first window to contain more energy than the previous one is regarded as the end of the IR.

    • Pearson correlation coefficients (cc) of the energy decay for the segments obtained with each window size are computed. The final end point is selected following criteria:

      • If a good linear fit is obtained (cc < -0.95), it is used as the final point.

      • Else, if there are acceptable fits (cc < -0.9), the ending point is the averaged from these.

      • Else, if there are any fits with cc < -0.7, they are all averaged but the best one is weighted significantly stronger.

      • If no fit has cc < -0.7, all are averaged together with the total length of the IR weighted stronger than the other values.

dsptoolbox.transfer_functions.window_centered_ir(signal: ImpulseResponse, total_length_samples: int, window_type: Window = Window.Hann) tuple[ImpulseResponse, ndarray[tuple[Any, ...], dtype[_ScalarT]]]

This function windows an IR placing its peak in the middle. It trims it to the total length of the window or pads it to the desired length (padding in the end, window has total_length).

Parameters:
signal: `ImpulseResponse`

Signal to window

total_length_samples: int

Total window length in samples.

window_type: Window, optional

Window function to be used. Default: Hann.

Returns:
new_sigImpulseResponse

Windowed signal. The used window is also saved under new_sig.window.

start_positions_samplesNDArray

This array contains the position index of the start of the IR in each channel of the original IR.

Notes

  • If the window seems truncated, it is because the length and peak position were longer than the IR, so that it had to be zero-padded to match the given length.

dsptoolbox.transfer_functions.window_frequency_dependent(ir: ImpulseResponse, cycles: int, end_window_value_db: float = -50.0) Spectrum

A spectrum with frequency-dependent windowing defined by cycles is returned. To this end, a variable gaussian window is applied.

A width of 5 cycles means that there are 5 periods of each frequency before the window values hit end_window_value_db.

The output spectrum can be converted to a time series with a IRFFT. Its frequency vector has linear resolution.

Parameters:
irImpulseResponse

Impulse response from which to extract the spectrum.

cyclesint

Number of cycles to include for each frequency bin. It defines the window lengths.

end_window_value_dbfloat, optional

This is the value that the gaussian window should have at its given width in dB. It must be below 0 dB. Default: -50.

Returns:
Spectrum

Complex spectrum.

Notes

  • It is recommended that the impulse response has been already left- and right-windowed using, for instance, a tukey window. However, its length should be somewhat larger than the longest window (this depends on the number of cycles and lowest frequency).

  • The length of the IR should be as short as possible for a fast computation. This implementation will use numba, if available, for parallelizing the computation.

  • The implemented method is a straight-forward windowing in the time domain for each respective frequency bin. Warping the IR is another valid approach, but its frequency resolution will not be linear.

dsptoolbox.transfer_functions.window_ir(signal: ImpulseResponse, total_length_samples: int, adaptive: bool = True, constant_percentage: float = 0.75, window_type: Window | list[Window] = Window.Hann, at_start: bool = True, offset_samples: int = 0, left_to_right_flank_length_ratio: float = 1.0) tuple[ImpulseResponse, ndarray[tuple[Any, ...], dtype[_ScalarT]]]

Windows an IR with trimming and selection of constant valued length. This is equivalent to a tukey window whose flanks can be selected to be any type. The peak of the impulse response is aligned to correspond to the first value with amplitude 1 of the window.

BEWARE: This function moves the starting point for each channel, thus losing timing information between channels.

Parameters:
signalImpulseResponse

Signal to window

total_length_samplesint

Total window length in samples.

adaptivebool, optional

When True, some design parameters will modified in case that the IR does not have enough samples to accomodate them. See Notes for more details. Default: True.

constant_percentagefloat, optional

Percentage (between 0 and 1) of the window’s length that should be constant value. Default: 0.75.

window_typeWindow, list[Window], optional

Window function to be used for the flanks. Pass a list containing two windows to use different windows for the left and right flanks respectively. Default: Hann.

at_startbool, optional

Windows the start with a rising window as well as the end. Default: True.

offset_samplesint, optional

Passing an offset in samples delays the impulse w.r.t. the first window value with amplitude 1. The offset must be inside the constant region of the window. Default: 0.

left_to_right_flank_length_ratiofloat, optional

This is the length ratio between left and right flanks. For instance, 2 leads to a length of the left flank twice as long as the right one, while 0.1 would be a tenth of the length. Default: 1 (equal length).

Returns:
new_sigImpulseResponse

Windowed signal. The used window is also saved under new_sig.window.

start_positions_samplesNDArray

This array contains the position index of the start of the IR in each channel of the original IR (relative to the possibly padded windowed IR).

Notes

  • With adaptive=True, following modifications are allowed:
    • Left flank length is variable to fit the first part of the IR. The offset is always maintained.

    • Constant amplitude part of the window is modified in order to fit the right flank into the IR. If the IR is too short, there might be only a couple samples with constant amplitude.

  • With adaptive=False, the desired window might not fit the given IR. In that case, the window values that will be multiplied with zero-padded parts of the window are set to 0 in order to make them visible.

dsptoolbox.transfer_functions.window_ir_tukey(ir: ImpulseResponse, left_flank_s: float | None, right_flank_s: float | None, window_flank_type: Window = Window.Hann) ImpulseResponse

This function applies a Tukey-like window to all channels of an ImpulseResponse. This preserves timing information across channels in contrast to window_ir.

Parameters:
irImpulseResponse

Impulse response to apply window to.

left_flank_sfloat, None

Duration of the left flank of the windw in seconds. Pass None to avoid applying a window to the left flank altogether.

right_flank_sfloat, None

Duration of the right flank of the windw in seconds. Pass None to avoid applying a window to the right flank altogether.

window_flank_typeWindow, optional

Window type to compute the flanks from. See Notes for details. Default: Hann.

Returns:
ImpulseResponse

New impulse response with applied window.

Notes

  • The usual Tukey window applies flanks that correspond to a Hann window. This function offers the possibility of applying any type of from the supported Window types.