annotate Example VamPy plugins/PySpectralFeatures.py @ 11:4610f2b8477d

added pyRealTime object impl to host
author fazekasgy
date Mon, 16 Jun 2008 09:44:48 +0000
parents d2d36e7d2276
children 7d28bed0864e
rev   line source
fazekasgy@9 1 '''PySpectralFeatures.py - Example plugin demonstrates'''
fazekasgy@9 2 '''how to use the NumPy array interface and write Matlab style code.'''
fazekasgy@9 3
fazekasgy@9 4 from numpy import *
fazekasgy@9 5
fazekasgy@9 6 class PySpectralFeatures:
fazekasgy@9 7
fazekasgy@9 8 def __init__(self):
fazekasgy@9 9 self.m_imputSampleRate = 0.0
fazekasgy@9 10 self.m_stepSize = 0
fazekasgy@9 11 self.m_blockSize = 0
fazekasgy@9 12 self.m_channels = 0
fazekasgy@9 13 self.threshold = 0.00
fazekasgy@9 14 self.r = 2.0
fazekasgy@9 15
fazekasgy@9 16 def initialise(self,channels,stepSize,blockSize,inputSampleRate):
fazekasgy@9 17 self.m_channels = channels
fazekasgy@9 18 self.m_stepSize = stepSize
fazekasgy@9 19 self.m_blockSize = blockSize
fazekasgy@9 20 self.m_inputSampleRate = inputSampleRate
fazekasgy@9 21 #self.prevMag = ones((blockSize/2)-1) / ((blockSize/2)-1)
fazekasgy@9 22 self.prevMag = zeros((blockSize/2)-1)
fazekasgy@9 23 self.prevMag[0] = 1
fazekasgy@9 24
fazekasgy@9 25 return True
fazekasgy@9 26
fazekasgy@9 27 def getMaker(self):
fazekasgy@9 28 return 'VamPy Example Plugins'
fazekasgy@9 29
fazekasgy@9 30 def getName(self):
fazekasgy@9 31 return 'VamPy Spectral Features'
fazekasgy@9 32
fazekasgy@9 33 def getIdentifier(self):
fazekasgy@9 34 return 'vampy-sf2'
fazekasgy@9 35
fazekasgy@9 36 def getDescription(self):
fazekasgy@9 37 return 'A collection of low-level spectral descriptors.'
fazekasgy@9 38
fazekasgy@9 39 def getMaxChannelCount(self):
fazekasgy@9 40 return 1
fazekasgy@9 41
fazekasgy@9 42 def getInputDomain(self):
fazekasgy@9 43 return 'FrequencyDomain'
fazekasgy@9 44
fazekasgy@9 45 def getOutputDescriptors(self):
fazekasgy@9 46
fazekasgy@9 47 #descriptors are python dictionaries
fazekasgy@9 48 #Generic values are the same for all
fazekasgy@9 49 Generic={
fazekasgy@9 50 'hasFixedBinCount':True,
fazekasgy@9 51 'binCount':1,
fazekasgy@9 52 'hasKnownExtents':False,
fazekasgy@9 53 'isQuantized':False,
fazekasgy@9 54 'sampleType':'OneSamplePerStep'
fazekasgy@9 55 }
fazekasgy@9 56
fazekasgy@9 57 #Spectral centroid etc...
fazekasgy@9 58 SC=Generic.copy()
fazekasgy@9 59 SC.update({
fazekasgy@9 60 'identifier':'vampy-sc',
fazekasgy@9 61 'name':'Spectral Centroid',
fazekasgy@9 62 'description':'Spectral Centroid (Brightness)',
fazekasgy@9 63 'unit':'Hz'
fazekasgy@9 64 })
fazekasgy@9 65
fazekasgy@9 66 SCF=Generic.copy()
fazekasgy@9 67 SCF.update({
fazekasgy@9 68 'identifier':'vampy-scf',
fazekasgy@9 69 'name':'Spectral Crest Factor',
fazekasgy@9 70 'description':'Spectral Crest (Tonality)',
fazekasgy@9 71 'unit':'v'
fazekasgy@9 72 })
fazekasgy@9 73
fazekasgy@9 74 BW=Generic.copy()
fazekasgy@9 75 BW.update({
fazekasgy@9 76 'identifier':'vampy-bw',
fazekasgy@9 77 'name':'Band Width',
fazekasgy@9 78 'description':'Spectral Band Width',
fazekasgy@9 79 'unit':'Hz',
fazekasgy@9 80 })
fazekasgy@9 81
fazekasgy@9 82 SE=Generic.copy()
fazekasgy@9 83 SE.update({
fazekasgy@9 84 'identifier':'vampy-se',
fazekasgy@9 85 'name':'Shannon Entropy',
fazekasgy@9 86 'description':'Shannon Entropy',
fazekasgy@9 87 'unit':'',
fazekasgy@9 88 })
fazekasgy@9 89
fazekasgy@9 90 RE=Generic.copy()
fazekasgy@9 91 RE.update({
fazekasgy@9 92 'identifier':'vampy-re',
fazekasgy@9 93 'name':'Renyi Entropy',
fazekasgy@9 94 'description':'Renyi Entropy',
fazekasgy@9 95 'unit':'',
fazekasgy@9 96 })
fazekasgy@9 97
fazekasgy@9 98 KL=Generic.copy()
fazekasgy@9 99 KL.update({
fazekasgy@9 100 'identifier':'vampy-kl',
fazekasgy@9 101 'name':'Kullback Leibler divergence',
fazekasgy@9 102 'description':'KL divergence between successive spectra',
fazekasgy@9 103 'unit':'',
fazekasgy@9 104 })
fazekasgy@9 105
fazekasgy@9 106 #return a list of dictionaries
fazekasgy@9 107 return [SC,SCF,BW,SE,RE,KL]
fazekasgy@9 108
fazekasgy@9 109 def getParameterDescriptors(self):
fazekasgy@9 110 threshold={
fazekasgy@9 111 'identifier':'threshold',
fazekasgy@9 112 'name':'Noise threshold: ',
fazekasgy@9 113 'description':'',
fazekasgy@9 114 'unit':'v',
fazekasgy@9 115 'minValue':0.0,
fazekasgy@9 116 'maxValue':0.5,
fazekasgy@9 117 'defaultValue':0.05,
fazekasgy@9 118 'isQuantized':False
fazekasgy@9 119 }
fazekasgy@9 120
fazekasgy@9 121 renyicoeff={
fazekasgy@9 122 'identifier':'r',
fazekasgy@9 123 'name':'Renyi entropy coeff: ',
fazekasgy@9 124 'description':'',
fazekasgy@9 125 'unit':'',
fazekasgy@9 126 'minValue':0.0,
fazekasgy@9 127 'maxValue':10.0,
fazekasgy@9 128 'defaultValue':2,
fazekasgy@9 129 'isQuantized':False
fazekasgy@9 130 }
fazekasgy@9 131
fazekasgy@9 132 return [threshold,renyicoeff]
fazekasgy@9 133
fazekasgy@9 134 def setParameter(self,paramid,newval):
fazekasgy@9 135 if paramid == 'threshold' :
fazekasgy@9 136 self.threshold = newval
fazekasgy@9 137 if paramid == 'r' :
fazekasgy@9 138 self.r == newval
fazekasgy@9 139 return
fazekasgy@9 140
fazekasgy@9 141 def getParameter(self,paramid):
fazekasgy@9 142 if paramid == 'threshold' :
fazekasgy@9 143 return self.threshold
fazekasgy@9 144 if paramid == 'r':
fazekasgy@9 145 return float(self.r)
fazekasgy@9 146 else:
fazekasgy@9 147 return 0.0
fazekasgy@9 148
fazekasgy@9 149 def processN(self,membuffer,samplecount):
fazekasgy@9 150 fftsize = self.m_blockSize
fazekasgy@9 151 sampleRate = self.m_inputSampleRate
fazekasgy@9 152
fazekasgy@9 153 #for time domain plugins use the following line:
fazekasgy@9 154 #audioSamples = frombuffer(membuffer[0],float32)
fazekasgy@9 155 #-1: do till the end, skip DC 2*32bit / 8bit = 8byte
fazekasgy@9 156 complexSpectrum = frombuffer(membuffer[0],complex64,-1,8)
fazekasgy@9 157 magnitudeSpectrum = abs(complexSpectrum) / (fftsize/2)
fazekasgy@9 158 tpower = sum(magnitudeSpectrum)
fazekasgy@9 159 #phaseSpectrum = angle(complexSpectrum)
fazekasgy@9 160
fazekasgy@9 161 freq = array(range(1,len(complexSpectrum)+1)) \
fazekasgy@9 162 * sampleRate / fftsize
fazekasgy@9 163
fazekasgy@9 164 centroid = 0.0
fazekasgy@9 165 crest = 0.0
fazekasgy@9 166 bw = 0.0
fazekasgy@9 167 shannon = 0.0
fazekasgy@9 168 renyi = 0.0
fazekasgy@9 169 r = self.r
fazekasgy@9 170 KLdiv = 0.0
fazekasgy@9 171 flatness = 0.0
fazekasgy@9 172 exp=1.0 / (fftsize/2)
fazekasgy@9 173 #print exp
fazekasgy@9 174
fazekasgy@9 175 #declare outputs
fazekasgy@9 176 output0=[]
fazekasgy@9 177 output1=[]
fazekasgy@9 178 output2=[]
fazekasgy@9 179 output3=[]
fazekasgy@9 180 output4=[]
fazekasgy@9 181 output5=[]
fazekasgy@9 182
fazekasgy@9 183 if tpower > self.threshold :
fazekasgy@9 184
fazekasgy@9 185 centroid = sum(freq * magnitudeSpectrum) / tpower
fazekasgy@9 186 crest = max(magnitudeSpectrum) / tpower
fazekasgy@9 187 bw = sum( abs(freq - centroid) * magnitudeSpectrum ) / tpower
fazekasgy@9 188 #flatness = prod(abs(complexSpectrum))
fazekasgy@9 189 #print flatness
fazekasgy@9 190 normMag = magnitudeSpectrum / tpower #make it sum to 1
fazekasgy@9 191 shannon = - sum( normMag * log2(normMag) )
fazekasgy@9 192 renyi = (1/1-r) * log10( sum( power(normMag,r)))
fazekasgy@9 193 KLdiv = sum( normMag * log2(normMag / self.prevMag) )
fazekasgy@9 194 self.prevMag = normMag
fazekasgy@9 195
fazekasgy@9 196 output0.append({
fazekasgy@9 197 'hasTimestamp':False,
fazekasgy@9 198 'values':[float(centroid)],
fazekasgy@9 199 #'label':str(centroid)
fazekasgy@9 200 })
fazekasgy@9 201
fazekasgy@9 202 output1.append({
fazekasgy@9 203 'hasTimestamp':False,
fazekasgy@9 204 'values':[float(crest)],
fazekasgy@9 205 #'label':str(crest)
fazekasgy@9 206 })
fazekasgy@9 207
fazekasgy@9 208 output2.append({
fazekasgy@9 209 'hasTimestamp':False,
fazekasgy@9 210 'values':[float(bw)],
fazekasgy@9 211 #'label':str(bw)
fazekasgy@9 212 })
fazekasgy@9 213
fazekasgy@9 214 output3.append({
fazekasgy@9 215 'hasTimestamp':False,
fazekasgy@9 216 'values':[float(shannon)],
fazekasgy@9 217 #'label':str(shannon)
fazekasgy@9 218 })
fazekasgy@9 219
fazekasgy@9 220 output4.append({
fazekasgy@9 221 'hasTimestamp':False,
fazekasgy@9 222 'values':[float(renyi)],
fazekasgy@9 223 #'label':str(renyi)
fazekasgy@9 224 })
fazekasgy@9 225
fazekasgy@9 226 output5.append({
fazekasgy@9 227 'hasTimestamp':False,
fazekasgy@9 228 'values':[float(KLdiv)], #strictly must be a list
fazekasgy@9 229 #'label':str(renyi)
fazekasgy@9 230 })
fazekasgy@9 231
fazekasgy@9 232 #return a LIST of list of dictionaries
fazekasgy@9 233 return [output0,output1,output2,output3,output4,output5]