spaudiopy.decoder

Loudspeaker decoders.

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['axes.grid'] = True

import spaudiopy as spa

# Loudspeaker Setup
ls_dirs = np.array([[-80, -45, 0, 45, 80, -60, -30, 30, 60],
                    [0, 0, 0, 0, 0, 60, 60, 60, 60]])
ls_x, ls_y, ls_z = spa.utils.sph2cart(spa.utils.deg2rad(ls_dirs[0, :]),
                                      spa.utils.deg2rad(90-ls_dirs[1, :]))

Functions

allrad(F_nm, hull[, N_sph, jobs_count])

Loudspeaker signals of All-Round Ambisonic Decoder.

allrad2(F_nm, hull[, N_sph, jobs_count])

Loudspeaker signals of All-Round Ambisonic Decoder 2.

allrap(src, hull[, N_sph, jobs_count])

Loudspeaker gains for All-Round Ambisonic Panning.

allrap2(src, hull[, N_sph, jobs_count])

Loudspeaker gains for All-Round Ambisonic Panning 2.

apply_blacklist(hull[, blacklist])

Specify a blacklist to exclude simplices from valid simplices.

calculate_barycenter(hull)

Barycenter of hull object.

calculate_centroids(hull)

Calculate centroid for each simplex.

calculate_face_areas(hull)

Calculate area for each simplex.

calculate_face_normals(hull[, eps, normalize])

Calculate outwards pointing normal for each simplex.

calculate_vertex_normals(hull[, normalize])

Calculate normal for each vertex from simplices normals.

characteristic_ambisonic_order(hull)

Find the characteristic order for specified loudspeaker layout.

check_aperture(hull[, aperture_limit, ...])

Return valid simplices, where the aperture form the listener is small.

check_listener_inside(hull[, listener_position])

Return valid simplices for which the listener is inside the hull.

check_normals(hull[, normal_limit, ...])

Return valid simplices that point towards listener.

check_opening(hull[, opening_limit])

Return valid simplices with all opening angles within simplex > limit.

epad(F_nm, hull[, N_sph])

Loudspeaker signals of Energy-Preserving Ambisonic Decoder.

find_imaginary_loudspeaker(hull)

Find imaginary loudspeaker coordinates for smoother hull.

get_hull(x, y, z)

Wrapper for scipy.spatial.ConvexHull.

mad(F_nm, hull[, N_sph])

Loudspeaker signals of Mode-Matching Ambisonic Decoder.

magls_bin(hrirs, N_sph[, f_trans, hf_cont, ...])

Magnitude Least-Squares (magLS) binaural decoder.

nearest_loudspeaker(src, hull)

Loudspeaker gains for nearest loudspeaker selection (NLS) decoding, based on euclidean distance.

sad(F_nm, hull[, N_sph])

Loudspeaker signals of Sampling Ambisonic Decoder.

sh2bin(sig_nm, hrirs_nm)

Spherical Harmonic Domain signals to binaural renderer.

sort_vertices(simplices)

Start the simplices with smallest vertex entry.

vbap(src, hull[, norm, valid_simplices, ...])

Loudspeaker gains for Vector Base Amplitude Panning decoding.

vbip(src, hull[, norm, valid_simplices, ...])

Loudspeaker gains for Vector Base Intensity Panning decoding.

Classes

LoudspeakerSetup(x, y, z[, listener_position])

Creates a 'hull' object containing all information for further decoding.

class spaudiopy.decoder.LoudspeakerSetup(x, y, z, listener_position=None)[source]

Bases: object

Creates a ‘hull’ object containing all information for further decoding.

ls_setup = spa.decoder.LoudspeakerSetup(ls_x, ls_y, ls_z)
ls_setup.pop_triangles(normal_limit=85, aperture_limit=90,
                       opening_limit=150)
ls_setup.show()

(png, hires.png, pdf)

_images/spaudiopy-decoder-2.png
__init__(x, y, z, listener_position=None)[source]
Parameters:
  • x (array_like)

  • y (array_like)

  • z (array_like)

  • listener_position ((3,), cartesian, optional) – Offset, will be substracted from the loudspeaker positions.

