view Syncopation models/syncopation.py @ 40:6371e8f21f7d

updating the syncopation functions to fix a few problems
author christopherh <christopher.harte@eecs.qmul.ac.uk>
date Thu, 23 Apr 2015 15:46:58 +0100
parents cc38b3047ed9
children
line wrap: on
line source
'''
Author: Chunyang Song
Institution: Centre for Digital Music, Queen Mary University of London

'''
from rhythm_parser import *
from music_objects import *


def sync_perbar_permodel (model, bar, parameters=None):
	return model.get_syncopation(bar, parameters)

def calculate_syncopation(model, source, parameters=None):
 	total = 0.0
 	barResults = []
 	numberOfNotes = 0

	barlist = None

 	if isinstance(source, BarList):
 		barlist = source
 		sourceType = "bar list"
 	elif isinstance(source, Bar):
 		barlist = BarList().append(source)
 		sourceType = "single bar"
	elif isinstance(source, basestring):
		#treat source as a filename
		sourceType = source
		if source[-4:]==".mid":
			import readmidi
			midiFile = readmidi.read_midi_file(source)
			barlist = readmidi.get_bars_from_midi(midiFile)

		elif source[-4:]==".rhy":
			#import rhythm_parser 
			barlist = read_rhythm(source)
		else:
			print "Error in syncopation_barlist_permodel(): Unrecognised file type."
	else:
		print "Error in syncopation_barlist_permodel(): unrecognised source type."
	
	barsDiscarded=0
	discardedlist = []
	includedlist = []

	if barlist!=None:
		for bar in barlist:
			if not bar.is_empty():
				barSyncopation = sync_perbar_permodel(model, bar, parameters)
			else:
				barSyncopation = None
				print 'Bar %d cannot be measured because it is empty, returning None.' % barlist.index(bar)
			
			barResults.append(barSyncopation)
			if barSyncopation != None:
				total += barSyncopation
				numberOfNotes += sum(bar.get_binary_sequence())
				includedlist.append(barlist.index(bar))
			else:
				barsDiscarded += 1
				discardedlist.append(barlist.index(bar))
				print 'Model could not measure bar %d, returning None.' % barlist.index(bar)

		import WNBD
		if model is WNBD:
			total =  total / numberOfNotes

		average = total / (len(barResults)-barsDiscarded)

 	return {
 			"model_name":model.__name__ , 
 			"summed_syncopation":total, 
 			"mean_syncopation_per_bar":average, 
 			"source":sourceType, 
 			"number_of_bars":len(barResults), 
 			"number_of_bars_not_measured":barsDiscarded, 
 			"bars_with_valid_output":includedlist, 
 			"syncopation_by_bar":barResults
 			}



def results_to_xml(results, outputFilename):
	from xml.etree.ElementTree import Element, ElementTree

	elem = Element("syncopation_results")

	for key, val in results.items():
		child = Element(key)
		child.text = str(val)
		elem.append(child)

	ElementTree(elem).write(outputFilename)