def harmonicModelAnal(x, fs, w, N, H, t, nH, minf0, maxf0, f0et, harmDevSlope=0.01, minSineDur=0.02): # Analysis of a sound using the sinusoidal harmonic model # x: input sound, fs: sampling rate, w: analysis window, # N: FFT size (minimum 512), t: threshold in negative dB, # nH: maximum number of harmonics, minf0: minimum f0 frequency in Hz, # maxf0: maximim f0 frequency in Hz, # f0et: error threshold in the f0 detection (ex: 5), # harmDevSlope: slope of harmonic deviation # minSineDur: minimum length of harmonics # returns xhfreq, xhmag, xhphase: harmonic frequencies, magnitudes and phases hN = N / 2 # size of positive spectrum hM1 = int(math.floor((w.size + 1) / 2)) # half analysis window size by rounding hM2 = int(math.floor(w.size / 2)) # half analysis window size by floor x = np.append(np.zeros(hM2), x) # add zeros at beginning to center first window at sample 0 x = np.append(x, np.zeros(hM2)) # add zeros at the end to analyze last sample pin = hM1 # init sound pointer in middle of anal window pend = x.size - hM1 # last sample to start a frame fftbuffer = np.zeros(N) # initialize buffer for FFT w = w / sum(w) # normalize analysis window hfreqp = [] f0t = 0 f0stable = 0 while pin <= pend: x1 = x[pin - hM1 : pin + hM2] # select frame mX, pX = DFT.dftAnal(x1, w, N) # compute dft ploc = UF.peakDetection(mX, hN, t) # detect peak locations iploc, ipmag, ipphase = UF.peakInterp(mX, pX, ploc) # refine peak values ipfreq = fs * iploc / N f0t = UF.f0DetectionTwm(ipfreq, ipmag, f0et, minf0, maxf0, f0stable) # find f0 if ((f0stable == 0) & (f0t > 0)) or ((f0stable > 0) & (np.abs(f0stable - f0t) < f0stable / 5.0)): f0stable = f0t # consider a stable f0 if it is close to the previous one else: f0stable = 0 hfreq, hmag, hphase = UF.harmonicDetection( ipfreq, ipmag, ipphase, f0t, nH, hfreqp, fs, harmDevSlope ) # find harmonics hfreqp = hfreq if pin == hM1: xhfreq = np.array([hfreq]) xhmag = np.array([hmag]) xhphase = np.array([hphase]) else: xhfreq = np.vstack((xhfreq, np.array([hfreq]))) xhmag = np.vstack((xhmag, np.array([hmag]))) xhphase = np.vstack((xhphase, np.array([hphase]))) pin += H # advance sound pointer xhfreq = UF.cleaningSineTracks(xhfreq, round(fs * minSineDur / H)) return xhfreq, xhmag, xhphase
def sineModelAnal(x, fs, w, N, H, t, maxnSines = 100, minSineDur=.01, freqDevOffset=20, freqDevSlope=0.01): # Analysis of a sound using the sinusoidal model # x: input array sound, w: analysis window, N: size of complex spectrum, # H: hop-size, t: threshold in negative dB # maxnSines: maximum number of sines per frame # minSineDur: minimum duration of sines in seconds # freqDevOffset: minimum frequency deviation at 0Hz # freqDevSlope: slope increase of minimum frequency deviation # returns xtfreq, xtmag, xtphase: frequencies, magnitudes and phases of sinusoids hN = N/2 # size of positive spectrum hM1 = int(math.floor((w.size+1)/2)) # half analysis window size by rounding hM2 = int(math.floor(w.size/2)) # half analysis window size by floor x = np.append(np.zeros(hM2),x) # add zeros at beginning to center first window at sample 0 x = np.append(x,np.zeros(hM2)) # add zeros at the end to analyze last sample pin = hM1 # initialize sound pointer in middle of analysis window pend = x.size - hM1 # last sample to start a frame w = w / sum(w) # normalize analysis window tfreq = np.array([]) while pin<pend: # while input sound pointer is within sound x1 = x[pin-hM1:pin+hM2] # select frame mX, pX = DFT.dftAnal(x1, w, N) # compute dft ploc = UF.peakDetection(mX, hN, t) # detect locations of peaks pmag = mX[ploc] # get the magnitude of the peaks iploc, ipmag, ipphase = UF.peakInterp(mX, pX, ploc) # refine peak values by interpolation ipfreq = fs*iploc/float(N) tfreq, tmag, tphase = UF.sineTracking(ipfreq, ipmag, ipphase, tfreq, freqDevOffset, freqDevSlope) tfreq = np.resize(tfreq, min(maxnSines, tfreq.size)) tmag = np.resize(tmag, min(maxnSines, tmag.size)) tphase = np.resize(tphase, min(maxnSines, tphase.size)) jtfreq = np.zeros(maxnSines) jtmag = np.zeros(maxnSines) jtphase = np.zeros(maxnSines) jtfreq[:tfreq.size]=tfreq jtmag[:tmag.size]=tmag jtphase[:tphase.size]=tphase if pin == hM1: xtfreq = jtfreq xtmag = jtmag xtphase = jtphase else: xtfreq = np.vstack((xtfreq, jtfreq)) xtmag = np.vstack((xtmag, jtmag)) xtphase = np.vstack((xtphase, jtphase)) pin += H xtfreq = UF.cleaningSineTracks(xtfreq, round(fs*minSineDur/H)) return xtfreq, xtmag, xtphase