classmethod from_sph(azi, zen, r=1, listener_position=None)[source]

Alternative constructor, using spherical coordinates in rad.

Parameters:
  • azi (array_like, spherical)

  • zen (array_like, spherical)

  • r (array_like, spherical)

  • listener_position ((azi, zen, r), spherical, optional) – Offset, will be substracted from the loudspeaker positions.

is_simplex_valid(simplex)[source]

Tests if simplex is in valid simplices (independent of orientation).

pop_triangles(normal_limit=85, aperture_limit=None, opening_limit=None, blacklist=None)[source]

Refine triangulation by removing them from valid simplices. Bypass by passing ‘None’.

Parameters:
  • normal_limit (float, optional)

  • aperture_limit (float, optional)

  • opening_limit (float, optional)

  • blacklist (list, optional)

get_characteristic_order()[source]

Characteristic Ambisonics order.

ambisonics_setup(update_hull=False, imaginary_ls=None, characteristic_order=None, N_kernel=50)[source]

Prepare loudspeaker hull for ambisonic rendering. Sets the kernel_hull as an n-design of twice N_kernel, and updates the ambisonic hull with an additional imaginary loudspeaker, if desired.

Parameters:
  • update_hull (bool, optional)

  • imaginary_ls ((L, 3), cartesian, optional) – Imaginary loudspeaker positions, if set to ‘None’ calls ‘find_imaginary_loudspeaker()’ for ‘update_hull’.

  • characteristic_order (int, optional) – Characteristic Ambisonic order, ‘None’ calls ‘get_characteristic_order()’

  • N_kernel (int, optional)

Examples

ls_setup.ambisonics_setup(update_hull=True)
N_e = ls_setup.characteristic_order
ls_setup.ambisonics_hull.show(title=f"Ambisonic Hull, $N_e={N_e}$")

(png, hires.png, pdf)

_images/spaudiopy-decoder-3.png
binauralize(ls_signals, fs, orientation=(0, 0), hrirs=None)[source]

Create binaural signals that the loudspeaker signals produce on this setup (no delays).

Parameters:
  • ls_signals ((L, S) np.ndarray) – Loudspeaker signals.

  • fs (int)

  • orientation ((azi, zen) tuple, optional) – Listener orientation offset (azimuth, zenith) in rad.

  • hrirs (sig.HRIRs, optional)

Returns:

  • l_sig (array_like)

  • r_sig (array_like)

loudspeaker_signals(ls_gains, sig_in=None)[source]

Render loudspeaker signals.

Parameters:
  • ls_gains ((S, L) np.ndarray)

  • sig_in ((S,) array like, optional)

Returns:

sig_out ((L, S) np.ndarray)

show(title='Loudspeaker Setup', **kwargs)[source]

Plot hull object, calls plot.hull().

spaudiopy.decoder.get_hull(x, y, z)[source]

Wrapper for scipy.spatial.ConvexHull.

spaudiopy.decoder.calculate_centroids(hull)[source]

Calculate centroid for each simplex.

spaudiopy.decoder.calculate_face_areas(hull)[source]

Calculate area for each simplex.

spaudiopy.decoder.calculate_face_normals(hull, eps=1e-05, normalize=False)[source]

Calculate outwards pointing normal for each simplex.

spaudiopy.decoder.calculate_vertex_normals(hull, normalize=False)[source]

Calculate normal for each vertex from simplices normals.

spaudiopy.decoder.calculate_barycenter(hull)[source]

Barycenter of hull object.

spaudiopy.decoder.check_listener_inside(hull, listener_position=None)[source]

Return valid simplices for which the listener is inside the hull.

spaudiopy.decoder.check_normals(hull, normal_limit=85, listener_position=None)[source]

Return valid simplices that point towards listener.

spaudiopy.decoder.check_aperture(hull, aperture_limit=90, listener_position=None)[source]

Return valid simplices, where the aperture form the listener is small.

