annotate Example VamPy plugins/PyZeroCrossing.py @ 24:7d28bed0864e

* Rearrange Python plugin construction. Formerly, the PyPluginAdapter has retained a single plugin instance pointer for each plugin found, and its createPlugin method has simply returned a new PyPlugin object wrapping the same instance pointer. This has a couple of negative consequences: - Because construction of the actual Python instance occurred before the wrapper was constructed, it was not possible to pass arguments (i.e. the sample rate) from the wrapper constructor to the Python plugin instance constructor -- they had to be passed later, to initialise, disadvantaging those plugins that would like to use the sample rate for parameter & step/block size calculations etc - Because there was only a single Python plugin instance, it was not possible to run more than one instance at once with any isolation This rework instead stores the Python class pointer (rather than instance pointer) in the PyPluginAdapter, and each PyPlugin wrapper instance creates its own Python plugin instance. What could possibly go wrong?
author cannam
date Mon, 17 Aug 2009 15:22:06 +0000
parents 535d559300dc
children ba3686eb697c
rev   line source
fazekasgy@1 1 '''PyZeroCrossing.py - Example plugin demonstrates'''
cannam@7 2 '''how to call a python class using the VamPy Vamp plugin'''
fazekasgy@0 3
cannam@24 4 from random import *
cannam@24 5
fazekasgy@0 6 class PyZeroCrossing:
fazekasgy@0 7
cannam@24 8 def __init__(self,inputSampleRate):
cannam@24 9 self.m_inputSampleRate = inputSampleRate
fazekasgy@0 10 self.m_stepSize = 0
fazekasgy@0 11 self.m_blockSize = 0
fazekasgy@0 12 self.m_channels = 0
fazekasgy@0 13 self.previousSample = 0.0
cannam@23 14 self.threshold = 0.005
cannam@24 15 self.identity = random()
cannam@24 16 self.counter = 0
fazekasgy@0 17
cannam@24 18 def initialise(self,channels,stepSize,blockSize):
fazekasgy@0 19 self.m_channels = channels
fazekasgy@0 20 self.m_stepSize = stepSize
fazekasgy@0 21 self.m_blockSize = blockSize
fazekasgy@0 22 return True
fazekasgy@0 23
fazekasgy@0 24 def getMaker(self):
fazekasgy@0 25 return 'VamPy Example Plugins'
fazekasgy@0 26
fazekasgy@0 27 def getName(self):
fazekasgy@8 28 return 'Vampy Zero Crossings'
fazekasgy@0 29
fazekasgy@0 30 def getIdentifier(self):
fazekasgy@0 31 return 'python-zc'
fazekasgy@0 32
fazekasgy@0 33 def getMaxChannelCount(self):
fazekasgy@0 34 return 1
fazekasgy@0 35
fazekasgy@0 36 def getInputDomain(self):
fazekasgy@0 37 return 'TimeDomain'
fazekasgy@0 38
fazekasgy@0 39 def getOutputDescriptors(self):
fazekasgy@0 40
fazekasgy@6 41 #descriptors are python dictionaries
fazekasgy@0 42 output0={
fazekasgy@0 43 'identifier':'vampy-counts',
fazekasgy@0 44 'name':'Number of Zero Crossings',
fazekasgy@0 45 'description':'Number of zero crossings per audio frame',
fazekasgy@0 46 'unit':' ',
fazekasgy@0 47 'hasFixedBinCount':True,
fazekasgy@0 48 'binCount':1,
fazekasgy@0 49 #'binNames':['1 Hz',1.5,'2 Hz',3,'4 Hz'],
fazekasgy@0 50 'hasKnownExtents':False,
fazekasgy@0 51 #'minValue':0.0,
fazekasgy@0 52 #'maxValue':0.0,
fazekasgy@0 53 'isQuantized':True,
fazekasgy@0 54 'quantizeStep':1.0,
fazekasgy@0 55 'sampleType':'OneSamplePerStep'
fazekasgy@0 56 #'sampleRate':48000.0
fazekasgy@0 57 }
fazekasgy@0 58
fazekasgy@0 59 output1={
fazekasgy@0 60 'identifier':'vampy-crossings',
fazekasgy@0 61 'name':'Zero Crossing Locations',
fazekasgy@0 62 'description':'The locations of zero crossing points',
fazekasgy@0 63 'unit':'discrete',
fazekasgy@0 64 'hasFixedBinCount':True,
fazekasgy@0 65 'binCount':0,
fazekasgy@0 66 'sampleType':'VariableSampleRate'
fazekasgy@0 67 #'sampleRate':48000.0
fazekasgy@0 68 }
fazekasgy@0 69
fazekasgy@0 70 #return a list of dictionaries
fazekasgy@0 71 return [output0,output1]
fazekasgy@0 72
fazekasgy@0 73 def getParameterDescriptors(self):
fazekasgy@0 74 paramlist1={
fazekasgy@0 75 'identifier':'threshold',
cannam@24 76 'name':'Noise threshold',
cannam@24 77 'description':'',
fazekasgy@0 78 'unit':'v',
fazekasgy@0 79 'minValue':0.0,
fazekasgy@0 80 'maxValue':0.5,
fazekasgy@8 81 'defaultValue':0.005,
fazekasgy@0 82 'isQuantized':False
fazekasgy@0 83 }
fazekasgy@0 84 return [paramlist1]
fazekasgy@0 85
fazekasgy@0 86 def setParameter(self,paramid,newval):
fazekasgy@0 87 if paramid == 'threshold' :
fazekasgy@0 88 self.threshold = newval
fazekasgy@0 89 return
fazekasgy@0 90
fazekasgy@0 91 def getParameter(self,paramid):
fazekasgy@0 92 if paramid == 'threshold' :
fazekasgy@0 93 return self.threshold
fazekasgy@0 94 else:
fazekasgy@0 95 return 0.0
fazekasgy@0 96
fazekasgy@8 97 def process(self,inbuf,timestamp):
fazekasgy@0 98 crossing = False
fazekasgy@0 99 prev = self.previousSample
fazekasgy@0 100 count = 0.0;
fazekasgy@8 101 channel = inbuf[0]
fazekasgy@0 102
cannam@24 103 print "Identity ", self.identity, ", counter ", self.counter
cannam@24 104 self.counter = self.counter + 1
cannam@24 105
fazekasgy@0 106 #we have two outputs defined thus we have to declare
fazekasgy@0 107 #them as empty dictionaries in our output list
fazekasgy@0 108 #in order to be able to return variable rate outputs
fazekasgy@0 109 output0=[]
fazekasgy@0 110 output1=[]
fazekasgy@0 111
fazekasgy@8 112 if sum([abs(s) for s in channel]) > self.threshold :
fazekasgy@8 113
fazekasgy@8 114 for x in range(len(channel)-1) :
fazekasgy@0 115 crossing = False
fazekasgy@8 116 sample = channel[x]
fazekasgy@0 117 if sample <= 0.0 :
fazekasgy@0 118 if prev > 0.0 : crossing = True
fazekasgy@0 119 else :
fazekasgy@0 120 if sample > 0.0 :
fazekasgy@0 121 if prev <= 0.0 : crossing = True
fazekasgy@0 122
fazekasgy@0 123 if crossing == True :
fazekasgy@0 124 count = count + 1
fazekasgy@0 125 feature1={
fazekasgy@1 126 'hasTimestamp':True,
fazekasgy@0 127 #for now return sample position and convert to RealTime in C code
fazekasgy@8 128 'timeStamp':long(timestamp + x),
fazekasgy@8 129 'values':[count],
fazekasgy@8 130 'label':str(count),
fazekasgy@0 131 }
fazekasgy@0 132 output1.append(feature1)
fazekasgy@0 133
fazekasgy@0 134 prev = sample
fazekasgy@0 135 self.previousSample = prev
fazekasgy@8 136
fazekasgy@0 137 else :
fazekasgy@0 138 count = 0.0
fazekasgy@8 139 self.previousSample = channel[len(channel)-1]
fazekasgy@0 140
fazekasgy@0 141 feature0={
fazekasgy@0 142 'hasTimestamp':False,
fazekasgy@8 143 #'timeStamp':timestamp,
fazekasgy@1 144 'values':[count], #strictly must be a list
fazekasgy@0 145 'label':str(count)
fazekasgy@0 146 }
fazekasgy@0 147 output0.append(feature0)
fazekasgy@0 148
fazekasgy@0 149 #return a LIST of list of dictionaries
fazekasgy@0 150 return [output0,output1]
cannam@7 151