Mercurial > hg > vampy
view Example VamPy plugins/PySpectralFeatures.py @ 26:ba3686eb697c
examples now pass all tests
author | fazekasgy |
---|---|
date | Wed, 19 Aug 2009 15:21:17 +0000 |
parents | 7d28bed0864e |
children |
line wrap: on
line source
'''PySpectralFeatures.py - Example plugin demonstrates''' '''how to use the NumPy array interface and write Matlab style code.''' from numpy import * class PySpectralFeatures: def __init__(self,inputSampleRate): self.m_inputSampleRate = inputSampleRate self.m_stepSize = 0 self.m_blockSize = 0 self.m_channels = 0 self.threshold = 0.05 self.r = 2.0 return None def initialise(self,channels,stepSize,blockSize): self.m_channels = channels self.m_stepSize = stepSize self.m_blockSize = blockSize self.prevMag = zeros((blockSize/2)-1) self.prevMag[0] = 1 return True def reset(self): # reset any initial conditions self.prevMag = zeros((self.m_blockSize/2)-1) self.prevMag[0] = 1 return None def getMaker(self): return 'VamPy Example Plugins' def getName(self): return 'VamPy Spectral Features' def getIdentifier(self): return 'vampy-sf2' def getDescription(self): return 'A collection of low-level spectral descriptors.' def getMaxChannelCount(self): return 1 def getInputDomain(self): return 'FrequencyDomain' def getOutputDescriptors(self): #descriptors are python dictionaries #Generic values are the same for all Generic={ 'hasFixedBinCount':True, 'binCount':1, 'hasKnownExtents':False, 'isQuantized':False, 'sampleType':'OneSamplePerStep' } #Spectral centroid etc... SC=Generic.copy() SC.update({ 'identifier':'vampy-sc', 'name':'Spectral Centroid', 'description':'Spectral Centroid (Brightness)', 'unit':'Hz' }) SCF=Generic.copy() SCF.update({ 'identifier':'vampy-scf', 'name':'Spectral Crest Factor', 'description':'Spectral Crest (Tonality)', 'unit':'v' }) BW=Generic.copy() BW.update({ 'identifier':'vampy-bw', 'name':'Band Width', 'description':'Spectral Band Width', 'unit':'Hz', }) SE=Generic.copy() SE.update({ 'identifier':'vampy-se', 'name':'Shannon Entropy', 'description':'Shannon Entropy', 'unit':'', }) RE=Generic.copy() RE.update({ 'identifier':'vampy-re', 'name':'Renyi Entropy', 'description':'Renyi Entropy', 'unit':'', }) KL=Generic.copy() KL.update({ 'identifier':'vampy-kl', 'name':'Kullback Leibler divergence', 'description':'KL divergence between successive spectra', 'unit':'', }) #return a list of dictionaries return [SC,SCF,BW,SE,RE,KL] def getParameterDescriptors(self): threshold={ 'identifier':'threshold', 'name':'Noise threshold: ', 'description':'Noise threshold', 'unit':'v', 'minValue':0.0, 'maxValue':0.5, 'defaultValue':0.05, 'isQuantized':False } renyicoeff={ 'identifier':'r', 'name':'Renyi entropy coeff: ', 'description':'Renyi entropy coeff', 'unit':'', 'minValue':0.0, 'maxValue':10.0, 'defaultValue':2.0, 'isQuantized':False } return [threshold,renyicoeff] def setParameter(self,paramid,newval): if paramid == 'threshold' : self.threshold = newval if paramid == 'r' : self.r == newval return def getParameter(self,paramid): if paramid == 'threshold' : return self.threshold if paramid == 'r': return float(self.r) else: return 0.0 def processN(self,membuffer,samplecount): fftsize = self.m_blockSize sampleRate = self.m_inputSampleRate #for time domain plugins use the following line: #audioSamples = frombuffer(membuffer[0],float32) #for frequency domain plugins use the following line: complexSpectrum = frombuffer(membuffer[0],complex64,-1,8) #meaning of the parameters above: #-1: do until the end, skip DC 2*32bit / 8bit = 8byte magnitudeSpectrum = abs(complexSpectrum) / (fftsize/2) tpower = sum(magnitudeSpectrum) #phaseSpectrum = angle(complexSpectrum) freq = array(range(1,len(complexSpectrum)+1)) \ * sampleRate / fftsize centroid = 0.0 crest = 0.0 bw = 0.0 shannon = 0.0 renyi = 0.0 KLdiv = 0.0 exp=1.0 / (fftsize/2) #declare outputs output0=[] output1=[] output2=[] output3=[] output4=[] output5=[] if tpower > self.threshold : centroid = sum(freq * magnitudeSpectrum) / tpower crest = max(magnitudeSpectrum) / tpower bw = sum( abs(freq - centroid) * magnitudeSpectrum ) / tpower normMag = magnitudeSpectrum / tpower #make it sum to 1 shannon = - sum( normMag * log2(normMag) ) renyi = (1/1-self.r) * log10( sum( power(normMag,self.r))) KLdiv = sum( normMag * log2(normMag / self.prevMag) ) self.prevMag = normMag output0.append({ 'hasTimestamp':False, 'values':[float(centroid)], #'label':str(centroid) }) output1.append({ 'hasTimestamp':False, 'values':[float(crest)], #'label':str(crest) }) output2.append({ 'hasTimestamp':False, 'values':[float(bw)], #'label':str(bw) }) output3.append({ 'hasTimestamp':False, 'values':[float(shannon)], #'label':str(shannon) }) output4.append({ 'hasTimestamp':False, 'values':[float(renyi)], #'label':str(renyi) }) output5.append({ 'hasTimestamp':False, 'values':[float(KLdiv)], #strictly must be a list #'label':str(renyi) }) #return a LIST of list of dictionaries return [output0,output1,output2,output3,output4,output5]