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@38
|
13 def syncopation_barlist_permodel(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@38
|
23 elif isinstance(source, basestring):
|
christopher@38
|
24 #treat source as a filename
|
christopher@38
|
25 sourceType = source
|
christopher@38
|
26 if source[-4:]==".mid":
|
christopher@38
|
27 import readmidi
|
christopher@38
|
28 midiFile = readmidi.read_midi_file(source)
|
christopher@38
|
29 barlist = readmidi.get_bars_from_midi(midiFile)
|
christopher@38
|
30
|
christopher@38
|
31 elif source[-4:]==".rhy":
|
christopher@38
|
32 #import rhythm_parser
|
christopher@38
|
33 barlist = read_rhythm(source)
|
christopher@38
|
34 else:
|
christopher@38
|
35 print "Error in syncopation_barlist_permodel(): Unrecognised file type."
|
christopher@38
|
36 else:
|
christopher@38
|
37 print "Error in syncopation_barlist_permodel(): unrecognised source type."
|
csong@35
|
38
|
christopher@38
|
39 barsDiscarded=0
|
csong@28
|
40
|
christopher@38
|
41 if barlist!=None:
|
christopher@38
|
42 for bar in barlist:
|
christopher@38
|
43 if not bar.is_empty():
|
christopher@38
|
44 barSyncopation = sync_perbar_permodel(model, bar, parameters)
|
christopher@38
|
45 else:
|
christopher@38
|
46 barSyncopation = None
|
christopher@38
|
47 print 'Bar %d cannot be measured because it is empty, returning None.' % barlist.index(bar)
|
christopher@38
|
48
|
christopher@38
|
49 barResults.append(barSyncopation)
|
christopher@38
|
50 if barSyncopation != None:
|
christopher@38
|
51 total += barSyncopation
|
christopher@38
|
52 numberOfNotes += sum(bar.get_binary_sequence())
|
christopher@38
|
53 else:
|
christopher@38
|
54 barsDiscarded += 1
|
christopher@38
|
55 print 'Model could not measure bar %d, returning None.' % barlist.index(bar)
|
csong@23
|
56
|
christopher@38
|
57 import WNBD
|
christopher@38
|
58 if model is WNBD:
|
christopher@38
|
59 total = total / numberOfNotes
|
csong@9
|
60
|
christopher@38
|
61 average = total / (len(barResults)-barsDiscarded)
|
csong@9
|
62
|
christopher@38
|
63 return {"summed_syncopation":total, "average_syncopation_per_bar":average, "source":sourceType, "number_of_bars":len(barResults), "number_of_bars_not_measured":barsDiscarded, "syncopation_by_bar":barResults}
|
csong@21
|
64
|
csong@9
|
65
|
csong@9
|
66
|
christopher@38
|
67 def results_to_xml(results, outputFilename):
|
christopher@38
|
68 from xml.etree.ElementTree import Element, ElementTree
|
csong@9
|
69
|
christopher@38
|
70 elem = Element("syncopation_results")
|
csong@9
|
71
|
christopher@38
|
72 for key, val in results.items():
|
christopher@38
|
73 child = Element(key)
|
christopher@38
|
74 child.text = str(val)
|
christopher@38
|
75 elem.append(child)
|
csong@9
|
76
|
christopher@38
|
77 ElementTree(elem).write(outputFilename)
|
csong@9
|
78
|
csong@9
|
79
|