|
1 | 1 | import { gcd } from './fraction.mjs'; |
2 | 2 |
|
3 | | -// TODO: make it work for stacked patterns + support silence |
4 | | - |
5 | 3 | function drawLine(pat, chars = 60) { |
6 | | - let s = ''; |
7 | 4 | let c = 0; |
8 | | - while (s.length < chars) { |
| 5 | + let lines = ['']; |
| 6 | + const slots = []; |
| 7 | + while (lines[0].length < chars) { |
9 | 8 | const haps = pat.queryArc(c, c + 1); |
10 | | - const durations = haps.map((hap) => hap.duration); |
| 9 | + const durations = haps.filter((hap) => hap.hasOnset()).map((hap) => hap.duration); |
11 | 10 | const totalSlots = gcd(...durations).inverse(); |
12 | | - s += '|'; |
13 | | - haps.forEach((hap) => { |
14 | | - const duration = hap.whole.end.sub(hap.whole.begin); |
15 | | - const slots = totalSlots.mul(duration); |
16 | | - s += Array(slots.valueOf()) |
17 | | - .fill() |
18 | | - .map((_, i) => (!i ? hap.value : '-')) |
19 | | - .join(''); |
20 | | - }); |
21 | | - ++c; |
| 11 | + slots.push(totalSlots); |
| 12 | + const minDuration = durations.reduce((a, b) => a.min(b), durations[0]); |
| 13 | + lines = lines.map((line) => line + '|'); |
| 14 | + |
| 15 | + for (let i = 0; i < totalSlots; i++) { |
| 16 | + const step = c * totalSlots + i; |
| 17 | + const [begin, end] = [minDuration.mul(step), minDuration.mul(step + 1)]; |
| 18 | + const matches = haps.filter((hap) => hap.whole.begin.lte(begin) && hap.whole.end.gte(end)); |
| 19 | + const missingLines = matches.length - lines.length; |
| 20 | + if (missingLines > 0) { |
| 21 | + console.log(c, 'missingLines', missingLines); |
| 22 | + const emptyCycles = |
| 23 | + '|' + |
| 24 | + new Array(c) |
| 25 | + .fill() |
| 26 | + .map((_, l) => Array(slots[l]).fill('.').join('')) |
| 27 | + .join('|') + |
| 28 | + Array(i).fill('.').join(''); |
| 29 | + lines = lines.concat(Array(missingLines).fill(emptyCycles)); |
| 30 | + } |
| 31 | + lines = lines.map((line, i) => { |
| 32 | + const hap = matches[i]; |
| 33 | + if (hap) { |
| 34 | + const isOnset = hap.whole.begin.eq(begin); |
| 35 | + const char = isOnset ? '' + hap.value : '-'; |
| 36 | + return line + char; |
| 37 | + } |
| 38 | + return line + '.'; |
| 39 | + }); |
| 40 | + } |
| 41 | + c++; |
22 | 42 | } |
23 | | - return s; |
| 43 | + return lines.join('\n'); |
24 | 44 | } |
25 | 45 |
|
26 | 46 | export default drawLine; |
0 commit comments