annotate Example VamPy plugins/PySpectralCentroid.py @ 53:7e59caea821b

* Make a better job of preloading Python, especially when it's in a framework. Go for the Python file in the frameworks directory in preference to any libpythonX.Y.dylib. Particularly, don't try to preload any library without an absolute path until we've exhausted all our framework possibilities (so as to avoid picking up an ancient system library).
author cannam
date Fri, 09 Oct 2009 13:48:25 +0000
parents d56f48aafb99
children 44d56a3d16b7
rev   line source
fazekasgy@52 1 '''PySpectralCentroid.py - Example plugin demonstrates
fazekasgy@52 2 how to write a C style plugin using VamPy in pure Python.
fazekasgy@52 3 This plugin also introduces the use of the builtin vampy
fazekasgy@52 4 extension module.
fazekasgy@52 5
fazekasgy@52 6 The plugin has frequency domain input and is using the
fazekasgy@52 7 legacy interface: the FFT outpout is passed as a list
fazekasgy@52 8 of complex numbers.
fazekasgy@52 9
fazekasgy@52 10 Outputs:
fazekasgy@52 11 1) Spectral centroid
fazekasgy@52 12
fazekasgy@52 13 Note: This is not the adviced way of writing Vampy plugins now,
fazekasgy@52 14 since the interfaces provided for Numpy are at least 5 times
fazekasgy@52 15 faster. However, this is still a nice and easy to understand
fazekasgy@52 16 example, which also shows how can one write a reasonable
fazekasgy@52 17 plugin without having Numpy installed.
fazekasgy@52 18
fazekasgy@52 19 Warning: Earlier versions of this plugin are now obsolete.
fazekasgy@52 20 (They were using the legacy interface of Vampy 1 which
fazekasgy@52 21 did not distinquish between time and frequency domain inputs.)
fazekasgy@52 22
fazekasgy@52 23 Centre for Digital Music, Queen Mary University of London.
fazekasgy@52 24 Copyright (C) 2009 Gyorgy Fazekas, QMUL. (See Vamp sources
fazekasgy@52 25 for licence information.)
fazekasgy@52 26
fazekasgy@52 27 '''
fazekasgy@52 28
fazekasgy@52 29 # import the names we use from vampy
fazekasgy@52 30 from vampy import Feature,FeatureSet,ParameterDescriptor
fazekasgy@52 31 from vampy import OutputDescriptor,FrequencyDomain,OneSamplePerStep
fazekasgy@52 32
fazekasgy@52 33 from math import sqrt
fazekasgy@52 34
fazekasgy@52 35 class PySpectralCentroid:
fazekasgy@52 36
fazekasgy@52 37 def __init__(self,inputSampleRate):
fazekasgy@52 38 self.m_imputSampleRate = 0.0
fazekasgy@52 39 self.m_stepSize = 0
fazekasgy@52 40 self.m_blockSize = 0
fazekasgy@52 41 self.m_channels = 0
fazekasgy@52 42 self.previousSample = 0.0
fazekasgy@52 43 self.m_inputSampleRate = inputSampleRate
fazekasgy@52 44 self.threshold = 0.00
fazekasgy@52 45
fazekasgy@52 46 def initialise(self,channels,stepSize,blockSize):
fazekasgy@52 47 self.m_channels = channels
fazekasgy@52 48 self.m_stepSize = stepSize
fazekasgy@52 49 self.m_blockSize = blockSize
fazekasgy@52 50 return True
fazekasgy@52 51
fazekasgy@52 52 def getMaker(self):
fazekasgy@52 53 return 'Vampy Example Plugins'
fazekasgy@52 54
fazekasgy@52 55 def getName(self):
fazekasgy@52 56 return 'Spectral Centroid (using legacy process interface)'
fazekasgy@52 57
fazekasgy@52 58 def getIdentifier(self):
fazekasgy@52 59 return 'vampy-sc3'
fazekasgy@52 60
fazekasgy@52 61 def getMaxChannelCount(self):
fazekasgy@52 62 return 1
fazekasgy@52 63
fazekasgy@52 64 def getInputDomain(self):
fazekasgy@52 65 return FrequencyDomain
fazekasgy@52 66
fazekasgy@52 67 def getOutputDescriptors(self):
fazekasgy@52 68
fazekasgy@52 69 cod = OutputDescriptor()
fazekasgy@52 70 cod.identifier='vampy-sc3'
fazekasgy@52 71 cod.name='Spectral Centroid'
fazekasgy@52 72 cod.description='Spectral Centroid (Brightness)'
fazekasgy@52 73 cod.unit=''
fazekasgy@52 74 cod.hasFixedBinCount=True
fazekasgy@52 75 cod.binCount=1
fazekasgy@52 76 cod.hasKnownExtents=False
fazekasgy@52 77 cod.isQuantized=True
fazekasgy@52 78 cod.quantizeStep=1.0
fazekasgy@52 79 cod.sampleType=OneSamplePerStep
fazekasgy@52 80 return cod
fazekasgy@52 81
fazekasgy@52 82 def getParameterDescriptors(self):
fazekasgy@52 83 thd = ParameterDescriptor()
fazekasgy@52 84 thd.identifier='threshold'
fazekasgy@52 85 thd.name='Noise threshold'
fazekasgy@52 86 thd.description='Return null or delete this function if not needed.'
fazekasgy@52 87 thd.unit='v'
fazekasgy@52 88 thd.minValue=0.0
fazekasgy@52 89 thd.maxValue=0.5
fazekasgy@52 90 thd.defaultValue=0.05
fazekasgy@52 91 thd.isQuantized=False
fazekasgy@52 92 return thd
fazekasgy@52 93
fazekasgy@52 94 def setParameter(self,paramid,newval):
fazekasgy@52 95 if paramid == 'threshold' :
fazekasgy@52 96 self.threshold = newval
fazekasgy@52 97 return
fazekasgy@52 98
fazekasgy@52 99 def getParameter(self,paramid):
fazekasgy@52 100 if paramid == 'threshold' :
fazekasgy@52 101 return self.threshold
fazekasgy@52 102 else:
fazekasgy@52 103 return 0.0
fazekasgy@52 104
fazekasgy@52 105 def process(self,inputbuffers,timestamp):
fazekasgy@52 106
fazekasgy@52 107 # this is a 1 channel frequency domain plugin, therefore
fazekasgy@52 108 # inputbuffers contain (block size / 2) + 1 complex numbers
fazekasgy@52 109 # corresponding to the FFT output from DC to Nyquist inclusive
fazekasgy@52 110
fazekasgy@52 111 cplxArray = inputbuffers[0][:-1]
fazekasgy@52 112
fazekasgy@52 113 prev = self.previousSample
fazekasgy@52 114 numLin = 0.0
fazekasgy@52 115 denom = 0.0
fazekasgy@52 116 centroid = 0.0
fazekasgy@52 117
fazekasgy@52 118 output = FeatureSet()
fazekasgy@52 119
fazekasgy@52 120 pw = 0
fazekasgy@52 121 for i in xrange(1,len(cplxArray)) :
fazekasgy@52 122 pw = pw + abs(cplxArray[i])
fazekasgy@52 123
fazekasgy@52 124 if pw > self.threshold :
fazekasgy@52 125 for i in range(1,(len(cplxArray))) :
fazekasgy@52 126
fazekasgy@52 127 re = cplxArray[i].real
fazekasgy@52 128 im = cplxArray[i].imag
fazekasgy@52 129 freq = i * self.m_inputSampleRate / self.m_blockSize
fazekasgy@52 130 power = sqrt (re*re + im*im) / (self.m_blockSize/2)
fazekasgy@52 131 denom = denom + power
fazekasgy@52 132 numLin = numLin + freq * power
fazekasgy@52 133
fazekasgy@52 134 if denom != 0 :
fazekasgy@52 135 centroid = numLin / denom
fazekasgy@52 136
fazekasgy@52 137 else :
fazekasgy@52 138 centroid = 0.0
fazekasgy@52 139
fazekasgy@52 140 output[0] = Feature()
fazekasgy@52 141 output[0].values = centroid
fazekasgy@52 142 output[0].label = str(centroid)
fazekasgy@52 143
fazekasgy@52 144 return output