comparison Example VamPy plugins/PySpectralFeatures.py @ 9:d2d36e7d2276

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