Impression d'un événement SONGEND à la fin de la chanson.
[minwii.git] / src / minwii / loganalyse.py
1 # -*- coding: utf-8 -*-
2 """
3 Module d'analyse des fichiers de log minwii.
4
5 $Id$
6 $URL$
7 """
8
9 from logfilereader import LogFileReader
10 from pprint import pprint
11 from musicxml import musicXml2Song
12 from statlib import stats
13
14 DEFAULT_STATS = ('geometricmean',
15 'harmonicmean',
16 'mean',
17 'median',
18 'medianscore',
19 'mode',
20 'moment',
21 'variation',
22 'skew',
23 'kurtosis',
24 'itemfreq',
25 'histogram',
26 'cumfreq',
27 'relfreq',
28 )
29
30 def statsresults(m) :
31 def computeList(self):
32 l = m(self)
33 ret = {}
34 for name in DEFAULT_STATS :
35 ret[name] = getattr(stats, name)(l)
36 return ret
37 return computeList
38
39 class LogFileAnalyser(LogFileReader) :
40
41 POSSIBLE_ANALYSES = {'BEGINNER' : ('songDuration',
42 'playingDuration',
43 'noteEndNoteOnLatency',
44 'noteOnCount')}
45
46 def analyse(self) :
47 mode = self.getMode()
48 print 'Mode :', mode
49
50 results = {}
51
52 for name in self.POSSIBLE_ANALYSES[mode] :
53 meth = getattr(self, name)
54 results[name] = meth()
55
56 pprint(results)
57
58 def playingDuration(self) :
59 """ retourne la durée écoulée entre le premier et de dernier message
60 de type événement : correspond à la durée d'interprétation.
61 """
62 last = self.getLastEventTicks()
63 first = self.getFirstEventTicks()
64 return last - first
65
66 def songDuration(self) :
67 """ retourne la durée de référence de la chanson
68 en prenant en compte le tempo présent dans la transcription
69 et en effectuant toutes les répétitions des couplets / refrains.
70 """
71 songFile = self.getSongFile()
72 song = musicXml2Song(songFile)
73 duration = 0
74 for note, verseIndex in song.iterNotes() :
75 duration = duration + note.duration
76 return duration * song.quarterNoteDuration
77
78 @statsresults
79 def noteEndNoteOnLatency(self) :
80 eIter = self.getEventsIterator()
81 latencies = []
82 lastnoteEndT = 0
83
84 for ticks, eventName, message in eIter :
85 if eventName == 'NOTEEND':
86 lastnoteEndT = ticks
87 if eventName == 'NOTEON' and lastnoteEndT :
88 latencies.append(ticks - lastnoteEndT)
89
90 return latencies
91
92 def noteOnCount(self) :
93 "retourne le nombre d'événements NOTEON"
94
95 eIter = self.getEventsIterator()
96 cpt = 0
97
98 for ticks, eventName, message in eIter :
99 if eventName == 'NOTEON' :
100 cpt = cpt + 1
101
102 return cpt
103
104
105
106
107
108
109
110 def main() :
111 from optparse import OptionParser
112 usage = "%prog logfile"
113 op = OptionParser(usage)
114 options, args = op.parse_args()
115 if len(args) != 1 :
116 op.error("incorrect number of arguments")
117
118
119 lfa = LogFileAnalyser(args[0])
120 lfa.analyse()
121
122 if __name__ == "__main__" :
123 from os.path import realpath, sep
124 import sys
125 minwiipath = realpath(__file__).split(sep)
126 minwiipath = minwiipath[:-2]
127 minwiipath = sep.join(minwiipath)
128 sys.path.insert(1, minwiipath)
129 main()