lsd¶
- hrtfpykit.hrtf.lsd(hrtf_a, hrtf_b, ear='both', plane='all', elevation=0.0, positions=None, frequencies=None, reduction='none', epsilon=1e-12)¶
Compute log-spectral distortion (LSD) between two HRTFs in dB.
LSD compares two frequency-domain HRTFs in the logarithmic magnitude domain. Both inputs must provide
TF.valueswith shape (positions, ears, frequency_bins), matchingTF.frequency_bins, and matching source positions fromget_positions()in degrees.The comparison can be restricted to one ear, both ears, all source positions, a measured horizontal or median plane, explicit source-position queries, explicit frequency queries, or a reduced scalar. Position queries are resolved against
Sourcesin spherical degrees and then intersected with the selected plane. Frequency queries are mapped to the nearest available TF bins and duplicate bin selections are removed.The selected ear axis is averaged after the per-ear LSD calculation. reduction=``none`` returns absolute dB differences. The other reductions use root-mean-square dB differences over the requested axes before the ear average.
- Parameters:
hrtf_a (HRTF) – First
HRTFobject used in the comparison. It must provide TF values, frequency bins, and a source grid matching hrtf_b.hrtf_b (HRTF) – Second
HRTFobject used in the comparison. It must provide TF values, frequency bins, and a source grid matching hrtf_a.ear ({
left,right,both}, default=``both``) – Ear channel selection.leftuses ear channel 0,rightuses ear channel 1, andbothevaluates both channels before averaging over ears.plane ({
all,horizontal,median}, default=``all``) – Spatial subset used before comparison.alluses the current full source grid,horizontaluses the nearest measured horizontal plane at elevation, andmedianuses the canonical median plane at azimuth 0 degrees.elevation (float, default=0.0) – Requested elevation in degrees used only when plane=``horizontal``. The nearest measured elevation in hrtf_a is used.
positions (np.ndarray | list | tuple | str | None, default=None) – Optional source-position selector. Accepts one query or a collection of queries in the format accepted by
get_position_queries(), including named positions such asfrontand numeric spherical queries with shape (2,) or (3,). Resolved position indices are intersected with the selected plane.frequencies (float | list[float] | tuple[float, ...] | np.ndarray | None, default=None) – Optional frequency selector in hertz. Each requested frequency is mapped to the nearest available TF bin. None selects all available bins from 20 Hz through 20 kHz, inclusive, which excludes DC for typical one-sided FFT grids.
reduction ({
none,locations,frequencies,global}, default=``none``) – Aggregation mode.nonekeeps selected positions and frequencies,locationsreduces over positions and returns one value per selected frequency,frequenciesreduces over frequencies and returns one value per selected position, andglobalreduces over positions and frequencies to one scalar.epsilon (float, default=1e-12) – Positive lower bound applied to magnitudes before conversion to dB. This avoids invalid values from log10(0).
- Returns:
LSD values in dB. With reduction=``none``, the usual output shape is (selected_positions, selected_frequencies); if one frequency is selected, the frequency axis is squeezed and the output has shape (selected_positions,). With reduction=``locations``, the output is indexed by selected frequency, or returned as a scalar when only one frequency is selected. With reduction=``frequencies``, the output is indexed by selected position. With reduction=``global``, the output is a scalar.
- Return type:
np.ndarray | float
- Raises:
ValueError – If either input is not an HRTF-like object with
TFandSources, if TF values or frequency bins are missing, if source positions, TF shapes, or frequency bins do not match, if TF values are not arranged as (positions, ears, frequency_bins), if the ear axis has fewer than two channels, if ear, plane, or reduction is unsupported, if epsilon is not finite and positive, if selected planes or position filters produce no source positions, if frequency selectors are invalid or select no bins, or if reduction=``frequencies`` is requested for a single selected frequency.
Notes
Use reduction=``none`` for heatmaps and per-bin diagnostics, reduction=``frequencies`` for one spatial error value per source position, reduction=``locations`` for one spectral error curve, and reduction=``global`` for a single comparison score.
Examples
Compare the horizontal-plane spectra of two HRTFs at a few analysis frequencies and reduce over source locations:
>>> from hrtfpykit.hrtf import load_hrtf, lsd >>> hrtf_a = load_hrtf("hrtfs/P0001_FreeFieldComp_44kHz.sofa") >>> hrtf_b = load_hrtf("hrtfs/P0002_FreeFieldComp_44kHz.sofa") >>> spectral_error = lsd( ... hrtf_a, ... hrtf_b, ... ear="both", ... plane="horizontal", ... elevation=0.0, ... frequencies=[500.0, 1000.0, 4000.0], ... reduction="locations", ... ) >>> spectral_error.shape (3,)