Mercurial > hg > silvet
diff 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 |
line wrap: on
line diff
--- a/yeti/em_onecolumn.yeti Fri Mar 28 12:52:11 2014 +0000 +++ b/yeti/em_onecolumn.yeti Fri Mar 28 14:00:40 2014 +0000 @@ -10,82 +10,100 @@ inRange ranges instrument note = note >= ranges[instrument].lowest and note <= ranges[instrument].highest; +normalise v = + (s = vec.sum v; + if s > 0 then vec.divideBy s v + else v + fi); + initialise ranges templates notes = - (instruments = keys ranges; + (instruments = sort (keys ranges); { pitches = // z in the original. 1 per note - vec.randoms notes, + normalise (vec.randoms notes), sources = // u in the original. 1 per note-instrument - mapIntoHash id - do instrument: + //!!! should this be normalised across instruments? i.e. row-wise + mat.fromColumns + (map do instrument: vec.fromList (map do note: if inRange ranges instrument note then 1 else 0 fi done [0..notes-1]) - done instruments, - instruments, - templates, - ranges, + done instruments), + instruments = array instruments, + instCount = length instruments, + templates = array + (map do iname: + m = templates[iname]; + mat.fromColumns (map normalise (mat.asColumns m)) + done instruments), + ranges = array + (map do iname: + ranges[iname] + done instruments), lowest = head - (sort (map do i: ranges[i].lowest done instruments)), + (sort (map do iname: ranges[iname].lowest done instruments)), highest = head (reverse - (sort (map do i: ranges[i].highest done instruments))), + (sort (map do iname: ranges[iname].highest done instruments))), }); epsilon = 1e-16; select predicate = concatMap do v: if predicate v then [v] else [] fi done; -distributionsFor data instrument note = +distributionsFor data instNo note = { - w = mat.getColumn note data.templates[instrument], + w = mat.getColumn note data.templates[instNo], p = vec.at data.pitches note, - s = vec.at data.sources[instrument] note, + s = mat.at data.sources note instNo, }; performExpectation data column = - (estimate = - fold do acc instrument: + (column = normalise column; + estimate = + fold do acc inst: fold do acc note: - { w, p, s } = distributionsFor data instrument note; + { w, p, s } = distributionsFor data inst note; vec.add [acc, vec.scaled (p * s) w]; - done acc [data.ranges[instrument].lowest .. - data.ranges[instrument].highest] - done (vec.consts epsilon (vec.length column)) data.instruments; + done acc [data.ranges[inst].lowest .. + data.ranges[inst].highest] + done (vec.consts epsilon (vec.length column)) [0..data.instCount-1]; vec.divide column estimate); performMaximisation data column q = - (pitches = vec.fromList + (column = normalise column; + + pitches = vec.fromList (map do note: - fold do acc instrument: - { w, p, s } = distributionsFor data instrument note; + fold do acc inst: + { w, p, s } = distributionsFor data inst note; fold do acc bin: acc + s * p * (vec.at w bin) * (vec.at q bin); done acc [0..vec.length column - 1] - done epsilon data.instruments; + done epsilon [0..data.instCount-1]; done [data.lowest .. data.highest]); pitches = vec.divideBy (vec.sum pitches) pitches; - sources = mapIntoHash id - do instrument: vec.fromList + sources = mat.fromColumns + (map do inst: vec.fromList (map do note: - if not inRange data.ranges instrument note then epsilon else - { w, p, s } = distributionsFor data instrument note; + if not inRange data.ranges inst note then epsilon else + { w, p, s } = distributionsFor data inst note; fold do acc bin: acc + s * p * (vec.at w bin) * (vec.at q bin); done epsilon [0..vec.length column - 1] fi; done [data.lowest .. data.highest]) - done data.instruments; + done [0..data.instCount-1]); - sourceDenoms = fold do acc instrument: - vec.add [acc, sources[instrument]] - done (vec.zeros (data.highest - data.lowest + 1)) data.instruments; + sourceDenoms = fold do acc inst: + vec.add [acc, (mat.getColumn inst sources)] + done (vec.zeros (data.highest - data.lowest + 1)) [0..data.instCount-1]; - sources = mapIntoHash id - do instrument: - vec.divide sources[instrument] sourceDenoms; - done (keys sources); + sources = mat.fromColumns + (map do inst: + vec.divide (mat.getColumn inst sources) sourceDenoms; + done [0..data.instCount-1]); data with { pitches,