import numpy as np from scipy.fft import fft import soundfile as sf from numpy import log10 import math # Average Noise Spectral Level def ANSL(u, fs, M, A=0, N=None, D=None, w=None): """ :param u: Voltage data (Unit: V) :param fs: Sampling rate (Unit: Hz) :param M: Sensitivity (Unit: dBV re 1uPa) :param A: Preamplifier (Unit: dB) :param N: Segment length :param D: Overlap length :param w: Window :return: Spectral level """ L = len(u) if N == None: if L >= fs: N = round(fs) else: N = L elif N > L: raise Exception("Segment length is larger than data length.") if D == None: D = 0 if w is None: w = np.hamming(N) G = np.mean(np.square(abs(w))) K = 1 + math.floor((L-N) / (N-D)) T = N / fs df = 1 / T X2 = np.zeros(N) for k in range(K): X = fft(w * u[round(k*(N-D)):round(k*(N-D)+N)]) X2 += np.square(abs(X)) spl = 10 * log10(X2) - 10 * log10(N*fs*G*K/2) - M - A freq = np.arange(0, fs/2, df) spl = spl[0:len(freq)] return freq, spl # 1/3 Octave Spectral Level def OneThirdOct_SPL(freq, spl, f_start, Npoints): """ :param freq: Frequency :param spl: 1 Hz bandwidth spectral level :param f_start: Starting frequency of the 1/3 octave :param Npoints: The number of frequency points :return: 1/3 Octave Spectral Level """ fC = f_start * np.power(2, np.arange(Npoints)/3) fL = f_start * np.power(2, np.arange(Npoints)/3 - 1.0/6) fH = f_start * np.power(2, np.arange(Npoints)/3 + 1.0/6) spl_oct = np.zeros(Npoints) for it in range(Npoints): # idx = (freq >= fL[it]) & (freq <= fH[it]) idx = np.where((freq >= fL[it]) & (freq <= fH[it])) # print(idx) # print(spl[idx]) spl_oct[it] = 10 * log10(np.mean(np.power(10, spl[idx]/10))) # print(spl_oct[it]) return fC, spl_oct def call_oanp(soundFile, M, A=0): [x, fs] = sf.read(soundFile) u = 3 * x # Voltage data # M = -164.0 # Sensitivity # A = 0 # Preamplifier N = fs # Segment length D = N/2 # Overlap length w = np.hanning(N) # Window # Average Noise Spectral Level [freq, spl] = ANSL(u, fs, M, A, N, D, w) # 1/3 Octave Spectral Level [fC, spl_oct] = OneThirdOct_SPL(freq, spl, f_start=20, Npoints=28) return [freq, spl, fC, spl_oct]