Source code for mosqito.sound_level_meter.noct_spectrum.noct_synthesis

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

# Standard library import
from numpy import asarray, delete, array, where

# Local application imports
from mosqito.sound_level_meter.noct_spectrum._center_freq import _center_freq
from mosqito.sound_level_meter.noct_spectrum._filter_bandwidth import _filter_bandwidth
from mosqito.sound_level_meter.noct_spectrum._n_oct_freq_filter import _n_oct_freq_filter

[docs] def noct_synthesis(spectrum, freqs, fmin, fmax, n=3, G=10, fr=1000): """Adapt input spectrum to nth-octave band spectrum This function the input spectrum to n-th octave band levels. Parameters ---------- spectrum : array_like RMS amplitude one-sided spectrum, size (nperseg, nseg). freqs : list List of input frequency , size (nperseg) or (nperseg, nseg). fmin : float Minimum frequency band [Hz]. fmax : float Maximum frequency band [Hz]. n : int Number of bands per octave. G : int System for specifying the exact geometric mean frequencies. Can be base 2 or base 10. fr : int Reference frequency. Shall be set to 1 kHz for audible frequency range, to 1 Hz for infrasonic range (f < 20 Hz) and to 1 MHz for ultrasonic range (f > 31.5 kHz). Returns ------- spec : numpy.ndarray nth-octave octave band spectrum of signal sig [dB re.2e-5 Pa], size (nbands, nseg). fpref : numpy.ndarray Corresponding preferred nth-octave octave band center frequencies, size (nbands). See Also -------- .comp_spectrum : Spectrum computation from a time signal .noct_spectrum : N-th octave band spectrum computation from a time signal Examples -------- .. plot:: :include-source: >>> from mosqito.sound_level_meter import comp_spectrum, noct_synthesis >>> from mosqito.utils import amp2db >>> import matplotlib.pyplot as plt >>> import numpy as np >>> f=1000 >>> fs=48000 >>> d=0.2 >>> dB=60 >>> time = np.arange(0, d, 1/fs) >>> stimulus = np.sin(2 * np.pi * f * time) + 0.5 * np.sin(6 * 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 >>> spec, freqs = comp_spectrum(stimulus, fs, db=False) >>> spec_3, freq_axis = noct_synthesis(spec, freqs, fmin=90, fmax=14000) >>> spec_3db = amp2db(spec_3, ref=2e-5) >>> plt.step(freq_axis, spec_3db) >>> plt.xlabel("Center frequency [Hz]") >>> plt.ylabel("Amplitude [dB]") """ # Deduce sampling frequency fs = freqs.max() * 2 # Sampling frequency shall be equal to 48 kHz (as per ISO 532) if round(fs) != 48000: raise ValueError("""ERROR: Sampling frequency shall be equal to 48 kHz""") # Get filters center frequencies fc_vec, fpref = _center_freq(fmin=fmin, fmax=fmax, n=n, G=G, fr=fr) # Compute the filters bandwidth alpha_vec, f_low, f_high = _filter_bandwidth(fc_vec, n=n) # Delete ends frequencies to prevent aliasing idx = asarray(where(f_high > fs / 2)) if any(idx[0]): fc_vec = delete(fc_vec, idx) f_low = delete(f_low, idx) f_high = delete(f_high, idx) # Calculation of the rms level of the signal in each band spec = [] for fc, alpha in zip(fc_vec, alpha_vec): spec.append(_n_oct_freq_filter(spectrum, fs, fc, alpha)) return array(spec), fpref