spaudiopy.decoder.check_opening(hull, opening_limit=135)[source]

Return valid simplices with all opening angles within simplex > limit.

spaudiopy.decoder.apply_blacklist(hull, blacklist=None)[source]

Specify a blacklist to exclude simplices from valid simplices.

spaudiopy.decoder.sort_vertices(simplices)[source]

Start the simplices with smallest vertex entry.

spaudiopy.decoder.find_imaginary_loudspeaker(hull)[source]

Find imaginary loudspeaker coordinates for smoother hull.

References

Zotter, F., & Frank, M. (2012). All-Round Ambisonic Panning and Decoding. Journal of Audio Engineering Society, Sec. 1.1.

spaudiopy.decoder.vbap(src, hull, norm=2, valid_simplices=None, retain_outside=False, jobs_count=1)[source]

Loudspeaker gains for Vector Base Amplitude Panning decoding.

Parameters:
  • src ((n, 3) numpy.ndarray) – Cartesian coordinates of n sources to be rendered.

  • hull (LoudspeakerSetup)

  • norm (non-zero int, float) – Gain normalization norm, e.g. 1: anechoic, 2: reverberant

  • valid_simplices ((nsimplex, 3) numpy.ndarray) – Valid simplices employed for rendering, defaults hull.valid_simplices.

  • retain_outside (bool, optional) – Render on the ‘ambisonic hull’ to fade out amplitude.

  • jobs_count (int or None, optional) – Number of parallel jobs, ‘None’ employs ‘cpu_count’.

Returns:

gains ((n, L) numpy.ndarray) – Panning gains for L loudspeakers to render n sources.

References

Pulkki, V. (1997). Virtual Sound Source Positioning Using Vector Base Amplitude Panning. AES, 144(5), 357–360.

Examples

ls_setup = spa.decoder.LoudspeakerSetup(ls_x, ls_y, ls_z)
ls_setup.pop_triangles(normal_limit=85, aperture_limit=90,
                       opening_limit=150)

spa.plot.decoder_performance(ls_setup, 'VBAP')

ls_setup.ambisonics_setup(update_hull=True)
spa.plot.decoder_performance(ls_setup, 'VBAP', retain_outside=True)
plt.suptitle('VBAP with imaginary loudspeaker')
_images/spaudiopy-decoder-4_00.png

(png, hires.png, pdf)

_images/spaudiopy-decoder-4_01.png

(png, hires.png, pdf)

spaudiopy.decoder.vbip(src, hull, norm=2, valid_simplices=None, retain_outside=False, jobs_count=1)[source]

Loudspeaker gains for Vector Base Intensity Panning decoding.

Parameters:
  • src ((n, 3) numpy.ndarray) – Cartesian coordinates of n sources to be rendered.

  • hull (LoudspeakerSetup)

  • norm (non-zero int, float) – Gain normalization norm, e.g. 1: anechoic, 2: reverberant

  • valid_simplices ((nsimplex, 3) numpy.ndarray) – Valid simplices employed for rendering, defaults hull.valid_simplices.

  • retain_outside (bool, optional) – Render on the ‘ambisonic hull’, amplitude will not fade out with VBIP.

  • jobs_count (int or None, optional) – Number of parallel jobs, ‘None’ employs ‘cpu_count’.

Returns:

gains ((n, L) numpy.ndarray) – Panning gains for L loudspeakers to render n sources.

Examples

ls_setup = spa.decoder.LoudspeakerSetup(ls_x, ls_y, ls_z)
ls_setup.pop_triangles(normal_limit=85, aperture_limit=90,
                       opening_limit=150)

spa.plot.decoder_performance(ls_setup, 'VBIP')

ls_setup.ambisonics_setup(update_hull=True)
spa.plot.decoder_performance(ls_setup, 'VBIP', retain_outside=True)
plt.suptitle('VBIP with imaginary loudspeaker')
_images/spaudiopy-decoder-5_00.png

(png, hires.png, pdf)

_images/spaudiopy-decoder-5_01.png

(png, hires.png, pdf)

