@onjmin/dtm 0.1.14 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -1
- package/dist/index.d.mts +9 -4
- package/dist/index.d.ts +9 -4
- package/dist/index.js +272 -114
- package/dist/index.mjs +272 -114
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -1627,8 +1627,8 @@ function parseKoeHeader(headerBytes) {
|
|
|
1627
1627
|
}
|
|
1628
1628
|
var pcmBase = (jsonLength) => 8 + jsonLength;
|
|
1629
1629
|
var BlobVoiceSource = class {
|
|
1630
|
-
constructor(
|
|
1631
|
-
this.blob =
|
|
1630
|
+
constructor(blob2, base) {
|
|
1631
|
+
this.blob = blob2;
|
|
1632
1632
|
this.base = base;
|
|
1633
1633
|
}
|
|
1634
1634
|
blob;
|
|
@@ -1639,8 +1639,8 @@ var BlobVoiceSource = class {
|
|
|
1639
1639
|
}
|
|
1640
1640
|
};
|
|
1641
1641
|
var RangeVoiceSource = class {
|
|
1642
|
-
constructor(
|
|
1643
|
-
this.url =
|
|
1642
|
+
constructor(url2, base) {
|
|
1643
|
+
this.url = url2;
|
|
1644
1644
|
this.base = base;
|
|
1645
1645
|
}
|
|
1646
1646
|
url;
|
|
@@ -1656,8 +1656,8 @@ var RangeVoiceSource = class {
|
|
|
1656
1656
|
return res.arrayBuffer();
|
|
1657
1657
|
}
|
|
1658
1658
|
};
|
|
1659
|
-
async function rangeFetch(
|
|
1660
|
-
const res = await fetch(
|
|
1659
|
+
async function rangeFetch(url2, start, length) {
|
|
1660
|
+
const res = await fetch(url2, {
|
|
1661
1661
|
headers: { Range: `bytes=${start}-${start + length - 1}` }
|
|
1662
1662
|
});
|
|
1663
1663
|
if (!res.ok && res.status !== 206)
|
|
@@ -2428,22 +2428,22 @@ var createLocalBackend = async (options) => {
|
|
|
2428
2428
|
}
|
|
2429
2429
|
};
|
|
2430
2430
|
};
|
|
2431
|
-
var spawnVoiceWorker = async (
|
|
2432
|
-
const sameOrigin = new URL(
|
|
2433
|
-
if (sameOrigin) return new Worker(
|
|
2434
|
-
const text = await fetch(
|
|
2431
|
+
var spawnVoiceWorker = async (url2) => {
|
|
2432
|
+
const sameOrigin = new URL(url2, location.href).origin === location.origin;
|
|
2433
|
+
if (sameOrigin) return new Worker(url2);
|
|
2434
|
+
const text = await fetch(url2).then((r) => r.text());
|
|
2435
2435
|
return new Worker(
|
|
2436
2436
|
URL.createObjectURL(new Blob([text], { type: "text/javascript" }))
|
|
2437
2437
|
);
|
|
2438
2438
|
};
|
|
2439
2439
|
var createWorkerBackend = async (workerUrl, options) => {
|
|
2440
|
-
const
|
|
2440
|
+
const worker2 = await spawnVoiceWorker(workerUrl);
|
|
2441
2441
|
const aliasSet = /* @__PURE__ */ new Set();
|
|
2442
2442
|
const pending = /* @__PURE__ */ new Map();
|
|
2443
2443
|
let reqId = 0;
|
|
2444
2444
|
let onReady = null;
|
|
2445
2445
|
let onFail = null;
|
|
2446
|
-
|
|
2446
|
+
worker2.onmessage = (ev) => {
|
|
2447
2447
|
const m = ev.data;
|
|
2448
2448
|
if (m.type === "ready") {
|
|
2449
2449
|
for (const a of m.aliases) aliasSet.add(a);
|
|
@@ -2458,14 +2458,14 @@ var createWorkerBackend = async (workerUrl, options) => {
|
|
|
2458
2458
|
}
|
|
2459
2459
|
}
|
|
2460
2460
|
};
|
|
2461
|
-
|
|
2461
|
+
worker2.onerror = (e) => {
|
|
2462
2462
|
const ev = e;
|
|
2463
2463
|
onFail?.(new Error(ev.message || ev.error || `Event: ${ev.type}`));
|
|
2464
2464
|
};
|
|
2465
2465
|
await new Promise((resolve, reject) => {
|
|
2466
2466
|
onReady = resolve;
|
|
2467
2467
|
onFail = reject;
|
|
2468
|
-
|
|
2468
|
+
worker2.postMessage({
|
|
2469
2469
|
type: "init",
|
|
2470
2470
|
koe: options.koe,
|
|
2471
2471
|
worldlineScriptUrl: options.worldlineScriptUrl ?? DEFAULT_WORLDLINE_SCRIPT,
|
|
@@ -2482,7 +2482,7 @@ var createWorkerBackend = async (workerUrl, options) => {
|
|
|
2482
2482
|
m.pcm ? { pcm: m.pcm, preSec: m.preSec ?? 0, rate: m.rate ?? 1 } : null
|
|
2483
2483
|
)
|
|
2484
2484
|
);
|
|
2485
|
-
|
|
2485
|
+
worker2.postMessage({
|
|
2486
2486
|
type: "render",
|
|
2487
2487
|
id,
|
|
2488
2488
|
alias,
|
|
@@ -2494,7 +2494,7 @@ var createWorkerBackend = async (workerUrl, options) => {
|
|
|
2494
2494
|
hasAlias: (a) => aliasSet.has(a),
|
|
2495
2495
|
pitchTokens: collectPitchTokens(aliasSet),
|
|
2496
2496
|
renderAlias,
|
|
2497
|
-
dispose: () =>
|
|
2497
|
+
dispose: () => worker2.terminate()
|
|
2498
2498
|
};
|
|
2499
2499
|
};
|
|
2500
2500
|
var createKoeVoice = async (ctx, destination, options) => {
|
|
@@ -2629,7 +2629,7 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2629
2629
|
[FALLBACK_MODEL, createKlattVoice(ctx, destination)]
|
|
2630
2630
|
]);
|
|
2631
2631
|
const loading = /* @__PURE__ */ new Map();
|
|
2632
|
-
const
|
|
2632
|
+
const load2 = (model) => {
|
|
2633
2633
|
const m = model.toLowerCase();
|
|
2634
2634
|
const ready = loaded.get(m);
|
|
2635
2635
|
if (ready) return Promise.resolve(ready);
|
|
@@ -2661,7 +2661,7 @@ var createSingingVoices = (ctx, destination, options = {}) => {
|
|
|
2661
2661
|
const loadModels = async (models) => {
|
|
2662
2662
|
const set = /* @__PURE__ */ new Set();
|
|
2663
2663
|
for (const m of models) if (m) set.add(m.toLowerCase());
|
|
2664
|
-
await Promise.all([...set].map((m) =>
|
|
2664
|
+
await Promise.all([...set].map((m) => load2(m)));
|
|
2665
2665
|
};
|
|
2666
2666
|
const forEachSungNote = (track, fn) => {
|
|
2667
2667
|
let prevVowel = "";
|
|
@@ -2883,21 +2883,26 @@ var shiftNotes = (cores, shiftSteps) => {
|
|
|
2883
2883
|
// src/midi-io.ts
|
|
2884
2884
|
var STEPS_PER_BEAT = 48;
|
|
2885
2885
|
var analyzeMidiTracks = (midi) => {
|
|
2886
|
-
const {
|
|
2886
|
+
const { tracks } = midi;
|
|
2887
2887
|
const result = [];
|
|
2888
|
-
for (let i = 0; i <
|
|
2888
|
+
for (let i = 0; i < tracks.length; i++) {
|
|
2889
2889
|
const notes = [];
|
|
2890
2890
|
let currentTime = 0;
|
|
2891
|
-
for (const event of
|
|
2892
|
-
currentTime += event.
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2891
|
+
for (const event of tracks[i]) {
|
|
2892
|
+
currentTime += event.delta;
|
|
2893
|
+
if (event.noteOn && event.noteOn.velocity > 0) {
|
|
2894
|
+
notes.push({
|
|
2895
|
+
pitch: event.noteOn.noteNumber,
|
|
2896
|
+
channel: event.channel ?? 0
|
|
2897
|
+
});
|
|
2898
|
+
} else if (event.noteOff || event.noteOn && event.noteOn.velocity === 0) {
|
|
2899
|
+
const noteOff = event.noteOff || event.noteOn;
|
|
2900
|
+
if (noteOff) {
|
|
2901
|
+
for (let k = notes.length - 1; k >= 0; k--) {
|
|
2902
|
+
if (notes[k].pitch === noteOff.noteNumber && notes[k].end === void 0) {
|
|
2903
|
+
notes[k].end = currentTime;
|
|
2904
|
+
break;
|
|
2905
|
+
}
|
|
2901
2906
|
}
|
|
2902
2907
|
}
|
|
2903
2908
|
}
|
|
@@ -2915,51 +2920,54 @@ var analyzeMidiTracks = (midi) => {
|
|
|
2915
2920
|
return result;
|
|
2916
2921
|
};
|
|
2917
2922
|
var getMidiBPM = (midi) => {
|
|
2918
|
-
const {
|
|
2919
|
-
for (const
|
|
2920
|
-
for (const
|
|
2921
|
-
if (
|
|
2922
|
-
|
|
2923
|
-
return 6e7 / data;
|
|
2923
|
+
const { tracks } = midi;
|
|
2924
|
+
for (const track of tracks) {
|
|
2925
|
+
for (const event of track) {
|
|
2926
|
+
if (event.setTempo && typeof event.setTempo.microsecondsPerQuarter === "number") {
|
|
2927
|
+
return 6e7 / event.setTempo.microsecondsPerQuarter;
|
|
2924
2928
|
}
|
|
2925
|
-
const [b1, b2, b3] = data;
|
|
2926
|
-
return 6e7 / (b1 << 16 | b2 << 8 | b3);
|
|
2927
2929
|
}
|
|
2928
2930
|
}
|
|
2929
2931
|
return 120;
|
|
2930
2932
|
};
|
|
2931
2933
|
var extractMidiPlacements = (midi, selectedTrackIndices) => {
|
|
2932
|
-
const {
|
|
2933
|
-
const ticksPerBeat =
|
|
2934
|
+
const { tracks, division } = midi;
|
|
2935
|
+
const ticksPerBeat = division;
|
|
2934
2936
|
const bpm = getMidiBPM(midi);
|
|
2935
2937
|
const channelNotes = {};
|
|
2936
2938
|
for (const trackIdx of selectedTrackIndices) {
|
|
2937
|
-
const trackData =
|
|
2939
|
+
const trackData = tracks[trackIdx];
|
|
2938
2940
|
if (!trackData) continue;
|
|
2939
2941
|
let currentTime = 0;
|
|
2940
|
-
for (const event of trackData
|
|
2941
|
-
currentTime += event.
|
|
2942
|
+
for (const event of trackData) {
|
|
2943
|
+
currentTime += event.delta;
|
|
2942
2944
|
if (event.channel === 9) continue;
|
|
2943
|
-
if (event.
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
if (isNoteOff) {
|
|
2949
|
-
for (let i = channelNotes[channel].length - 1; i >= 0; i--) {
|
|
2950
|
-
const note = channelNotes[channel][i];
|
|
2951
|
-
if (note.pitch === pitch && note.end === null) {
|
|
2952
|
-
note.end = currentTime;
|
|
2953
|
-
break;
|
|
2954
|
-
}
|
|
2955
|
-
}
|
|
2956
|
-
} else {
|
|
2945
|
+
if (event.noteOn && event.noteOn.velocity > 0) {
|
|
2946
|
+
const pitch = event.noteOn.noteNumber;
|
|
2947
|
+
const velocity = event.noteOn.velocity;
|
|
2948
|
+
const channel = event.channel ?? 0;
|
|
2949
|
+
if (!channelNotes[channel]) channelNotes[channel] = [];
|
|
2957
2950
|
channelNotes[channel].push({
|
|
2958
2951
|
pitch,
|
|
2959
2952
|
velocity,
|
|
2960
2953
|
start: currentTime,
|
|
2961
2954
|
end: null
|
|
2962
2955
|
});
|
|
2956
|
+
} else if (event.noteOff || event.noteOn && event.noteOn.velocity === 0) {
|
|
2957
|
+
const noteOff = event.noteOff || event.noteOn;
|
|
2958
|
+
if (noteOff) {
|
|
2959
|
+
const pitch = noteOff.noteNumber;
|
|
2960
|
+
const channel = event.channel ?? 0;
|
|
2961
|
+
if (channelNotes[channel]) {
|
|
2962
|
+
for (let i = channelNotes[channel].length - 1; i >= 0; i--) {
|
|
2963
|
+
const note = channelNotes[channel][i];
|
|
2964
|
+
if (note.pitch === pitch && note.end === null) {
|
|
2965
|
+
note.end = currentTime;
|
|
2966
|
+
break;
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2963
2971
|
}
|
|
2964
2972
|
}
|
|
2965
2973
|
}
|
|
@@ -3072,33 +3080,36 @@ var extractMidiPlacements = (midi, selectedTrackIndices) => {
|
|
|
3072
3080
|
return { placements, bpm };
|
|
3073
3081
|
};
|
|
3074
3082
|
var extractMidiPlacementsByTrack = (midi, selectedIndices, trackIds) => {
|
|
3075
|
-
const {
|
|
3076
|
-
const ticksPerBeat =
|
|
3083
|
+
const { tracks, division } = midi;
|
|
3084
|
+
const ticksPerBeat = division;
|
|
3077
3085
|
const bpm = getMidiBPM(midi);
|
|
3078
3086
|
const ticksPerStep = ticksPerBeat / STEPS_PER_BEAT;
|
|
3079
3087
|
const placements = [];
|
|
3080
3088
|
selectedIndices.forEach((midiIdx, lane) => {
|
|
3081
3089
|
if (lane >= trackIds.length) return;
|
|
3082
|
-
const trackData =
|
|
3090
|
+
const trackData = tracks[midiIdx];
|
|
3083
3091
|
if (!trackData) return;
|
|
3084
3092
|
const trackId = trackIds[lane];
|
|
3085
3093
|
const active = [];
|
|
3086
3094
|
let currentTime = 0;
|
|
3087
|
-
for (const event of trackData
|
|
3088
|
-
currentTime += event.
|
|
3095
|
+
for (const event of trackData) {
|
|
3096
|
+
currentTime += event.delta;
|
|
3089
3097
|
if (event.channel === 9) continue;
|
|
3090
|
-
if (event.
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
+
if (event.noteOn && event.noteOn.velocity > 0) {
|
|
3099
|
+
const pitch = event.noteOn.noteNumber;
|
|
3100
|
+
const velocity = event.noteOn.velocity;
|
|
3101
|
+
active.push({ pitch, velocity, start: currentTime, end: null });
|
|
3102
|
+
} else if (event.noteOff || event.noteOn && event.noteOn.velocity === 0) {
|
|
3103
|
+
const noteOff = event.noteOff || event.noteOn;
|
|
3104
|
+
if (noteOff) {
|
|
3105
|
+
const pitch = noteOff.noteNumber;
|
|
3106
|
+
for (let i = active.length - 1; i >= 0; i--) {
|
|
3107
|
+
if (active[i].pitch === pitch && active[i].end === null) {
|
|
3108
|
+
active[i].end = currentTime;
|
|
3109
|
+
break;
|
|
3110
|
+
}
|
|
3098
3111
|
}
|
|
3099
3112
|
}
|
|
3100
|
-
} else {
|
|
3101
|
-
active.push({ pitch, velocity, start: currentTime, end: null });
|
|
3102
3113
|
}
|
|
3103
3114
|
}
|
|
3104
3115
|
for (const note of active) {
|
|
@@ -5529,13 +5540,6 @@ var TRACKS_ADVANCED = [
|
|
|
5529
5540
|
color: [100, 255, 160],
|
|
5530
5541
|
instrument: 14,
|
|
5531
5542
|
volume: 100
|
|
5532
|
-
},
|
|
5533
|
-
{
|
|
5534
|
-
id: "t15",
|
|
5535
|
-
name: "TRACK 16",
|
|
5536
|
-
color: [255, 150, 200],
|
|
5537
|
-
instrument: 15,
|
|
5538
|
-
volume: 100
|
|
5539
5543
|
}
|
|
5540
5544
|
];
|
|
5541
5545
|
var DEFAULT_TRACKS = TRACKS_SIMPLE;
|
|
@@ -6437,11 +6441,11 @@ var mountDAW = (target, options = {}) => {
|
|
|
6437
6441
|
lyricCount.textContent = active.lyricModel && n > 0 ? `${n}\u97F3\u7BC0` : "";
|
|
6438
6442
|
};
|
|
6439
6443
|
const syncLyricTerms = () => {
|
|
6440
|
-
const
|
|
6441
|
-
if (
|
|
6444
|
+
const url2 = active.lyricModel ? KOE_VOICEBANK_TERMS[active.lyricModel] : void 0;
|
|
6445
|
+
if (url2) {
|
|
6442
6446
|
const label = lyricModelLabel(active.lyricModel);
|
|
6443
6447
|
lyricTermsLink.textContent = `${label}UTAU\u97F3\u6E90`;
|
|
6444
|
-
lyricTermsLink.href =
|
|
6448
|
+
lyricTermsLink.href = url2;
|
|
6445
6449
|
lyricTerms.classList.remove("dtm-hidden");
|
|
6446
6450
|
} else {
|
|
6447
6451
|
lyricTerms.classList.add("dtm-hidden");
|
|
@@ -6779,9 +6783,9 @@ var mountDAW = (target, options = {}) => {
|
|
|
6779
6783
|
chordTrack.core.addHistoryOnce();
|
|
6780
6784
|
redrawAll();
|
|
6781
6785
|
};
|
|
6782
|
-
const loadMIDI = (bytes) => {
|
|
6786
|
+
const loadMIDI = async (bytes) => {
|
|
6783
6787
|
if (!options.parseMidi) return;
|
|
6784
|
-
const midi = options.parseMidi(bytes);
|
|
6788
|
+
const midi = await options.parseMidi(bytes);
|
|
6785
6789
|
const analysis = analyzeMidiTracks(midi);
|
|
6786
6790
|
const selected = analysis.filter((a) => a.selected).map((a) => a.index);
|
|
6787
6791
|
applyMidiSelection(midi, selected);
|
|
@@ -6945,13 +6949,13 @@ var mountDAW = (target, options = {}) => {
|
|
|
6945
6949
|
});
|
|
6946
6950
|
refs.generateMmlBtn.addEventListener("click", showMML);
|
|
6947
6951
|
refs.exportMidiBtn.addEventListener("click", () => {
|
|
6948
|
-
const
|
|
6949
|
-
const
|
|
6952
|
+
const blob2 = exportMIDI2();
|
|
6953
|
+
const url2 = URL.createObjectURL(blob2);
|
|
6950
6954
|
const a = document.createElement("a");
|
|
6951
|
-
a.href =
|
|
6955
|
+
a.href = url2;
|
|
6952
6956
|
a.download = "dtm.mid";
|
|
6953
6957
|
a.click();
|
|
6954
|
-
URL.revokeObjectURL(
|
|
6958
|
+
URL.revokeObjectURL(url2);
|
|
6955
6959
|
});
|
|
6956
6960
|
const copy = (text, btn) => {
|
|
6957
6961
|
navigator.clipboard?.writeText(text);
|
|
@@ -7018,7 +7022,7 @@ var mountDAW = (target, options = {}) => {
|
|
|
7018
7022
|
refs.overlay.hidden = false;
|
|
7019
7023
|
setLoading(true);
|
|
7020
7024
|
const buffer = new Uint8Array(await file.arrayBuffer());
|
|
7021
|
-
pendingMidi = options.parseMidi(buffer);
|
|
7025
|
+
pendingMidi = await options.parseMidi(buffer);
|
|
7022
7026
|
detectedTracks = analyzeMidiTracks(pendingMidi);
|
|
7023
7027
|
refs.midiTrackSelection.innerHTML = `<span class="dtm-label">\u30C8\u30E9\u30C3\u30AF</span>`;
|
|
7024
7028
|
detectedTracks.forEach((t, i) => {
|
|
@@ -7647,12 +7651,12 @@ var mountMmlPlayer = (target, mml, options = {}) => {
|
|
|
7647
7651
|
termsRow.style.gap = "4px";
|
|
7648
7652
|
termsRow.style.flexWrap = "wrap";
|
|
7649
7653
|
const label = KOE_VOICEBANK_LABELS[model] ?? model;
|
|
7650
|
-
const
|
|
7654
|
+
const url2 = KOE_VOICEBANK_TERMS[model];
|
|
7651
7655
|
const span1 = doc.createElement("span");
|
|
7652
7656
|
span1.textContent = "\u4F7F\u7528\u6642\u306B\u306F";
|
|
7653
7657
|
const a = doc.createElement("a");
|
|
7654
7658
|
a.textContent = `${label}UTAU\u97F3\u6E90`;
|
|
7655
|
-
a.href =
|
|
7659
|
+
a.href = url2;
|
|
7656
7660
|
a.target = "_blank";
|
|
7657
7661
|
a.rel = "noopener";
|
|
7658
7662
|
a.style.color = "var(--dtm-primary)";
|
|
@@ -8121,13 +8125,173 @@ var createPianoRoll = (options, handlers) => {
|
|
|
8121
8125
|
};
|
|
8122
8126
|
};
|
|
8123
8127
|
|
|
8128
|
+
// node_modules/.pnpm/fast-unique-numbers@9.0.27/node_modules/fast-unique-numbers/build/es2019/factories/add-unique-number.js
|
|
8129
|
+
var createAddUniqueNumber = (generateUniqueNumber2) => {
|
|
8130
|
+
return (set) => {
|
|
8131
|
+
const number = generateUniqueNumber2(set);
|
|
8132
|
+
set.add(number);
|
|
8133
|
+
return number;
|
|
8134
|
+
};
|
|
8135
|
+
};
|
|
8136
|
+
|
|
8137
|
+
// node_modules/.pnpm/fast-unique-numbers@9.0.27/node_modules/fast-unique-numbers/build/es2019/factories/cache.js
|
|
8138
|
+
var createCache = (lastNumberWeakMap) => {
|
|
8139
|
+
return (collection, nextNumber) => {
|
|
8140
|
+
lastNumberWeakMap.set(collection, nextNumber);
|
|
8141
|
+
return nextNumber;
|
|
8142
|
+
};
|
|
8143
|
+
};
|
|
8144
|
+
|
|
8145
|
+
// node_modules/.pnpm/fast-unique-numbers@9.0.27/node_modules/fast-unique-numbers/build/es2019/factories/generate-unique-number.js
|
|
8146
|
+
var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER === void 0 ? 9007199254740991 : Number.MAX_SAFE_INTEGER;
|
|
8147
|
+
var TWO_TO_THE_POWER_OF_TWENTY_NINE = 536870912;
|
|
8148
|
+
var TWO_TO_THE_POWER_OF_THIRTY = TWO_TO_THE_POWER_OF_TWENTY_NINE * 2;
|
|
8149
|
+
var createGenerateUniqueNumber = (cache2, lastNumberWeakMap) => {
|
|
8150
|
+
return (collection) => {
|
|
8151
|
+
const lastNumber = lastNumberWeakMap.get(collection);
|
|
8152
|
+
let nextNumber = lastNumber === void 0 ? collection.size : lastNumber < TWO_TO_THE_POWER_OF_THIRTY ? lastNumber + 1 : 0;
|
|
8153
|
+
if (!collection.has(nextNumber)) {
|
|
8154
|
+
return cache2(collection, nextNumber);
|
|
8155
|
+
}
|
|
8156
|
+
if (collection.size < TWO_TO_THE_POWER_OF_TWENTY_NINE) {
|
|
8157
|
+
while (collection.has(nextNumber)) {
|
|
8158
|
+
nextNumber = Math.floor(Math.random() * TWO_TO_THE_POWER_OF_THIRTY);
|
|
8159
|
+
}
|
|
8160
|
+
return cache2(collection, nextNumber);
|
|
8161
|
+
}
|
|
8162
|
+
if (collection.size > MAX_SAFE_INTEGER) {
|
|
8163
|
+
throw new Error("Congratulations, you created a collection of unique numbers which uses all available integers!");
|
|
8164
|
+
}
|
|
8165
|
+
while (collection.has(nextNumber)) {
|
|
8166
|
+
nextNumber = Math.floor(Math.random() * MAX_SAFE_INTEGER);
|
|
8167
|
+
}
|
|
8168
|
+
return cache2(collection, nextNumber);
|
|
8169
|
+
};
|
|
8170
|
+
};
|
|
8171
|
+
|
|
8172
|
+
// node_modules/.pnpm/fast-unique-numbers@9.0.27/node_modules/fast-unique-numbers/build/es2019/module.js
|
|
8173
|
+
var LAST_NUMBER_WEAK_MAP = /* @__PURE__ */ new WeakMap();
|
|
8174
|
+
var cache = createCache(LAST_NUMBER_WEAK_MAP);
|
|
8175
|
+
var generateUniqueNumber = createGenerateUniqueNumber(cache, LAST_NUMBER_WEAK_MAP);
|
|
8176
|
+
var addUniqueNumber = createAddUniqueNumber(generateUniqueNumber);
|
|
8177
|
+
|
|
8178
|
+
// node_modules/.pnpm/broker-factory@3.1.15/node_modules/broker-factory/build/es2019/factories/create-broker.js
|
|
8179
|
+
var createBrokerFactory = (createOrGetOngoingRequests, extendBrokerImplementation, generateUniqueNumber2, isMessagePort2) => (brokerImplementation) => {
|
|
8180
|
+
const fullBrokerImplementation = extendBrokerImplementation(brokerImplementation);
|
|
8181
|
+
return (sender) => {
|
|
8182
|
+
const ongoingRequests = createOrGetOngoingRequests(sender);
|
|
8183
|
+
sender.addEventListener("message", (({ data: message }) => {
|
|
8184
|
+
const { id } = message;
|
|
8185
|
+
if (id !== null && ongoingRequests.has(id)) {
|
|
8186
|
+
const { reject, resolve } = ongoingRequests.get(id);
|
|
8187
|
+
ongoingRequests.delete(id);
|
|
8188
|
+
if (message.error === void 0) {
|
|
8189
|
+
resolve(message.result);
|
|
8190
|
+
} else {
|
|
8191
|
+
reject(new Error(message.error.message));
|
|
8192
|
+
}
|
|
8193
|
+
}
|
|
8194
|
+
}));
|
|
8195
|
+
if (isMessagePort2(sender)) {
|
|
8196
|
+
sender.start();
|
|
8197
|
+
}
|
|
8198
|
+
const call = (method, params = null, transferables = []) => {
|
|
8199
|
+
return new Promise((resolve, reject) => {
|
|
8200
|
+
const id = generateUniqueNumber2(ongoingRequests);
|
|
8201
|
+
ongoingRequests.set(id, { reject, resolve });
|
|
8202
|
+
if (params === null) {
|
|
8203
|
+
sender.postMessage({ id, method }, transferables);
|
|
8204
|
+
} else {
|
|
8205
|
+
sender.postMessage({ id, method, params }, transferables);
|
|
8206
|
+
}
|
|
8207
|
+
});
|
|
8208
|
+
};
|
|
8209
|
+
const notify = (method, params, transferables = []) => {
|
|
8210
|
+
sender.postMessage({ id: null, method, params }, transferables);
|
|
8211
|
+
};
|
|
8212
|
+
let functions = {};
|
|
8213
|
+
for (const [key, handler] of Object.entries(fullBrokerImplementation)) {
|
|
8214
|
+
functions = { ...functions, [key]: handler({ call, notify }) };
|
|
8215
|
+
}
|
|
8216
|
+
return { ...functions };
|
|
8217
|
+
};
|
|
8218
|
+
};
|
|
8219
|
+
|
|
8220
|
+
// node_modules/.pnpm/broker-factory@3.1.15/node_modules/broker-factory/build/es2019/factories/create-or-get-ongoing-requests.js
|
|
8221
|
+
var createCreateOrGetOngoingRequests = (ongoingRequestsMap) => (sender) => {
|
|
8222
|
+
if (ongoingRequestsMap.has(sender)) {
|
|
8223
|
+
return ongoingRequestsMap.get(sender);
|
|
8224
|
+
}
|
|
8225
|
+
const ongoingRequests = /* @__PURE__ */ new Map();
|
|
8226
|
+
ongoingRequestsMap.set(sender, ongoingRequests);
|
|
8227
|
+
return ongoingRequests;
|
|
8228
|
+
};
|
|
8229
|
+
|
|
8230
|
+
// node_modules/.pnpm/broker-factory@3.1.15/node_modules/broker-factory/build/es2019/factories/extend-broker-implementation.js
|
|
8231
|
+
var createExtendBrokerImplementation = (portMap) => (partialBrokerImplementation) => ({
|
|
8232
|
+
...partialBrokerImplementation,
|
|
8233
|
+
connect: ({ call }) => {
|
|
8234
|
+
return async () => {
|
|
8235
|
+
const { port1, port2 } = new MessageChannel();
|
|
8236
|
+
const portId = await call("connect", { port: port1 }, [port1]);
|
|
8237
|
+
portMap.set(port2, portId);
|
|
8238
|
+
return port2;
|
|
8239
|
+
};
|
|
8240
|
+
},
|
|
8241
|
+
disconnect: ({ call }) => {
|
|
8242
|
+
return async (port) => {
|
|
8243
|
+
const portId = portMap.get(port);
|
|
8244
|
+
if (portId === void 0) {
|
|
8245
|
+
throw new Error("The given port is not connected.");
|
|
8246
|
+
}
|
|
8247
|
+
await call("disconnect", { portId });
|
|
8248
|
+
};
|
|
8249
|
+
},
|
|
8250
|
+
isSupported: ({ call }) => {
|
|
8251
|
+
return () => call("isSupported");
|
|
8252
|
+
}
|
|
8253
|
+
});
|
|
8254
|
+
|
|
8255
|
+
// node_modules/.pnpm/broker-factory@3.1.15/node_modules/broker-factory/build/es2019/guards/message-port.js
|
|
8256
|
+
var isMessagePort = (sender) => {
|
|
8257
|
+
return typeof sender.start === "function";
|
|
8258
|
+
};
|
|
8259
|
+
|
|
8260
|
+
// node_modules/.pnpm/broker-factory@3.1.15/node_modules/broker-factory/build/es2019/module.js
|
|
8261
|
+
var createBroker = createBrokerFactory(createCreateOrGetOngoingRequests(/* @__PURE__ */ new WeakMap()), createExtendBrokerImplementation(/* @__PURE__ */ new WeakMap()), generateUniqueNumber, isMessagePort);
|
|
8262
|
+
|
|
8263
|
+
// node_modules/.pnpm/midi-json-parser-broker@4.0.132/node_modules/midi-json-parser-broker/build/es2019/module.js
|
|
8264
|
+
var wrap = createBroker({
|
|
8265
|
+
parseArrayBuffer: ({ call }) => {
|
|
8266
|
+
return async (arrayBuffer) => {
|
|
8267
|
+
return call("parse", { arrayBuffer }, [arrayBuffer]);
|
|
8268
|
+
};
|
|
8269
|
+
}
|
|
8270
|
+
});
|
|
8271
|
+
var load = (url2) => {
|
|
8272
|
+
const worker2 = new Worker(url2);
|
|
8273
|
+
return wrap(worker2);
|
|
8274
|
+
};
|
|
8275
|
+
|
|
8276
|
+
// node_modules/.pnpm/midi-json-parser@8.1.74/node_modules/midi-json-parser/build/es2019/worker/worker.js
|
|
8277
|
+
var worker = `(()=>{var e={455(e,t){!function(e){"use strict";var t=function(e){return function(t){var n=e(t);return t.add(n),n}},n=function(e){return function(t,n){return e.set(t,n),n}},r=void 0===Number.MAX_SAFE_INTEGER?9007199254740991:Number.MAX_SAFE_INTEGER,o=536870912,s=2*o,i=function(e,t){return function(n){var i=t.get(n),a=void 0===i?n.size:i<s?i+1:0;if(!n.has(a))return e(n,a);if(n.size<o){for(;n.has(a);)a=Math.floor(Math.random()*s);return e(n,a)}if(n.size>r)throw new Error("Congratulations, you created a collection of unique numbers which uses all available integers!");for(;n.has(a);)a=Math.floor(Math.random()*r);return e(n,a)}},a=new WeakMap,f=n(a),c=i(f,a),u=t(c);e.addUniqueNumber=u,e.generateUniqueNumber=c}(t)}},t={};function n(r){var o=t[r];if(void 0!==o)return o.exports;var s=t[r]={exports:{}};return e[r].call(s.exports,s,s.exports,n),s.exports}(()=>{"use strict";const e=-32603,t=-32602,r=-32601,o=(e,t)=>Object.assign(new Error(e),{status:t}),s=t=>o('The handler of the method called "'.concat(t,'" returned an unexpected result.'),e),i=(t,n)=>async({data:{id:i,method:a,params:f}})=>{const c=n[a];try{if(void 0===c)throw(e=>o('The requested method called "'.concat(e,'" is not supported.'),r))(a);const n=void 0===f?c():c(f);if(void 0===n)throw(t=>o('The handler of the method called "'.concat(t,'" returned no required result.'),e))(a);const u=n instanceof Promise?await n:n;if(null===i){if(void 0!==u.result)throw s(a)}else{if(void 0===u.result)throw s(a);const{result:e,transferables:n=[]}=u;t.postMessage({id:i,result:e},n)}}catch(e){const{message:n,status:r=-32603}=e;t.postMessage({error:{code:r,message:n},id:i})}};var a=n(455);const f=new Map,c=(e,n,r)=>({...n,connect:({port:t})=>{t.start();const r=e(t,n),o=(0,a.generateUniqueNumber)(f);return f.set(o,()=>{r(),t.close(),f.delete(o)}),{result:o}},disconnect:({portId:e})=>{const n=f.get(e);if(void 0===n)throw(e=>o('The specified parameter called "portId" with the given value "'.concat(e,'" does not identify a port connected to this worker.'),t))(e);return n(),{result:null}},isSupported:async()=>{if(await new Promise(e=>{const t=new ArrayBuffer(0),{port1:n,port2:r}=new MessageChannel;n.onmessage=({data:t})=>e(null!==t),r.postMessage(t,[t])})){const e=r();return{result:e instanceof Promise?await e:e}}return{result:!1}}}),u=(e,t,n=()=>!0)=>{const r=c(u,t,n),o=i(e,r);return e.addEventListener("message",o),()=>e.removeEventListener("message",o)},l=e=>void 0!==e.channel,d=e=>e.toString(16).toUpperCase().padStart(2,"0"),g=(e,t=0,n=e.byteLength-(t-e.byteOffset))=>{const r=t+e.byteOffset,o=[],s=new Uint8Array(e.buffer,r,n);for(let e=0;e<n;e+=1)o[e]=d(s[e]);return o.join("")},h=(e,t=0,n=e.byteLength-(t-e.byteOffset))=>{const r=t+e.byteOffset,o=new Uint8Array(e.buffer,r,n);return String.fromCharCode.apply(null,o)},m=e=>{const t=new DataView(e),n=v(t);let r=14;const o=[];for(let e=0,s=n.numberOfTracks;e<s;e+=1){let e;({offset:r,track:e}=b(t,r)),o.push(e)}return{division:n.division,format:n.format,tracks:o}},p=(e,t,n)=>{let r;const{offset:o,value:s}=T(e,t),i=e.getUint8(o);return r=240===i?y(e,o+1):255===i?U(e,o+1):w(i,e,o+1,n),{...r,event:{...r.event,delta:s},eventTypeByte:i}},v=e=>{if(e.byteLength<14)throw new Error("Expected at least 14 bytes instead of ".concat(e.byteLength));if("MThd"!==h(e,0,4))throw new Error('Unexpected characters "'.concat(h(e,0,4),'" found instead of "MThd"'));if(6!==e.getUint32(4))throw new Error("The header has an unexpected length of ".concat(e.getUint32(4)," instead of 6"));const t=e.getUint16(8),n=e.getUint16(10);return{division:e.getUint16(12),format:t,numberOfTracks:n}},U=(e,t)=>{let n;const r=e.getUint8(t),{offset:o,value:s}=T(e,t+1);if(1===r)n={text:h(e,o,s)};else if(2===r)n={copyrightNotice:h(e,o,s)};else if(3===r)n={trackName:h(e,o,s)};else if(4===r)n={instrumentName:h(e,o,s)};else if(5===r)n={lyric:h(e,o,s)};else if(6===r)n={marker:h(e,o,s)};else if(7===r)n={cuePoint:h(e,o,s)};else if(8===r)n={programName:h(e,o,s)};else if(9===r)n={deviceName:h(e,o,s)};else if(10===r||11===r||12===r||13===r||14===r||15===r)n={metaTypeByte:d(r),text:h(e,o,s)};else if(32===r)n={channelPrefix:e.getUint8(o)};else if(33===r)n={midiPort:e.getUint8(o)};else if(47===r)n={endOfTrack:!0};else if(81===r)n={setTempo:{microsecondsPerQuarter:(e.getUint8(o)<<16)+(e.getUint8(o+1)<<8)+e.getUint8(o+2)}};else if(84===r){let t;const r=e.getUint8(o);96&r?32==(96&r)?t=25:64==(96&r)?t=29:96&~r||(t=30):t=24,n={smpteOffset:{frame:e.getUint8(o+3),frameRate:t,hour:31&r,minutes:e.getUint8(o+1),seconds:e.getUint8(o+2),subFrame:e.getUint8(o+4)}}}else if(88===r)n={timeSignature:{denominator:Math.pow(2,e.getUint8(o+1)),metronome:e.getUint8(o+2),numerator:e.getUint8(o),thirtyseconds:e.getUint8(o+3)}};else if(89===r)n={keySignature:{key:e.getInt8(o),scale:e.getInt8(o+1)}};else{if(127!==r)throw new Error('Cannot parse a meta event with a type of "'.concat(d(r),'"'));n={sequencerSpecificData:g(e,o,s)}}return{event:n,offset:o+s}},w=(e,t,n,r)=>{const o=128&e?null:r,s=(null===o?e:o)>>4;let i,a=null===o?n:n-1;if(8===s)i={noteOff:{noteNumber:t.getUint8(a),velocity:t.getUint8(a+1)}},a+=2;else if(9===s){const e=t.getUint8(a),n=t.getUint8(a+1);i=0===n?{noteOff:{noteNumber:e,velocity:n}}:{noteOn:{noteNumber:e,velocity:n}},a+=2}else if(10===s)i={keyPressure:{noteNumber:t.getUint8(a),pressure:t.getUint8(a+1)}},a+=2;else if(11===s)i={controlChange:{type:t.getUint8(a),value:t.getUint8(a+1)}},a+=2;else if(12===s)i={programChange:{programNumber:t.getUint8(a)}},a+=1;else if(13===s)i={channelPressure:{pressure:t.getUint8(a)}},a+=1;else{if(14!==s)throw new Error('Cannot parse a midi event with a type of "'.concat(d(s),'"'));i={pitchBend:t.getUint8(a)|t.getUint8(a+1)<<7},a+=2}return i.channel=15&(null===o?e:o),{event:i,offset:a}},y=(e,t)=>{const{offset:n,value:r}=T(e,t);return{event:{sysex:g(e,n,r)},offset:n+r}},b=(e,t)=>{if("MTrk"!==h(e,t,4))throw new Error('Unexpected characters "'.concat(h(e,t,4),'" found instead of "MTrk"'));const n=[],r=e.getUint32(t+4)+t+8;let o=null,s=t+8;for(;s<r;){const t=p(e,s,o),{event:r,eventTypeByte:i}=t;n.push(r),s=t.offset,l(r)&&(128&i)>0&&(o=i)}return{offset:s,track:n}},T=(e,t)=>{let n=t,r=0;for(;;){const t=e.getUint8(n);if(n+=1,!(t>127))return r+=t,{offset:n,value:r};r+=127&t,r<<=7}};u(self,{parse:({arrayBuffer:e})=>({result:m(e)})})})()})();`;
|
|
8278
|
+
|
|
8279
|
+
// node_modules/.pnpm/midi-json-parser@8.1.74/node_modules/midi-json-parser/build/es2019/module.js
|
|
8280
|
+
var blob = new Blob([worker], { type: "application/javascript; charset=utf-8" });
|
|
8281
|
+
var url = URL.createObjectURL(blob);
|
|
8282
|
+
var midiJsonParser = load(url);
|
|
8283
|
+
var connect = midiJsonParser.connect;
|
|
8284
|
+
var disconnect = midiJsonParser.disconnect;
|
|
8285
|
+
var isSupported = midiJsonParser.isSupported;
|
|
8286
|
+
var parseArrayBuffer = midiJsonParser.parseArrayBuffer;
|
|
8287
|
+
URL.revokeObjectURL(url);
|
|
8288
|
+
|
|
8124
8289
|
// src/studio.ts
|
|
8125
8290
|
var import_meta = {};
|
|
8126
8291
|
var DEFAULT_CDN = {
|
|
8127
8292
|
soundFont: "https://rpgen3.github.io/soundfont/mjs/surikov/SoundFont.mjs",
|
|
8128
8293
|
soundFontDrum: "https://rpgen3.github.io/soundfont/mjs/surikov/SoundFont_drum.mjs",
|
|
8129
|
-
soundFontList: "https://rpgen3.github.io/soundfont/mjs/surikov/SoundFont_list.mjs"
|
|
8130
|
-
midiParser: "https://cdn.jsdelivr.net/npm/midi-parser-js@4.0.4/+esm"
|
|
8294
|
+
soundFontList: "https://rpgen3.github.io/soundfont/mjs/surikov/SoundFont_list.mjs"
|
|
8131
8295
|
};
|
|
8132
8296
|
var SOUNDFONT_NAME = "FluidR3_GM_sf2_file";
|
|
8133
8297
|
var TRACK_ROLES = ["melody", "submelody", "bass", "chord"];
|
|
@@ -8138,10 +8302,10 @@ var resolveDefaultVoiceWorkerUrl = () => {
|
|
|
8138
8302
|
return void 0;
|
|
8139
8303
|
}
|
|
8140
8304
|
};
|
|
8141
|
-
var importFrom = async (
|
|
8305
|
+
var importFrom = async (url2, name) => {
|
|
8142
8306
|
const mod = await import(
|
|
8143
8307
|
/* @vite-ignore */
|
|
8144
|
-
|
|
8308
|
+
url2
|
|
8145
8309
|
);
|
|
8146
8310
|
return mod[name] ?? mod.default;
|
|
8147
8311
|
};
|
|
@@ -8170,23 +8334,17 @@ var createDtmStudio = async (options = {}) => {
|
|
|
8170
8334
|
eng.SoundFont_drum ?? importFrom(cdn.soundFontDrum, "SoundFont_drum"),
|
|
8171
8335
|
eng.SoundFont_list ?? importFrom(cdn.soundFontList, "SoundFont_list")
|
|
8172
8336
|
]);
|
|
8173
|
-
let midiParser = null;
|
|
8174
8337
|
let parseMidi;
|
|
8175
8338
|
if (features.midi) {
|
|
8176
|
-
parseMidi = eng.parseMidi
|
|
8177
|
-
|
|
8178
|
-
|
|
8179
|
-
|
|
8180
|
-
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
|
|
8184
|
-
|
|
8185
|
-
parseMidi = (bytes) => {
|
|
8186
|
-
if (!midiParser) throw new Error("midi-parser not ready");
|
|
8187
|
-
return midiParser.parse(bytes);
|
|
8188
|
-
};
|
|
8189
|
-
}
|
|
8339
|
+
parseMidi = eng.parseMidi || ((bytes) => {
|
|
8340
|
+
const buffer = bytes.buffer;
|
|
8341
|
+
if (buffer instanceof ArrayBuffer) {
|
|
8342
|
+
return parseArrayBuffer(
|
|
8343
|
+
buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength)
|
|
8344
|
+
);
|
|
8345
|
+
}
|
|
8346
|
+
throw new Error("SharedArrayBuffer is not supported for MIDI parsing");
|
|
8347
|
+
});
|
|
8190
8348
|
}
|
|
8191
8349
|
const voiceWorkerUrl = options.voiceWorkerUrl === null ? void 0 : options.voiceWorkerUrl ?? resolveDefaultVoiceWorkerUrl();
|
|
8192
8350
|
const singingVoices = createSingingVoices(audioCtx, masterGain, {
|
|
@@ -8237,13 +8395,13 @@ var createDtmStudio = async (options = {}) => {
|
|
|
8237
8395
|
clamp4(Math.round(wave[i] * 32768), -32768, 32767),
|
|
8238
8396
|
true
|
|
8239
8397
|
);
|
|
8240
|
-
const
|
|
8241
|
-
const
|
|
8398
|
+
const blob2 = new Blob([view], { type: "audio/wav" });
|
|
8399
|
+
const url2 = URL.createObjectURL(blob2);
|
|
8242
8400
|
const a = document.createElement("a");
|
|
8243
|
-
a.href =
|
|
8401
|
+
a.href = url2;
|
|
8244
8402
|
a.download = "record.wav";
|
|
8245
8403
|
a.click();
|
|
8246
|
-
URL.revokeObjectURL(
|
|
8404
|
+
URL.revokeObjectURL(url2);
|
|
8247
8405
|
};
|
|
8248
8406
|
const onToggleRecord = recorder ? () => {
|
|
8249
8407
|
if (recorder.isRecording()) {
|