christopher@45
|
1 '''
|
christopher@45
|
2 Author: Chunyang Song
|
christopher@45
|
3 Institution: Centre for Digital Music, Queen Mary University of London
|
christopher@45
|
4
|
christopher@45
|
5 '''
|
christopher@45
|
6 from rhythm_parser import *
|
christopher@45
|
7 from music_objects import *
|
christopher@45
|
8
|
christopher@45
|
9
|
christopher@45
|
10 def sync_perbar_permodel (model, bar, parameters=None):
|
christopher@45
|
11 return model.get_syncopation(bar, parameters)
|
christopher@45
|
12
|
christopher@45
|
13 def calculate_syncopation(model, source, parameters=None, outfile=None):
|
christopher@45
|
14 total = 0.0
|
christopher@45
|
15 barResults = []
|
christopher@45
|
16 numberOfNotes = 0
|
christopher@45
|
17
|
christopher@45
|
18 barlist = None
|
christopher@45
|
19
|
christopher@45
|
20 if isinstance(source, BarList):
|
christopher@45
|
21 barlist = source
|
christopher@45
|
22 sourceType = "bar list"
|
christopher@45
|
23 elif isinstance(source, Bar):
|
christopher@45
|
24 barlist = BarList().append(source)
|
christopher@45
|
25 sourceType = "single bar"
|
christopher@45
|
26 elif isinstance(source, basestring):
|
christopher@45
|
27 #treat source as a filename
|
christopher@45
|
28 sourceType = source
|
christopher@45
|
29 if source[-4:]==".mid":
|
christopher@45
|
30 import readmidi
|
christopher@45
|
31 midiFile = readmidi.read_midi_file(source)
|
christopher@45
|
32 barlist = readmidi.get_bars_from_midi(midiFile)
|
christopher@45
|
33
|
christopher@45
|
34 elif source[-4:]==".rhy":
|
christopher@45
|
35 #import rhythm_parser
|
christopher@45
|
36 barlist = read_rhythm(source)
|
christopher@45
|
37 else:
|
christopher@45
|
38 print "Error in syncopation_barlist_permodel(): Unrecognised file type."
|
christopher@45
|
39 else:
|
christopher@45
|
40 print "Error in syncopation_barlist_permodel(): unrecognised source type."
|
christopher@45
|
41
|
christopher@45
|
42 barsDiscarded=0
|
christopher@45
|
43 discardedlist = []
|
christopher@45
|
44 includedlist = []
|
christopher@45
|
45
|
christopher@45
|
46 if barlist!=None:
|
christopher@45
|
47 for bar in barlist:
|
christopher@45
|
48 if not bar.is_empty():
|
christopher@45
|
49 barSyncopation = sync_perbar_permodel(model, bar, parameters)
|
christopher@45
|
50 else:
|
christopher@45
|
51 barSyncopation = None
|
christopher@45
|
52 print 'Bar %d cannot be measured because it is empty, returning None.' % barlist.index(bar)
|
christopher@45
|
53
|
christopher@45
|
54 barResults.append(barSyncopation)
|
christopher@45
|
55 if barSyncopation != None:
|
christopher@45
|
56 total += barSyncopation
|
christopher@45
|
57 numberOfNotes += sum(bar.get_binary_sequence())
|
christopher@45
|
58 includedlist.append(barlist.index(bar))
|
christopher@45
|
59 else:
|
christopher@45
|
60 barsDiscarded += 1
|
christopher@45
|
61 discardedlist.append(barlist.index(bar))
|
christopher@45
|
62 print 'Model could not measure bar %d, returning None.' % barlist.index(bar)
|
christopher@45
|
63
|
christopher@45
|
64 import WNBD
|
christopher@45
|
65 if model is WNBD:
|
christopher@45
|
66 total = total / numberOfNotes
|
christopher@45
|
67
|
christopher@45
|
68 average = total / (len(barResults)-barsDiscarded)
|
christopher@45
|
69
|
christopher@45
|
70 output = {
|
christopher@45
|
71 "model_name":model.__name__ ,
|
christopher@45
|
72 "summed_syncopation":total,
|
christopher@45
|
73 "mean_syncopation_per_bar":average,
|
christopher@45
|
74 "source":sourceType,
|
christopher@45
|
75 "number_of_bars":len(barResults),
|
christopher@45
|
76 "number_of_bars_not_measured":barsDiscarded,
|
christopher@45
|
77 "bars_with_valid_output":includedlist,
|
christopher@45
|
78 "syncopation_by_bar":barResults
|
christopher@45
|
79 }
|
christopher@45
|
80
|
christopher@45
|
81 if outfile!=None:
|
christopher@45
|
82
|
christopher@45
|
83 if ".xml" in outfile:
|
christopher@45
|
84 results_to_xml(output,outfile)
|
christopher@45
|
85 elif ".json" in outfile:
|
christopher@45
|
86 results_to_json(output,outfile)
|
christopher@45
|
87 else:
|
christopher@45
|
88 print "Error in syncopation.py: Unrecognised output file type: ", outfile
|
christopher@45
|
89
|
christopher@45
|
90 return output
|
christopher@45
|
91
|
christopher@45
|
92
|
christopher@45
|
93
|
christopher@45
|
94 def results_to_xml(results, outputFilename):
|
christopher@45
|
95 from xml.etree.ElementTree import Element, ElementTree
|
christopher@45
|
96
|
christopher@45
|
97 elem = Element("syncopation_results")
|
christopher@45
|
98
|
christopher@45
|
99 for key, val in results.items():
|
christopher@45
|
100 child = Element(key)
|
christopher@45
|
101 child.text = str(val)
|
christopher@45
|
102 elem.append(child)
|
christopher@45
|
103
|
christopher@45
|
104 ElementTree(elem).write(outputFilename)
|
christopher@45
|
105
|
christopher@45
|
106 def results_to_json(results, outputFilename):
|
christopher@45
|
107 import json
|
christopher@45
|
108
|
christopher@45
|
109 fileHandle = open(outputFilename, 'w')
|
christopher@45
|
110 json.dump(results, fileHandle, sort_keys=True, indent=4, separators=(',', ': '))
|
christopher@45
|
111 fileHandle.flush()
|
christopher@45
|
112
|