spaudiopy.decoder.characteristic_ambisonic_order(hull)[source]

Find the characteristic order for specified loudspeaker layout.

References

Zotter, F., & Frank, M. (2012). All-Round Ambisonic Panning and Decoding. Journal of Audio Engineering Society, Sec. 7.

spaudiopy.decoder.allrap(src, hull, N_sph=None, jobs_count=1)[source]

Loudspeaker gains for All-Round Ambisonic Panning.

Parameters:
  • src ((N, 3)) – Cartesian coordinates of N sources to be rendered.

  • hull (LoudspeakerSetup)

  • N_sph (int) – Decoding order, defaults to hull.characteristic_order.

  • jobs_count (int or None, optional) – Number of parallel jobs, ‘None’ employs ‘cpu_count’.

Returns:

gains ((N, L) numpy.ndarray) – Panning gains for L loudspeakers to render N sources.

References

Zotter, F., & Frank, M. (2012). All-Round Ambisonic Panning and Decoding. Journal of Audio Engineering Society, Sec. 4.

Examples

ls_setup = spa.decoder.LoudspeakerSetup(ls_x, ls_y, ls_z)
ls_setup.pop_triangles(normal_limit=85, aperture_limit=90,
                       opening_limit=150)
ls_setup.ambisonics_setup(update_hull=True)

spa.plot.decoder_performance(ls_setup, 'ALLRAP')

(png, hires.png, pdf)

_images/spaudiopy-decoder-6.png
spaudiopy.decoder.allrap2(src, hull, N_sph=None, jobs_count=1)[source]

Loudspeaker gains for All-Round Ambisonic Panning 2.

Parameters:
  • src ((N, 3)) – Cartesian coordinates of N sources to be rendered.

  • hull (LoudspeakerSetup)

  • N_sph (int) – Decoding order, defaults to hull.characteristic_order.

  • jobs_count (int or None, optional) – Number of parallel jobs, ‘None’ employs ‘cpu_count’.

Returns:

gains ((N, L) numpy.ndarray) – Panning gains for L loudspeakers to render N sources.

References

Zotter, F., & Frank, M. (2018). Ambisonic decoding with panning-invariant loudness on small layouts (AllRAD2). In 144th AES Convention.

Examples

ls_setup = spa.decoder.LoudspeakerSetup(ls_x, ls_y, ls_z)
ls_setup.pop_triangles(normal_limit=85, aperture_limit=90,
                       opening_limit=150)
ls_setup.ambisonics_setup(update_hull=True)

spa.plot.decoder_performance(ls_setup, 'ALLRAP2')

(png, hires.png, pdf)

_images/spaudiopy-decoder-7.png
spaudiopy.decoder.allrad(F_nm, hull, N_sph=None, jobs_count=1)[source]

Loudspeaker signals of All-Round Ambisonic Decoder.

Parameters:
  • F_nm (((N_sph+1)**2, S) numpy.ndarray) – Matrix of spherical harmonics coefficients of spherical function(S).

  • hull (LoudspeakerSetup)

  • N_sph (int) – Decoding order.

  • jobs_count (int or None, optional) – Number of parallel jobs, ‘None’ employs ‘cpu_count’.

Returns:

ls_sig ((L, S) numpy.ndarray) – Loudspeaker L output signal S.

References

Zotter, F., & Frank, M. (2012). All-Round Ambisonic Panning and Decoding. Journal of Audio Engineering Society, Sec. 6.

Examples

ls_setup = spa.decoder.LoudspeakerSetup(ls_x, ls_y, ls_z)
ls_setup.pop_triangles(normal_limit=85, aperture_limit=90,
                       opening_limit=150)
ls_setup.ambisonics_setup(update_hull=True)

spa.plot.decoder_performance(ls_setup, 'ALLRAD')

(png, hires.png, pdf)

_images/spaudiopy-decoder-8.png
spaudiopy.decoder.allrad2(F_nm, hull, N_sph=None, jobs_count=1)[source]

Loudspeaker signals of All-Round Ambisonic Decoder 2.

