annotate Example VamPy plugins/PyZeroCrossing.py @ 92:a6718f9fe942

If a module appears to redefine one of our own types, refuse to load it. Also clear out the class dict for all refused modules now, so that we don't get stale names on the next scan due to not having cleared the module on unload
author Chris Cannam
date Mon, 14 Jan 2019 16:19:44 +0000
parents f5b8646494d2
children
rev   line source
fazekasgy@37 1 '''PyZeroCrossing.py - Example plugin demonstrates
fazekasgy@37 2 how to write a Vampy plugin in pure Python without
fazekasgy@37 3 using Numpy or the extensions provided by the embedded
fazekasgy@37 4 vampy module.
fazekasgy@37 5
fazekasgy@37 6 This plugin is compatible with provious versions of vampy,
fazekasgy@37 7 apart from moving the inputSampleRate
fazekasgy@37 8 argument from initialise to __init__()
fazekasgy@37 9
fazekasgy@37 10 Outputs:
fazekasgy@37 11 1) Zero crossing counts
fazekasgy@37 12 2) Zero crossing locations
fazekasgy@37 13
fazekasgy@37 14 Centre for Digital Music, Queen Mary University of London.
fazekasgy@37 15 Copyright (C) 2009 Gyorgy Fazekas, QMUL. (See Vamp sources
fazekasgy@37 16 for licence information.)
fazekasgy@37 17
fazekasgy@37 18 '''
fazekasgy@37 19
fazekasgy@37 20 class PyZeroCrossing:
fazekasgy@37 21
fazekasgy@37 22 def __init__(self,inputSampleRate):
fazekasgy@37 23 self.m_inputSampleRate = inputSampleRate
fazekasgy@37 24 self.m_stepSize = 0
fazekasgy@37 25 self.m_blockSize = 0
fazekasgy@37 26 self.m_channels = 0
fazekasgy@37 27 self.previousSample = 0.0
fazekasgy@37 28 self.threshold = 0.005
fazekasgy@37 29 self.counter = 0
fazekasgy@37 30
fazekasgy@37 31 def initialise(self,channels,stepSize,blockSize):
fazekasgy@37 32 self.m_channels = channels
fazekasgy@37 33 self.m_stepSize = stepSize
fazekasgy@37 34 self.m_blockSize = blockSize
fazekasgy@37 35 return True
fazekasgy@37 36
fazekasgy@37 37 def getMaker(self):
fazekasgy@37 38 return 'Vampy Example Plugins'
fazekasgy@37 39
fazekasgy@37 40 def getName(self):
fazekasgy@37 41 return 'Vampy Zero Crossings'
Chris@69 42
Chris@69 43 def getDescription(self):
Chris@69 44 return 'Count the number of simple zero-crossings for the signal within each processing block'
Chris@69 45
Chris@69 46 def getCopyright(self):
Chris@69 47 return 'Plugin By George Fazekas. Freely redistributable example plugin (BSD license)'
fazekasgy@37 48
fazekasgy@37 49 def getIdentifier(self):
fazekasgy@37 50 return 'vampy-zc2'
fazekasgy@37 51
fazekasgy@37 52 def getMaxChannelCount(self):
fazekasgy@37 53 return 1
fazekasgy@37 54
fazekasgy@37 55 def getInputDomain(self):
fazekasgy@37 56 return 'TimeDomain'
fazekasgy@37 57
fazekasgy@37 58 def getOutputDescriptors(self):
fazekasgy@37 59
fazekasgy@37 60 #descriptors can be returned as python dictionaries
fazekasgy@37 61 output0={
fazekasgy@37 62 'identifier':'vampy-counts',
fazekasgy@37 63 'name':'Number of Zero Crossings',
fazekasgy@37 64 'description':'Number of zero crossings per audio frame',
fazekasgy@37 65 'unit':' ',
fazekasgy@37 66 'hasFixedBinCount':True,
fazekasgy@37 67 'binCount':1,
fazekasgy@37 68 #'binNames':['1 Hz',1.5,'2 Hz',3,'4 Hz'],
fazekasgy@37 69 'hasKnownExtents':False,
fazekasgy@37 70 #'minValue':0.0,
fazekasgy@37 71 #'maxValue':0.0,
fazekasgy@37 72 'isQuantized':True,
fazekasgy@37 73 'quantizeStep':1.0,
fazekasgy@37 74 'sampleType':'OneSamplePerStep'
fazekasgy@37 75 #'sampleRate':48000.0
fazekasgy@37 76 }
fazekasgy@37 77
fazekasgy@37 78 output1={
fazekasgy@37 79 'identifier':'vampy-crossings',
fazekasgy@37 80 'name':'Zero Crossing Locations',
fazekasgy@37 81 'description':'The locations of zero crossing points',
fazekasgy@37 82 'unit':'discrete',
fazekasgy@37 83 'hasFixedBinCount':True,
fazekasgy@37 84 'binCount':0,
fazekasgy@37 85 'sampleType':'VariableSampleRate'
fazekasgy@37 86 }
fazekasgy@37 87
fazekasgy@37 88 return [output0,output1]
fazekasgy@37 89
fazekasgy@37 90
fazekasgy@37 91 def getParameterDescriptors(self):
fazekasgy@37 92 paramlist1={
fazekasgy@37 93 'identifier':'threshold',
fazekasgy@37 94 'name':'Noise threshold',
Chris@68 95 'description':'Magnitude below which a process block will be considered to be all zero',
fazekasgy@37 96 'unit':'v',
fazekasgy@37 97 'minValue':0.0,
fazekasgy@37 98 'maxValue':0.5,
fazekasgy@37 99 'defaultValue':0.005,
fazekasgy@37 100 'isQuantized':False
fazekasgy@37 101 }
fazekasgy@37 102 return [paramlist1]
fazekasgy@37 103
fazekasgy@37 104
fazekasgy@37 105 def setParameter(self,paramid,newval):
fazekasgy@37 106 if paramid == 'threshold' :
fazekasgy@37 107 self.threshold = newval
fazekasgy@37 108 return
fazekasgy@37 109
fazekasgy@37 110
fazekasgy@37 111 def getParameter(self,paramid):
fazekasgy@37 112 if paramid == 'threshold' :
fazekasgy@37 113 return self.threshold
fazekasgy@37 114 else:
fazekasgy@37 115 return 0.0
fazekasgy@37 116
fazekasgy@37 117
fazekasgy@37 118 # legacy process type: the input is a python list of samples
fazekasgy@37 119 def process(self,inbuf,timestamp):
fazekasgy@37 120 crossing = False
fazekasgy@37 121 prev = self.previousSample
fazekasgy@37 122 count = 0.0;
fazekasgy@37 123 channel = inbuf[0]
fazekasgy@37 124
fazekasgy@37 125 #we have two outputs defined thus we have to declare
fazekasgy@37 126 #them as empty dictionaries in our output list
fazekasgy@37 127 #in order to be able to return variable rate outputs
fazekasgy@37 128 output0=[]
fazekasgy@37 129 output1=[]
fazekasgy@37 130
fazekasgy@37 131 if sum([abs(s) for s in channel]) > self.threshold :
fazekasgy@37 132
fazekasgy@37 133 for x in range(len(channel)-1) :
fazekasgy@37 134 crossing = False
fazekasgy@37 135 sample = channel[x]
fazekasgy@37 136 if sample <= 0.0 :
fazekasgy@37 137 if prev > 0.0 : crossing = True
fazekasgy@37 138 else :
fazekasgy@37 139 if sample > 0.0 :
fazekasgy@37 140 if prev <= 0.0 : crossing = True
fazekasgy@37 141
fazekasgy@37 142 if crossing == True :
fazekasgy@37 143 count = count + 1
fazekasgy@37 144 feature1={
fazekasgy@37 145 'hasTimestamp':True,
fazekasgy@37 146 'timeStamp':long(timestamp + x),
fazekasgy@37 147 'values':[count],
fazekasgy@37 148 'label':str(count),
fazekasgy@37 149 }
fazekasgy@37 150 output1.append(feature1)
fazekasgy@37 151
fazekasgy@37 152 prev = sample
fazekasgy@37 153 self.previousSample = prev
fazekasgy@37 154
fazekasgy@37 155 else :
fazekasgy@37 156 count = 0.0
fazekasgy@37 157 self.previousSample = channel[len(channel)-1]
fazekasgy@37 158
fazekasgy@37 159 feature0={
fazekasgy@37 160 'hasTimestamp':False,
fazekasgy@37 161 'values':[count],
fazekasgy@37 162 'label':str(count)
fazekasgy@37 163 }
fazekasgy@37 164 output0.append(feature0)
fazekasgy@37 165
fazekasgy@37 166 #return a LIST of list of dictionaries
fazekasgy@37 167 return [output0,output1]
fazekasgy@37 168