|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | + |
| 3 | +# Standard library import |
| 4 | +from numpy import array, concatenate, zeros, log10, power, argmin, split, arange, interp, iscomplex |
| 5 | + |
| 6 | +def freq_band_synthesis(spectrum, freqs, fmin, fmax): |
| 7 | + """Adapt input spectrum to frequency band levels |
| 8 | + |
| 9 | + Convert the input spectrum to frequency band spectrum |
| 10 | + between "fmin" and "fmax". |
| 11 | + |
| 12 | + Parameters |
| 13 | + ---------- |
| 14 | + spectrum : numpy.ndarray |
| 15 | + One-sided spectrum of the signal in [dB], size (nperseg, nseg). |
| 16 | + freqs : list |
| 17 | + List of input frequency , size (nperseg) or (nperseg, nseg). |
| 18 | + fmin : float |
| 19 | + Min frequency band [Hz]. |
| 20 | + fmax : float |
| 21 | + Max frequency band [Hz]. |
| 22 | + n : int |
| 23 | + Number of bands pr octave. |
| 24 | + G : int |
| 25 | + System for specifying the exact geometric mean frequencies. |
| 26 | + Can be base 2 or base 10. |
| 27 | + fr : int |
| 28 | + Reference frequency. Shall be set to 1 kHz for audible frequency |
| 29 | + range, to 1 Hz for infrasonic range (f < 20 Hz) and to 1 MHz for |
| 30 | + ultrasonic range (f > 31.5 kHz). |
| 31 | + Outputs |
| 32 | + ------- |
| 33 | + spec : numpy.ndarray |
| 34 | + Third octave band spectrum of signal sig [dB re.2e-5 Pa], size (nbands, nseg). |
| 35 | + fpref : numpy.ndarray |
| 36 | + Corresponding preferred third octave band center frequencies, size (nbands). |
| 37 | + """ |
| 38 | + if iscomplex(spectrum).any(): |
| 39 | + raise ValueError('Input spectrum must be in dB, no complex value allowed.') |
| 40 | + |
| 41 | + if (fmin.min() < freqs.min()): |
| 42 | + print("[WARNING] Input spectrum minimum frequency if higher than fmin. Empty values will be filled with 0.") |
| 43 | + df = freqs[1] - freqs[0] |
| 44 | + spectrum = interp(arange(fmin.min(),fmax.max()+df, df), freqs, spectrum) |
| 45 | + freqs = arange(fmin.min(),fmax.max()+df, df) |
| 46 | + |
| 47 | + if (fmax.max() > freqs.max()): |
| 48 | + print("[WARNING] Input spectrum maximum frequency if lower than fmax. Empty values will be filled with 0.") |
| 49 | + df = freqs[1] - freqs[0] |
| 50 | + spectrum = interp(arange(fmin.min(),fmax.max()+df, df), freqs, spectrum) |
| 51 | + freqs = arange(fmin.min(),fmax.max()+df, df) |
| 52 | + |
| 53 | + # Find the lower and upper index of each band |
| 54 | + idx_low = argmin(abs(freqs[:,None] - fmin), axis=0) |
| 55 | + idx_up = argmin(abs(freqs[:,None] - fmax), axis=0) |
| 56 | + idx = concatenate((idx_low, [idx_up[-1]])) |
| 57 | + |
| 58 | + # Split the given spectrum in several bands |
| 59 | + bands = array(split(spectrum, idx), dtype=object)[1:-1] |
| 60 | + |
| 61 | + # Compute the bands level |
| 62 | + band_spectrum = zeros((len(bands))) |
| 63 | + i = 0 |
| 64 | + for s in bands: |
| 65 | + band_spectrum[i] = 10*log10(sum(power(10,s/10))) |
| 66 | + i += 1 |
| 67 | + |
| 68 | + return band_spectrum, (fmin+fmax)/2 |
| 69 | + |
| 70 | + |
| 71 | + |
| 72 | + |
| 73 | + |
| 74 | + |
0 commit comments