Source code for mosqito.sq_metrics.loudness.loudness_zwtv.loudness_zwtv

# -*- coding: utf-8 -*-

# Standard library imports
from numpy import linspace

# Local applications imports
from mosqito.sq_metrics.loudness.loudness_zwst._main_loudness import _main_loudness
from mosqito.sq_metrics.loudness.loudness_zwst._calc_slopes import _calc_slopes
from mosqito.sq_metrics.loudness.loudness_zwtv._nonlinear_decay import _nl_loudness
from mosqito.sq_metrics.loudness.loudness_zwtv._temporal_weighting import (
    _temporal_weighting,
)
from mosqito.sq_metrics.loudness.loudness_zwtv._third_octave_levels import (
    _third_octave_levels,
)


[docs] def loudness_zwtv(signal, fs, field_type="free"): """ Returns the loudness value from a time signal This function computes the acoustic loudness according to Zwicker method for time-varying signals (ISO.532-1:2017). Parameters ---------- signal : numpy.array A time signal values [Pa]. fs : integer Sampling frequency, can be omitted if the input is a DataTime object. Default to None field_type : {'free', 'diffuse'} Type of soundfield. Default is 'free' Outputs Returns ------- N : float Overall loudness [sones], size (Ntime,). N_specific : numpy.ndarray Specific loudness [sones/bark], size (Nbark, Ntime). bark_axis : numpy.ndarray Bark axis, size (Nbark,). time_axis : numpy.ndarray Time axis, size (Ntime,). Warning ------- The sampling frequency of the signal must be >= 48 kHz to fulfill requirements. If the provided signal doesn't meet the requirements, it will be resampled. See Also -------- .loudness_zwst : Loudness computation for a stationary time signal .loudness_zwst_perseg : Loudness computation by time-segment .loudness_zwst_freq : Loudness computation from a sound spectrum Notes ----- For each time frame considered, the total loudness :math:`N` is computed as the integral of the specific loudness :math:`N'` measured in sone/bark, over the Bark scale. The values of specific loudness are evaluated from third octave band levels as function of critical band rate :math:`z` in Bark. The calculation includes the mutual effects that a time window can have on its neighbors. .. math:: N=\\int_{0}^{24Bark}N'(z)\\textup{dz} Due to normative continuity, the method is in accordance with ISO 226:1987 equal loudness contours instead of ISO 226:2003, as defined in the following standards: * ISO 532:1975 (method B) * DIN 45631:1991 * ISO 532-1:2017 (method 1) References ---------- :cite:empty:`L_zw-ZF91` .. bibliography:: :keyprefix: L_zw- Examples -------- .. plot:: :include-source: >>> from mosqito.sq_metrics import loudness_zwtv >>> import matplotlib.pyplot as plt >>> import numpy as np >>> fs=48000 >>> d=1 >>> dB=60 >>> time = np.arange(0, d, 1/fs) >>> f = np.linspace(1000,5000, len(time)) >>> stimulus = 0.5 * (1 + np.sin(2 * np.pi * f * time)) >>> rms = np.sqrt(np.mean(np.power(stimulus, 2))) >>> ampl = 0.00002 * np.power(10, dB / 20) / rms >>> stimulus = stimulus * ampl >>> N, N_spec, bark_axis, time_axis = loudness_zwtv(stimulus, fs) >>> plt.plot(time_axis, N) >>> plt.xlabel("Time [s]") >>> plt.ylabel("Loudness [Sone]") """ if fs < 48000: print( "[Warning] Signal resampled to 48 kHz to allow calculation. To fulfill the standard requirements fs should be >=48 kHz." ) from scipy.signal import resample signal = resample(signal, int(48000 * len(signal) / fs)) fs = 48000 # Compute third octave band spectrum vs. time spec_third, time_axis, _ = _third_octave_levels(signal, fs) # Calculate core loudness (vectorized version) core_loudness = _main_loudness(spec_third, field_type) # # Nonlinearity core_loudness = _nl_loudness(core_loudness) # # Calculation of specific loudness loudness, spec_loudness = _calc_slopes(core_loudness) # temporal weigthing filt_loudness = _temporal_weighting(loudness) # # Decimation from temporal resolution 0.5 ms to 2ms and return dec_factor = 4 N = filt_loudness[::dec_factor] N_spec = spec_loudness[:, ::dec_factor] time_axis = time_axis[::dec_factor] # # Build bark axis bark_axis = linspace(0.1, 24, int(24 / 0.1)) return N, N_spec, bark_axis, time_axis