Parameters:
  • F_nm (((N_sph+1)**2, S) numpy.ndarray) – Matrix of spherical harmonics coefficients of spherical function(S).

  • hull (LoudspeakerSetup)

  • N_sph (int) – Decoding order, defaults to hull.characteristic_order.

  • jobs_count (int or None, optional) – Number of parallel jobs, ‘None’ employs ‘cpu_count’.

Returns:

ls_sig ((L, S) numpy.ndarray) – Loudspeaker L output signal S.

References

Zotter, F., & Frank, M. (2018). Ambisonic decoding with panning-invariant loudness on small layouts (AllRAD2). In 144th AES Convention.

Examples

ls_setup = spa.decoder.LoudspeakerSetup(ls_x, ls_y, ls_z)
ls_setup.pop_triangles(normal_limit=85, aperture_limit=90,
                       opening_limit=150)
ls_setup.ambisonics_setup(update_hull=True)

spa.plot.decoder_performance(ls_setup, 'ALLRAD2')

(png, hires.png, pdf)

_images/spaudiopy-decoder-9.png
spaudiopy.decoder.sad(F_nm, hull, N_sph=None)[source]

Loudspeaker signals of Sampling Ambisonic Decoder.

Parameters:
  • F_nm (((N_sph+1)**2, S) numpy.ndarray) – Matrix of spherical harmonics coefficients of spherical function(S).

  • hull (LoudspeakerSetup)

  • N_sph (int) – Decoding order, defaults to hull.characteristic_order.

Returns:

ls_sig ((L, S) numpy.ndarray) – Loudspeaker L output signal S.

References

ch. 4.9.1, Zotter, F., & Frank, M. (2019). Ambisonics. Springer Topics in Signal Processing.

Examples

ls_setup = spa.decoder.LoudspeakerSetup(ls_x, ls_y, ls_z)
ls_setup.pop_triangles(normal_limit=85, aperture_limit=90,
                       opening_limit=150)

spa.plot.decoder_performance(ls_setup, 'SAD')

(png, hires.png, pdf)

_images/spaudiopy-decoder-10.png
spaudiopy.decoder.mad(F_nm, hull, N_sph=None)[source]

Loudspeaker signals of Mode-Matching Ambisonic Decoder.

Parameters:
  • F_nm (((N_sph+1)**2, S) numpy.ndarray) – Matrix of spherical harmonics coefficients of spherical function(S).

  • hull (LoudspeakerSetup)

  • N_sph (int) – Decoding order, defaults to hull.characteristic_order.

Returns:

ls_sig ((L, S) numpy.ndarray) – Loudspeaker L output signal S.

References

ch. 4.9.2, Zotter, F., & Frank, M. (2019). Ambisonics. Springer Topics in Signal Processing.

Examples

ls_setup = spa.decoder.LoudspeakerSetup(ls_x, ls_y, ls_z)
ls_setup.pop_triangles(normal_limit=85, aperture_limit=90,
                       opening_limit=150)

spa.plot.decoder_performance(ls_setup, 'MAD')

(png, hires.png, pdf)

_images/spaudiopy-decoder-11.png
spaudiopy.decoder.epad(F_nm, hull, N_sph=None)[source]

Loudspeaker signals of Energy-Preserving Ambisonic Decoder.

Parameters:
  • F_nm (((N_sph+1)**2, S) numpy.ndarray) – Matrix of spherical harmonics coefficients of spherical function(S).

  • hull (LoudspeakerSetup)

  • N_sph (int) – Decoding order, defaults to hull.characteristic_order.

Returns:

ls_sig ((L, S) numpy.ndarray) – Loudspeaker L output signal S.

Notes

Number of loudspeakers should be greater or equal than SH channels, i.e.

\[L \geq (N_{sph}+1)^2 .\]

References

Zotter, F., Pomberger, H., & Noisternig, M. (2012). Energy-preserving ambisonic decoding. Acta Acustica United with Acustica, 98(1), 37–47.

Examples

