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