Maria@4: # -*- coding: utf-8 -*- Maria@4: """ Maria@4: Created on Mon Aug 17 13:37:00 2015 Maria@4: Maria@4: @author: mariapanteli Maria@4: """ Maria@4: Maria@4: import librosa Maria@4: import scipy.signal Maria@4: # import matplotlib.pyplot as plt Maria@4: import numpy Maria@4: Maria@4: class OPMellin: Maria@4: def __init__(self, win2sec=8): Maria@4: self.y = None Maria@4: self.sr = None Maria@4: self.melspec = None Maria@4: self.melsr = None Maria@4: self.op = None Maria@4: self.opmellin = None Maria@4: self.win2sec = win2sec Maria@4: Maria@4: def load_audiofile(self, filename='test.wav', sr=None, segment=True): Maria@4: self.y, self.sr = librosa.load(filename, sr=sr) Maria@4: #self.y, self.sr = librosa.load(filename) # default sr=22050 Maria@4: if segment: Maria@4: tracklength = self.y.shape[0]/float(self.sr) Maria@4: startSample = 0 Maria@4: endSample = None Maria@4: if tracklength > 90: Maria@4: startPointSec = (tracklength/2.)-20 Maria@4: startSample = round(startPointSec*self.sr) Maria@4: endSample = startSample+45*self.sr Maria@4: self.y = self.y[startSample:endSample] Maria@4: Maria@4: Maria@4: # def mel_spectrogram(self, y=None, sr=None, filename='1_21.wav'): Maria@4: def mel_spectrogram(self, y=None, sr=None): Maria@4: if self.y is None: Maria@4: self.y = y Maria@4: if self.sr is None: Maria@4: self.sr = sr Maria@4: win1 = int(round(0.04*self.sr)) Maria@4: hop1 = int(round(win1/8.)) Maria@4: nfft1 = int(2**numpy.ceil(numpy.log2(win1))) Maria@4: nmels = 40 Maria@4: # y, sr = librosa.load(filename, sr=fs) Maria@4: # melspec = librosa.feature.melspectrogram(y=y, sr=sr, n_fft=nfft, win_length=win1, window=scipy.signal.hamming, hop_length=hop1, n_mels=nmels) Maria@4: # melspec = librosa.feature.melspectrogram(y=self.y, sr=self.sr, n_fft=nfft, hop_length=hop1, n_mels=nmels) Maria@4: D = numpy.abs(librosa.stft(self.y, n_fft=nfft1, hop_length=hop1, win_length=win1, window=scipy.signal.hamming))**2 Maria@4: #melspec = librosa.feature.melspectrogram(S=D, sr=self.sr, n_mels=nmels) Maria@4: melspec = librosa.feature.melspectrogram(S=D, sr=self.sr, n_mels=nmels, fmax=8000) Maria@4: melsr = self.sr/float(hop1) Maria@4: # librosa.display.specshow(melspec) Maria@4: # return melspec, melsr Maria@4: self.melspec = melspec Maria@4: self.melsr = melsr Maria@4: Maria@4: # post process spectrogram Maria@4: def post_process_spec(self, melspec=None, log=True, medianfilt=False, sqrt=False, smooth=False, diff=True, subtractmean=True, halfwave=True, maxnormal=True): Maria@4: if self.melspec is None: Maria@4: self.melspec = melspec Maria@4: if log: Maria@4: self.melspec = librosa.logamplitude(self.melspec) Maria@4: if medianfilt: Maria@4: ks = int(0.1 * self.melsr) # 100ms kernel size Maria@4: if ks % 2 == 0: # ks must be odd Maria@4: ks += 1 Maria@4: nmels = self.melspec.shape[0] Maria@4: for i in range(nmels): Maria@4: self.melspec[i,:] = scipy.signal.medfilt(self.melspec[i,:],kernel_size = ks) Maria@4: if sqrt: Maria@4: self.melspec = self.melspec**.5 Maria@4: if smooth: Maria@4: step = 50.0 Maria@4: nmels = self.melspec.shape[0] Maria@4: mm = self.melspec Maria@4: for i in range(nmels): Maria@4: mm[i,:] = numpy.convolve(mm[i,:], numpy.ones(step)/step, mode='same') Maria@4: self.melspec = mm Maria@4: if diff: Maria@4: self.melspec = numpy.concatenate((self.melspec,self.melspec[:,-1,None]),axis=1) # append one frame before diff to keep number of frames the same Maria@4: self.melspec = numpy.diff(self.melspec, n=1, axis=1) Maria@4: if subtractmean: Maria@4: mean = self.melspec.mean(axis=1) Maria@4: mean.shape = (mean.shape[0], 1) Maria@4: self.melspec = self.melspec - mean Maria@4: if halfwave: Maria@4: self.melspec[numpy.where(self.melspec < 0)] = 0 Maria@4: if maxnormal: Maria@4: if self.melspec.max() != 0: # avoid division by 0 Maria@4: self.melspec = self.melspec/self.melspec.max() Maria@4: # return melspec Maria@4: Maria@4: Maria@4: def onset_patterns(self, melspec=None, melsr=None, fft=True, logfilter=False, center=True, bpmrange=True): Maria@4: if self.melspec is None: Maria@4: self.melspec = melspec Maria@4: if self.melsr is None: Maria@4: self.melsr = melsr Maria@4: win2 = int(round(self.win2sec*self.melsr)) Maria@4: hop2 = int(round(0.5*self.melsr)) Maria@4: nmels, nmelframes = self.melspec.shape Maria@4: if fft: # periodicity via fft Maria@4: #nfft2 = int(2**numpy.ceil(numpy.log2(win2))) Maria@4: nfft2 = 2048 # nfft2 does not depend on win2?? Maria@4: melspectemp = self.melspec Maria@4: if ((nfft2 > win2) and (center is False)): Maria@4: # pad the signal by nfft2-win2 so that frame decomposition (n_frames) Maria@4: # is still based on win2 and not nfft2 Maria@4: melspectemp = numpy.concatenate([numpy.zeros((nmels,int((nfft2 - win2) // 2))),self.melspec, numpy.zeros((nmels,int((nfft2 - win2) // 2)))],axis=1) Maria@4: if melspectemp.shape[1]