comparison yeti/em_onecolumn.yeti @ 22:782b910394f3

Instruments by number rather than by name
author Chris Cannam
date Fri, 28 Mar 2014 14:00:40 +0000
parents 8e61ec97b34e
children 990b8b8b7e25
comparison
equal deleted inserted replaced
21:8e61ec97b34e 22:782b910394f3
8 plot = load may.plot; 8 plot = load may.plot;
9 9
10 inRange ranges instrument note = 10 inRange ranges instrument note =
11 note >= ranges[instrument].lowest and note <= ranges[instrument].highest; 11 note >= ranges[instrument].lowest and note <= ranges[instrument].highest;
12 12
13 normalise v =
14 (s = vec.sum v;
15 if s > 0 then vec.divideBy s v
16 else v
17 fi);
18
13 initialise ranges templates notes = 19 initialise ranges templates notes =
14 (instruments = keys ranges; 20 (instruments = sort (keys ranges);
15 { 21 {
16 pitches = // z in the original. 1 per note 22 pitches = // z in the original. 1 per note
17 vec.randoms notes, 23 normalise (vec.randoms notes),
18 sources = // u in the original. 1 per note-instrument 24 sources = // u in the original. 1 per note-instrument
19 mapIntoHash id 25 //!!! should this be normalised across instruments? i.e. row-wise
20 do instrument: 26 mat.fromColumns
27 (map do instrument:
21 vec.fromList 28 vec.fromList
22 (map do note: 29 (map do note:
23 if inRange ranges instrument note then 1 else 0 fi 30 if inRange ranges instrument note then 1 else 0 fi
24 done [0..notes-1]) 31 done [0..notes-1])
25 done instruments, 32 done instruments),
26 instruments, 33 instruments = array instruments,
27 templates, 34 instCount = length instruments,
28 ranges, 35 templates = array
36 (map do iname:
37 m = templates[iname];
38 mat.fromColumns (map normalise (mat.asColumns m))
39 done instruments),
40 ranges = array
41 (map do iname:
42 ranges[iname]
43 done instruments),
29 lowest = head 44 lowest = head
30 (sort (map do i: ranges[i].lowest done instruments)), 45 (sort (map do iname: ranges[iname].lowest done instruments)),
31 highest = head (reverse 46 highest = head (reverse
32 (sort (map do i: ranges[i].highest done instruments))), 47 (sort (map do iname: ranges[iname].highest done instruments))),
33 }); 48 });
34 49
35 epsilon = 1e-16; 50 epsilon = 1e-16;
36 51
37 select predicate = concatMap do v: if predicate v then [v] else [] fi done; 52 select predicate = concatMap do v: if predicate v then [v] else [] fi done;
38 53
39 distributionsFor data instrument note = 54 distributionsFor data instNo note =
40 { 55 {
41 w = mat.getColumn note data.templates[instrument], 56 w = mat.getColumn note data.templates[instNo],
42 p = vec.at data.pitches note, 57 p = vec.at data.pitches note,
43 s = vec.at data.sources[instrument] note, 58 s = mat.at data.sources note instNo,
44 }; 59 };
45 60
46 performExpectation data column = 61 performExpectation data column =
47 (estimate = 62 (column = normalise column;
48 fold do acc instrument: 63 estimate =
64 fold do acc inst:
49 fold do acc note: 65 fold do acc note:
50 { w, p, s } = distributionsFor data instrument note; 66 { w, p, s } = distributionsFor data inst note;
51 vec.add [acc, vec.scaled (p * s) w]; 67 vec.add [acc, vec.scaled (p * s) w];
52 done acc [data.ranges[instrument].lowest .. 68 done acc [data.ranges[inst].lowest ..
53 data.ranges[instrument].highest] 69 data.ranges[inst].highest]
54 done (vec.consts epsilon (vec.length column)) data.instruments; 70 done (vec.consts epsilon (vec.length column)) [0..data.instCount-1];
55 vec.divide column estimate); 71 vec.divide column estimate);
56 72
57 performMaximisation data column q = 73 performMaximisation data column q =
58 (pitches = vec.fromList 74 (column = normalise column;
75
76 pitches = vec.fromList
59 (map do note: 77 (map do note:
60 fold do acc instrument: 78 fold do acc inst:
61 { w, p, s } = distributionsFor data instrument note; 79 { w, p, s } = distributionsFor data inst note;
62 fold do acc bin: 80 fold do acc bin:
63 acc + s * p * (vec.at w bin) * (vec.at q bin); 81 acc + s * p * (vec.at w bin) * (vec.at q bin);
64 done acc [0..vec.length column - 1] 82 done acc [0..vec.length column - 1]
65 done epsilon data.instruments; 83 done epsilon [0..data.instCount-1];
66 done [data.lowest .. data.highest]); 84 done [data.lowest .. data.highest]);
67 pitches = vec.divideBy (vec.sum pitches) pitches; 85 pitches = vec.divideBy (vec.sum pitches) pitches;
68 86
69 sources = mapIntoHash id 87 sources = mat.fromColumns
70 do instrument: vec.fromList 88 (map do inst: vec.fromList
71 (map do note: 89 (map do note:
72 if not inRange data.ranges instrument note then epsilon else 90 if not inRange data.ranges inst note then epsilon else
73 { w, p, s } = distributionsFor data instrument note; 91 { w, p, s } = distributionsFor data inst note;
74 fold do acc bin: 92 fold do acc bin:
75 acc + s * p * (vec.at w bin) * (vec.at q bin); 93 acc + s * p * (vec.at w bin) * (vec.at q bin);
76 done epsilon [0..vec.length column - 1] 94 done epsilon [0..vec.length column - 1]
77 fi; 95 fi;
78 done [data.lowest .. data.highest]) 96 done [data.lowest .. data.highest])
79 done data.instruments; 97 done [0..data.instCount-1]);
80 98
81 sourceDenoms = fold do acc instrument: 99 sourceDenoms = fold do acc inst:
82 vec.add [acc, sources[instrument]] 100 vec.add [acc, (mat.getColumn inst sources)]
83 done (vec.zeros (data.highest - data.lowest + 1)) data.instruments; 101 done (vec.zeros (data.highest - data.lowest + 1)) [0..data.instCount-1];
84 102
85 sources = mapIntoHash id 103 sources = mat.fromColumns
86 do instrument: 104 (map do inst:
87 vec.divide sources[instrument] sourceDenoms; 105 vec.divide (mat.getColumn inst sources) sourceDenoms;
88 done (keys sources); 106 done [0..data.instCount-1]);
89 107
90 data with { 108 data with {
91 pitches, 109 pitches,
92 sources, 110 sources,
93 }); 111 });