Mercurial > hg > silvet
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 }); |