Source code for mosqito.sq_metrics.roughness.roughness_dw.roughness_dw_freq

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

# Standard imports
from numpy import empty, arange, mean, tile

# Local imports
from mosqito.sq_metrics.roughness.roughness_dw._roughness_dw_main_calc import (
    _roughness_dw_main_calc,
)
from mosqito.sq_metrics.roughness.roughness_dw._gzi_weighting import _gzi_weighting
from mosqito.sq_metrics.roughness.roughness_dw._H_weighting import _H_weighting


[docs] def roughness_dw_freq(spectrum, freqs): """ Computes the roughness according to Daniel and Weber method from a fine band spectrum This function computes the global and specific roughness values of a signal sampled at 48 kHz. Parameters ---------- spectrum : array_like Input amplitude or complex frequency spectrum, dim (nperseg x nseg) freqs : array Input frequency axis , dim (nperseg) if identical for all the blocks, else (nperseg x nseg). Returns ------- R : numpy.array Roughness value in [asper], dim (nseg). R_spec : numpy.array Specific roughness over bark axis, dim (47 bark x nseg). bark_axis : numpy.array Frequency axis in [bark], dim (nseg). Warning ------- The input spectrum must be an amplitude spectrum (use abs() on complex spectrum). See Also -------- .roughness_dw : roughness computation from a time signal Notes ----- The model consists of a parallel processing structure made up of successive stages to calculate intermediate specific roughnesses :math:`R'`, which are summed up to determine the total roughness :math:`R`: .. math:: R=0.25\\sum_{i=1}^{47}R'_{i} References ---------- :cite:empty:`R-roughnessDW` .. bibliography:: :keyprefix: R- Examples -------- .. plot:: :include-source: >>> from mosqito.sq_metrics import roughness_dw_freq >>> from mosqito.sound_level_meter import comp_spectrum >>> import matplotlib.pyplot as plt >>> import numpy as np >>> fc=1000 >>> fmod=70 >>> fs=44100 >>> d=0.2 >>> dB=60 >>> time = np.arange(0, d, 1/fs) >>> stimulus = ( >>> 0.5 >>> * (1 + np.sin(2 * np.pi * fmod * time)) >>> * np.sin(2 * np.pi * fc * time)) >>> rms = np.sqrt(np.mean(np.power(stimulus, 2))) >>> ampl = 0.00002 * np.power(10, dB / 20) / rms >>> stimulus = stimulus * ampl >>> n = len(stimulus) >>> spec, freqs = comp_spectrum(stimulus, fs, db=False) >>> R, R_specific, bark = roughness_dw_freq(spec, freqs) >>> plt.plot(bark, R_specific) >>> plt.xlabel("Bark axis [Bark]") >>> plt.ylabel("Specific roughness, [Asper/Bark]") >>> plt.title("Roughness = " + f"{R:.2f}" + " [Asper]") """ # Check input size coherence if len(spectrum) != len(freqs): raise ValueError("Input spectrum and frequency axis must have the same size !") if spectrum.any() < 0: raise ValueError( "Input must be an amplitude spectrum (use abs() on complex spectrum)." ) # 1D spectrum if len(spectrum.shape) == 1: nperseg = len(spectrum) nseg = 1 fs = int(2 * nperseg * mean(freqs[1:] - freqs[:-1])) # 2D spectrum elif len(spectrum.shape) > 1: nperseg = spectrum.shape[0] nseg = spectrum.shape[1] # one frequency axis per block if len(freqs.shape) > 1: fs = int(2 * nperseg * mean(freqs[0, 1:] - freqs[0, :-1])) # one frequency axis for all the blocks elif len(freqs.shape) == 1: fs = int(2 * nperseg * mean(freqs[1:] - freqs[:-1])) freqs = tile(freqs, (nseg, 1)).T # Initialization of the weighting functions H and g hWeight = _H_weighting(2 * nperseg, fs) # Aures modulation depth weighting function gzi = _gzi_weighting(arange(1, 48, 1) / 2) if len(spectrum.shape) > 1: R = empty((nseg)) R_spec = empty((47, nseg)) for i in range(nseg): R[i], R_spec[:, i], bark_axis = _roughness_dw_main_calc( spectrum[:, i], freqs[:, i], fs, gzi, hWeight ) else: R, R_spec, bark_axis = _roughness_dw_main_calc( spectrum, freqs, fs, gzi, hWeight ) return R, R_spec, bark_axis
if __name__ == "__main__": from mosqito.sq_metrics import roughness_dw_freq from mosqito.sound_level_meter import comp_spectrum import matplotlib.pyplot as plt import numpy as np fc = 1000 fmod = 70 fs = 44100 d = 0.2 dB = 60 time = np.arange(0, d, 1 / fs) stimulus = ( 0.5 * (1 + np.sin(2 * np.pi * fmod * time)) * np.sin(2 * np.pi * fc * time) ) rms = np.sqrt(np.mean(np.power(stimulus, 2))) ampl = 0.00002 * np.power(10, dB / 20) / rms stimulus = stimulus * ampl n = len(stimulus) spec, freqs = comp_spectrum(stimulus, fs, db=False) R, R_specific, bark = roughness_dw_freq(spec, freqs) plt.plot(bark, R_specific) plt.xlabel("Bark axis [Bark]") plt.ylabel("Specific roughness, [Asper/Bark]") plt.title("Roughness = " + f"{R:.2f}" + " [Asper]") plt.show(block=True)