Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | import { PatternCell } from "shared/lib/uge/types";
import {
PIANO_ROLL_CELL_SIZE,
TOTAL_NOTES,
TRACKER_PATTERN_LENGTH,
} from "consts";
export const calculatePlaybackTrackerPosition = (
playbackOrder: number,
playbackRow: number,
) =>
playbackOrder * TRACKER_PATTERN_LENGTH * PIANO_ROLL_CELL_SIZE +
playbackRow * PIANO_ROLL_CELL_SIZE;
export const calculateDocumentWidth = (sequenceLength: number) =>
sequenceLength * TRACKER_PATTERN_LENGTH * PIANO_ROLL_CELL_SIZE;
export const noteToRow = (note: number) => TOTAL_NOTES - 1 - note;
export const rowToNote = (row: number) => TOTAL_NOTES - 1 - row;
export const wrapNote = (note: number) =>
((note % TOTAL_NOTES) + TOTAL_NOTES) % TOTAL_NOTES;
export interface AbsColPosition {
sequenceId: number;
column: number;
}
export const toAbsCol = (sequenceId: number, column: number) =>
sequenceId * TRACKER_PATTERN_LENGTH + column;
export const fromAbsCol = (absCol: number): AbsColPosition => ({
sequenceId: Math.floor(absCol / TRACKER_PATTERN_LENGTH),
column: absCol % TRACKER_PATTERN_LENGTH,
});
export interface ResolvedAbsCol extends AbsColPosition {
patternId: number;
}
export const resolveAbsCol = (
sequence: number[],
absCol: number,
): ResolvedAbsCol | null => {
const { sequenceId, column } = fromAbsCol(absCol);
const patternId = sequence[sequenceId];
Iif (patternId === undefined) {
return null;
}
return { sequenceId, column, patternId };
};
export const clonePattern = (pattern: PatternCell[][]) =>
pattern.map((column) => column.map((cell) => ({ ...cell })));
export const clonePatterns = (patterns: PatternCell[][][]) =>
patterns.map(clonePattern);
export const mutatePatternsAndCollectChanges = (
sourcePatterns: PatternCell[][][],
mutate: (
clonedPatterns: PatternCell[][][],
changedPatternIds: Set<number>,
) => void,
) => {
const clonedPatterns = clonePatterns(sourcePatterns);
const changedPatternIds = new Set<number>();
mutate(clonedPatterns, changedPatternIds);
return { clonedPatterns, changedPatternIds };
};
export const commitChangedPatterns = (
changedPatternIds: Iterable<number>,
clonedPatterns: PatternCell[][][],
commit: (patternId: number, pattern: PatternCell[][]) => void,
) => {
for (const patternId of changedPatternIds) {
commit(patternId, clonedPatterns[patternId]);
}
};
export interface RollGridPoint {
absCol: number;
note: number;
}
export const interpolateGridLine = (
from: RollGridPoint | null,
to: RollGridPoint,
): RollGridPoint[] => {
Iif (!from) {
return [to];
}
const points: RollGridPoint[] = [];
let x0 = from.absCol;
let y0 = from.note;
const x1 = to.absCol;
const y1 = to.note;
const dx = Math.abs(x1 - x0);
const dy = Math.abs(y1 - y0);
const sx = x0 < x1 ? 1 : -1;
const sy = y0 < y1 ? 1 : -1;
let err = dx - dy;
while (x0 !== x1 || y0 !== y1) {
const e2 = 2 * err;
Iif (e2 > -dy) {
err -= dy;
x0 += sx;
}
Iif (e2 < dx) {
err += dx;
y0 += sy;
}
points.push({ absCol: x0, note: y0 });
}
return points;
};
|