6
|
1 |
#!/usr/bin/env python3
|
2
|
2 |
|
6
|
3 |
import os, xml2b40
|
|
4 |
import fractions as F
|
0
|
5 |
import segLibB40 as S
|
|
6 |
|
|
7 |
def keySeg (iseg,jseg):
|
|
8 |
hist = S.getSegment (iseg, jseg)
|
|
9 |
ks = S.keyCor (hist)
|
|
10 |
c1, key, m = ks [0] # correlation coeff, key, major/minor
|
|
11 |
c2, _, _ = ks [1] # second best key
|
|
12 |
conf = 300 * (c1 - c2) / c2
|
|
13 |
if conf > 100: conf = 10
|
|
14 |
return conf, S.b40nm (key) + (m and 'm' or ' ')
|
|
15 |
|
|
16 |
def mkAna (events, fnm):
|
|
17 |
kgroep = S.readEvents (events)
|
|
18 |
tikkenPerKwart = 384
|
|
19 |
S.mkWeights (kgroep)
|
|
20 |
conf, key = keySeg (0, len (kgroep)-1)
|
|
21 |
tonalcentre = key[:2] if key[1] in 'b#' else key[:1] # cut minor from key
|
|
22 |
S.mkTemplates ()
|
|
23 |
segs, kgroep = S.analyseK (kgroep, debug=0)
|
|
24 |
regels = []
|
|
25 |
regels.append ('File: %s, ticks per quarternote: %d' % (fnm, tikkenPerKwart))
|
|
26 |
regels.append ('%d note groups, %d chord segments' % (len (kgroep), len (segs)))
|
|
27 |
regels.append ('Key: %s, confidence: %.0f%%' % (key, conf))
|
|
28 |
for (kb, ke, score, chord, _) in segs:
|
|
29 |
grpsInSeg = kgroep [kb:ke]
|
|
30 |
totNotes = sum ([len (ns) for ts, ns in grpsInSeg])
|
|
31 |
percnt = 100. * score / totNotes
|
|
32 |
regels.append ('---- chord %s, score: %.0f%%' % (chord, percnt))
|
|
33 |
for tikken, noten in grpsInSeg:
|
6
|
34 |
noten = ', '.join ([S.b40nm (n) + str(int (n / 40)) for n in noten])
|
|
35 |
x = F.Fraction (tikken, tikkenPerKwart)
|
|
36 |
n, d = x.numerator, x.denominator
|
|
37 |
t = int (n / d)
|
0
|
38 |
r = x - t
|
|
39 |
if r == 0: r = ''
|
|
40 |
regels.append ('%4d %3s %s' % (t, r, noten))
|
6
|
41 |
return regels
|
0
|
42 |
|
|
43 |
if __name__ == '__main__':
|
2
|
44 |
from optparse import OptionParser
|
|
45 |
parser = OptionParser (usage='%prog [-h] [-g TPQ] [--C5] <file1>')
|
|
46 |
parser.add_option ("-t", action="store", type="int", help="ticks per quarternote", default=384, metavar='TPQ')
|
|
47 |
parser.add_option ("--C5", action="store_true", help="central C is C5", default=False)
|
|
48 |
options, args = parser.parse_args ()
|
|
49 |
if len (args) < 1: parser.error ('file argument needed')
|
|
50 |
fnmext = args [0]
|
|
51 |
fnm, ext = os.path.splitext (fnmext)
|
|
52 |
if ext != '.xml': parser.error ('.xml file needed file needed')
|
|
53 |
if not os.path.exists (fnmext): parser.error ('%s does not exist' % fnmext)
|
|
54 |
|
|
55 |
noten = xml2b40.xml2b40 (fnmext, options.t, options.C5)
|
|
56 |
regels = mkAna (noten, fnmext)
|
6
|
57 |
print ('\n'.join (regels))
|