diff Example VamPy plugins/PySpectralFeatures.py @ 37:27bab3a16c9a vampy2final

new branch Vampy2final
author fazekasgy
date Mon, 05 Oct 2009 11:28:00 +0000
parents
children 8b2eddf686da
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Example VamPy plugins/PySpectralFeatures.py	Mon Oct 05 11:28:00 2009 +0000
@@ -0,0 +1,182 @@
+'''PySpectralFeatures.py - Example plugin demonstrates 
+how to calculate and return simple low-level spectral 
+descriptors (curves) using Numpy and the buffer interface.
+
+Outputs: 
+1) Spectral Centroid
+2) Spectral Creast Factor
+3) Spectral Band-width
+4) Spectral Difference (first order)
+
+Centre for Digital Music, Queen Mary University of London.
+Copyright (C) 2009 Gyorgy Fazekas, QMUL. (See Vamp sources 
+for licence information.)
+
+'''
+
+from numpy import *
+from vampy import *
+
+class PySpectralFeatures: 
+	
+	def __init__(self,inputSampleRate):
+
+		# flags:
+		self.vampy_flags = vf_DEBUG | vf_BUFFER | vf_REALTIME
+
+		self.m_inputSampleRate = inputSampleRate
+		self.m_stepSize = 0
+		self.m_blockSize = 0
+		self.m_channels = 0
+		self.threshold = 0.05
+		return None
+		
+	def initialise(self,channels,stepSize,blockSize):
+		self.m_channels = channels
+		self.m_stepSize = stepSize		
+		self.m_blockSize = blockSize
+		self.prevMag = zeros((blockSize/2)-1)
+		return True
+		
+	def reset(self):
+		# reset any initial conditions
+		self.prevMag = zeros((blockSize/2)-1)
+		return None
+	
+	def getMaker(self):
+		return 'Vampy Example Plugins'
+	
+	def getName(self):
+		return 'Vampy Spectral Features'
+		
+	def getIdentifier(self):
+		return 'vampy-sf3'
+
+	def getDescription(self):
+		return 'A collection of low-level spectral descriptors.'
+	
+	def getMaxChannelCount(self):
+		return 1
+		
+	def getInputDomain(self):
+		return FrequencyDomain
+			
+	def getOutputDescriptors(self):
+
+		#Generic values are the same for all
+		Generic = OutputDescriptor()
+		Generic.hasFixedBinCount=True
+		Generic.binCount=1
+		Generic.hasKnownExtents=False
+		Generic.isQuantized=False
+		Generic.sampleType = OneSamplePerStep
+		Generic.unit = 'Hz'		
+		
+		#Spectral centroid etc...
+		SC = OutputDescriptor(Generic)
+		SC.identifier = 'vampy-sc'
+		SC.name = 'Spectral Centroid'
+		SC.description ='Spectral Centroid (Brightness)'
+				
+		SCF = OutputDescriptor(Generic)
+		SCF.identifier = 'vampy-scf'
+		SCF.name = 'Spectral Crest Factor'
+		SCF.description = 'Spectral Crest (Tonality)'
+		SCF.unit = 'v'
+
+		BW = OutputDescriptor(Generic)
+		BW.identifier = 'vampy-bw'
+		BW.name = 'Band Width'
+		BW.description = 'Spectral Band Width'
+		
+		SD = OutputDescriptor(Generic)
+		SD.identifier = 'vampy-sd'
+		SD.name = 'Spectral Difference'
+		SD.description = 'Eucledian distance of successive magnitude spectra.'
+			
+		#return a tuple, list or OutputList(SC,SCF,BW)
+		return OutputList(SC,SCF,BW,SD)
+
+	def getParameterDescriptors(self):
+		
+		threshold = ParameterDescriptor()
+		threshold.identifier='threshold'
+		threshold.name='Noise threshold'
+		threshold.description='Noise threshold'
+		threshold.unit='v'
+		threshold.minValue=0
+		threshold.maxValue=1
+		threshold.defaultValue=0.05
+		threshold.isQuantized=False
+		
+		return ParameterList(threshold)
+
+	def setParameter(self,paramid,newval):
+		if paramid == 'threshold' :
+			self.threshold = newval
+		return
+		
+	def getParameter(self,paramid):
+		if paramid == 'threshold' :
+			return self.threshold
+		else:
+			return 0.0
+
+
+    # using the numpy memory buffer interface: 
+	# flag : vf_BUFFER (or implement processN)
+	# NOTE: Vampy can now pass numpy arrays directly using 
+	# the flag vf_ARRAY (see MFCC plugin for example)
+	def process(self,membuffer,timestamp):
+
+		fftsize = self.m_blockSize
+		sampleRate = self.m_inputSampleRate
+
+		#for time domain plugins use the following line:
+		#audioSamples = frombuffer(membuffer[0],float32)
+
+		#for frequency domain plugins use:
+		complexSpectrum =  frombuffer(membuffer[0],complex64,-1,8)
+
+		# meaning of the parameters above:
+		# complex64 : data type of the created numpy array
+		# -1 : convert the whole buffer 
+		#  8 : skip the DC component (2*32bit / 8bit = 8byte)
+
+		magnitudeSpectrum = abs(complexSpectrum) / (fftsize*0.5)
+		#phaseSpectrum = angle(complexSpectrum)
+		
+		freq = array(range(1,len(complexSpectrum)+1)) \
+		* sampleRate / fftsize
+		
+		# return features in a FeatureSet()
+		output_featureSet = FeatureSet()
+
+		tpower = sum(magnitudeSpectrum)
+
+		if tpower > self.threshold : 
+			centroid = sum(freq * magnitudeSpectrum) / tpower 
+			crest = max(magnitudeSpectrum)  / tpower
+			bw = sum( abs(freq - centroid) * magnitudeSpectrum ) / tpower
+			normMag = magnitudeSpectrum / tpower			
+			sd = sqrt(sum(power((normMag - self.prevMag),2)))
+			self.prevMag = normMag
+		else :
+			centroid = 0.0
+			crest = 0.0
+			bw = 0.0
+			sd = 0.0
+			
+		# Any value resulting from the process can be returned.
+		# It is no longer necessary to wrap single values into lists
+		# and convert numpy.floats to python floats,
+		# however a FeatureList() (or python list) can be returned
+		# if more than one feature is calculated per frame.
+		# The feature values can be e.g. int, float, list or array.
+		
+		output_featureSet[0] = Feature(centroid)
+		output_featureSet[1] = Feature(crest)
+		output_featureSet[2] = Feature(bw)
+		output_featureSet[3] = Feature(sd)
+
+		return output_featureSet