ls_setup = spa.decoder.LoudspeakerSetup(ls_x, ls_y, ls_z)
ls_setup.pop_triangles(normal_limit=85, aperture_limit=90,
                       opening_limit=150)

spa.plot.decoder_performance(ls_setup, 'EPAD')

spa.plot.decoder_performance(ls_setup, 'EPAD', N_sph=2,
                              title='$N_{sph}=2$')
_images/spaudiopy-decoder-12_00.png

(png, hires.png, pdf)

_images/spaudiopy-decoder-12_01.png

(png, hires.png, pdf)

spaudiopy.decoder.nearest_loudspeaker(src, hull)[source]

Loudspeaker gains for nearest loudspeaker selection (NLS) decoding, based on euclidean distance.

Parameters:
  • src ((N, 3)) – Cartesian coordinates of N sources to be rendered.

  • hull (LoudspeakerSetup)

Returns:

gains ((N, L) numpy.ndarray) – Panning gains for L loudspeakers to render N sources.

Examples

ls_setup = spa.decoder.LoudspeakerSetup(ls_x, ls_y, ls_z)
ls_setup.pop_triangles(normal_limit=85, aperture_limit=90,
                       opening_limit=150)

spa.plot.decoder_performance(ls_setup, 'NLS')

(png, hires.png, pdf)

_images/spaudiopy-decoder-13.png
spaudiopy.decoder.sh2bin(sig_nm, hrirs_nm)[source]

Spherical Harmonic Domain signals to binaural renderer.

Ambisonic signals as N3D - ACN, i.e. real valued SH (time) signals.

Parameters:
  • sig_nm (((N_sph+1)**2, S) numpy.ndarray) – Input signal (SHD / Ambisonics).

  • hrirs_nm ((2, (N_sph+1)**2, L)) – Decoding IRs matrix, 2: left,right (stacked), real coeffs, L taps.

Returns:

(2, S+L-1) numpy.ndarray – Left and Right (stacked) binaural output signals.

See also

spaudiopy.decoder.magls_bin()

MagLS binaural decoder.

spaudiopy.decoder.magls_bin(hrirs, N_sph, f_trans=None, hf_cont='avg', hf_delay=(0, 0))[source]

Magnitude Least-Squares (magLS) binaural decoder.

This binaural decoder renders the (least squares) binaural output below f_trans, while rendering a magnitude solution above.

Parameters:
  • hrirs (sig.HRIRs) – HRIR set.

  • N_sph (int) – Ambisonic (SH) order.

  • f_trans (float, optional) – Transition frequency between linear and magLS handling. The default is None, which sets it to ‘N_sph * 500’.

  • hf_cont ([‘delay’, ‘avg’, ‘angle’], optional) – High Frequency phase continuation method . The default is ‘avg’.

  • hf_delay ((2,), optional) – High frequency (additional) group delay in smpls. The default is (0, 0).

Raises:

ValueError – When passing not supported option.

Returns:

hrirs_mls_nm ((2, (N_sph+1)**2, L)) – Decoding IRs matrix, 2: left,right (stacked), real coeffs, L taps.

Notes

Details can be found in [1]. The iterative procedure in [2] suffers form HF dispersion (available by hf_cont=’delay’ and hf_delay=(0, 0)). This function offers multiple options to mitigate this issue. E.g. manually estimating and setting hf_delay, or estimating a phase difference on previous frequency bins which are then used to predict. This delta can be the spherical average hf_cont=’avg’, which offers an algorithmic way to estimate the global group delay. It can also be estimated per direction when hf_cont=’angle’, which is able to preserve group delay changes over the angle, however, might reintroduce more complexity again. For very low orders, there might be a slight tradeoff.

References

[1] Hold, C., Meyer-Kahlen, N., & Pulkki, V. (2023). Magnitude-Least-Squares Binaural Ambisonic Rendering with Phase Continuation. Fortschritte Der Akustik - DAGA. [2] Zotter, F., & Frank, M. (2019). Ambisonics. Springer Topics in Signal Processing.

See also

spaudiopy.decoder.sh2bin()

Decode Ambisonic streams to binaural.