-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnoteSplitter.js
More file actions
67 lines (55 loc) · 1.92 KB
/
noteSplitter.js
File metadata and controls
67 lines (55 loc) · 1.92 KB
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
(function createNoteSplitter(root, factory) {
const exported = factory();
if (typeof module !== "undefined" && module.exports) {
module.exports = exported;
}
if (root) {
root.NoteSplitter = exported;
}
})(
typeof globalThis !== "undefined" ? globalThis : this,
function buildNoteSplitter() {
function splitNotesIntoChunks(notes, chunkSize) {
if (!Array.isArray(notes)) {
throw new Error("notes must be an array");
}
if (!Number.isInteger(chunkSize) || chunkSize <= 0) {
throw new Error("chunkSize must be a positive integer");
}
let maxEnd = 0;
for (const note of notes) {
if (!Number.isInteger(note.step) || note.step < 0) continue;
const dur = Math.max(1, Number.isInteger(note.duration) ? note.duration : 1);
maxEnd = Math.max(maxEnd, note.step + dur);
}
const numChunks = Math.max(1, Math.ceil(maxEnd / chunkSize));
const chunks = Array.from({ length: numChunks }, () => []);
for (const note of notes) {
if (!Number.isInteger(note.step) || note.step < 0) continue;
const dur = Math.max(1, Number.isInteger(note.duration) ? note.duration : 1);
const endStep = note.step + dur;
let cursor = note.step;
let isFirstSegment = true;
while (cursor < endStep) {
const chunkIdx = Math.floor(cursor / chunkSize);
const chunkBoundary = (chunkIdx + 1) * chunkSize;
const segEnd = Math.min(endStep, chunkBoundary);
const localStart = cursor - chunkIdx * chunkSize;
const segDuration = segEnd - cursor;
chunks[chunkIdx].push({
...note,
step: localStart,
duration: segDuration,
isContinuation: !isFirstSegment,
});
cursor = segEnd;
isFirstSegment = false;
}
}
return chunks;
}
return {
splitNotesIntoChunks,
};
},
);