@onjmin/dtm 2.0.2 → 2.0.3

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/dist/index.js CHANGED
@@ -62,6 +62,7 @@ __export(index_exports, {
62
62
  VIBRATO_MIN_SEC: () => VIBRATO_MIN_SEC,
63
63
  VOICE_IMAGES: () => VOICE_IMAGES,
64
64
  VOICE_IMAGE_KEY: () => VOICE_IMAGE_KEY,
65
+ addUnits: () => addUnits,
65
66
  analyzeMidiTracks: () => analyzeMidiTracks,
66
67
  applyHarmonicFilter: () => applyHarmonicFilter,
67
68
  applyMonophonic: () => applyMonophonic,
@@ -106,6 +107,7 @@ __export(index_exports, {
106
107
  isValidHttpUrl: () => isValidHttpUrl,
107
108
  keyCountFor: () => keyCountFor,
108
109
  koeUrl: () => koeUrl,
110
+ midiNote: () => midiNote,
109
111
  midiToUnits: () => midiToUnits,
110
112
  mountChordPlayer: () => mountChordPlayer,
111
113
  mountDAW: () => mountDAW,
@@ -133,6 +135,7 @@ __export(index_exports, {
133
135
  stripLyrics: () => stripLyrics,
134
136
  stripMmlMeta: () => stripMmlMeta,
135
137
  transposeNotes: () => transposeNotes,
138
+ units: () => units,
136
139
  unitsPerRow: () => unitsPerRow,
137
140
  unitsPerStep: () => unitsPerStep,
138
141
  unitsToHz: () => unitsToHz,
@@ -1714,6 +1717,9 @@ var createChannelStrip = (ctx, destination, options = {}) => {
1714
1717
  };
1715
1718
 
1716
1719
  // src/tuning.ts
1720
+ var units = (n) => n;
1721
+ var midiNote = (n) => n;
1722
+ var addUnits = (a, delta) => a + delta;
1717
1723
  var UNITS_PER_OCTAVE = 372;
1718
1724
  var UNITS_PER_SEMITONE = 372 / 12;
1719
1725
  var UNITS_PER_EDO31_DEGREE = 372 / 31;
@@ -1723,13 +1729,13 @@ var A4_HZ = 440;
1723
1729
  var DEFAULT_EDO = 12;
1724
1730
  var unitsPerStep = (edo) => UNITS_PER_OCTAVE / edo;
1725
1731
  var midiToUnits = (midi) => midi * UNITS_PER_SEMITONE;
1726
- var unitsToMidi = (units) => units / UNITS_PER_SEMITONE;
1727
- var unitsToHz = (units) => A4_HZ * 2 ** ((units - A4_UNITS) / UNITS_PER_OCTAVE);
1728
- var unitsToMidiDetune = (units) => {
1729
- const midi = Math.round(units / UNITS_PER_SEMITONE);
1732
+ var unitsToMidi = (u) => u / UNITS_PER_SEMITONE;
1733
+ var unitsToHz = (u) => A4_HZ * 2 ** ((u - A4_UNITS) / UNITS_PER_OCTAVE);
1734
+ var unitsToMidiDetune = (u) => {
1735
+ const midi = Math.round(u / UNITS_PER_SEMITONE);
1730
1736
  return {
1731
1737
  midi,
1732
- detuneCents: (units - midi * UNITS_PER_SEMITONE) * CENTS_PER_UNIT
1738
+ detuneCents: (u - midi * UNITS_PER_SEMITONE) * CENTS_PER_UNIT
1733
1739
  };
1734
1740
  };
1735
1741
  var NATURAL_STEPS = {
@@ -1755,7 +1761,7 @@ var fifthToStep = (fifthIndex, edo) => {
1755
1761
  var fifthToUnits = (fifthIndex, edo) => fifthToStep(fifthIndex, edo) * unitsPerStep(edo);
1756
1762
  var PITCH_ENCODING_VERSION = 2;
1757
1763
  var pitchV1ToUnits = (pitch) => pitch * UNITS_PER_SEMITONE;
1758
- var unitsToPitchV1 = (units) => Math.round(units / UNITS_PER_SEMITONE);
1764
+ var unitsToPitchV1 = (u) => Math.round(u / UNITS_PER_SEMITONE);
1759
1765
 
1760
1766
  // src/chords.ts
1761
1767
  var C3 = 48;
@@ -1768,7 +1774,9 @@ var chordToneToUnits = (relSemitone, relFifth, rootSemitone, rootFifth, edo) =>
1768
1774
  const relWithin12 = (relSemitone % 12 + 12) % 12;
1769
1775
  const relOct = Math.round((relSemitone - relWithin12) / 12);
1770
1776
  const relStep = (fifthToStep(relFifth, edo) - fifthToStep(rootFifth, edo) + edo) % edo;
1771
- return (rootOct + relOct) * UNITS_PER_OCTAVE + (rootStep + relStep) * perStep;
1777
+ return units(
1778
+ (rootOct + relOct) * UNITS_PER_OCTAVE + (rootStep + relStep) * perStep
1779
+ );
1772
1780
  };
1773
1781
  var buildChordPlacements = (options) => {
1774
1782
  const {
@@ -2344,7 +2352,7 @@ var Worldline = class _Worldline {
2344
2352
  const WL = this.wasm;
2345
2353
  const FS = WORLDLINE_SAMPLE_RATE;
2346
2354
  const basePitch = sampleCurve(preMs + durationMs / 2, pitch, preMs + durationMs);
2347
- const midiNote = Math.round(69 + 12 * Math.log2(basePitch / 440));
2355
+ const midiNote2 = Math.round(69 + 12 * Math.log2(basePitch / 440));
2348
2356
  const posMs = 0;
2349
2357
  const reqLen = preMs + durationMs;
2350
2358
  const cutMs = WL_FRAME_MS * 2;
@@ -2368,7 +2376,7 @@ var Worldline = class _Worldline {
2368
2376
  sv(8, samplePtr, "*");
2369
2377
  sv(12, 0, "i32");
2370
2378
  sv(16, 0, "*");
2371
- sv(20, midiNote, "i32");
2379
+ sv(20, midiNote2, "i32");
2372
2380
  sv(24, 100, "double");
2373
2381
  sv(32, 0, "double");
2374
2382
  sv(40, reqLen, "double");
@@ -2865,8 +2873,8 @@ var FORMANTS = {
2865
2873
  // 撥音(ん)は鼻音寄りの低フォルマント
2866
2874
  N: [250, 1e3]
2867
2875
  };
2868
- var unitsToFreq = (units) => 440 * 2 ** ((units - 2139) / 372);
2869
- var unitsToMidiFloat = (units) => units / 31;
2876
+ var unitsToFreq = (units2) => 440 * 2 ** ((units2 - 2139) / 372);
2877
+ var unitsToMidiFloat = (units2) => units2 / 31;
2870
2878
  var createKlattVoice = (ctx, destination, reverbBus, delayBus) => {
2871
2879
  const active = /* @__PURE__ */ new Set();
2872
2880
  const voice = (syllable, e) => {
@@ -3675,7 +3683,7 @@ var createSingingVoices = (ctx, destination, options = {}) => {
3675
3683
  };
3676
3684
  dispatchNote(note.pitch, 1);
3677
3685
  for (const offset of octaveUnisonOffsets(track.octaveUnison)) {
3678
- dispatchNote(note.pitch + offset, OCTAVE_UNISON_PEAK_SCALE);
3686
+ dispatchNote(units(note.pitch + offset), OCTAVE_UNISON_PEAK_SCALE);
3679
3687
  }
3680
3688
  if (!(model.renderToCache && model.scheduleCached)) {
3681
3689
  await new Promise((resolve) => setTimeout(resolve, 0));
@@ -4101,7 +4109,9 @@ var parseMML = (mml, options = {}) => {
4101
4109
  let pitchSteps = naturals[c];
4102
4110
  j++;
4103
4111
  pitchSteps += readAccidentals();
4104
- chordNotes.push((octave + 1) * 372 + pitchSteps * unitsPerStep2);
4112
+ chordNotes.push(
4113
+ units((octave + 1) * 372 + pitchSteps * unitsPerStep2)
4114
+ );
4105
4115
  } else if (c === ">") {
4106
4116
  octave = Math.min(8, octave + 1);
4107
4117
  j++;
@@ -4139,7 +4149,7 @@ var parseMML = (mml, options = {}) => {
4139
4149
  let pitchSteps = naturals[ch];
4140
4150
  j++;
4141
4151
  pitchSteps += readAccidentals();
4142
- const midiPitch = (octave + 1) * 372 + pitchSteps * unitsPerStep2;
4152
+ const midiPitch = units((octave + 1) * 372 + pitchSteps * unitsPerStep2);
4143
4153
  const steps = parseLength();
4144
4154
  recordContributor();
4145
4155
  placements.push({
@@ -9996,7 +10006,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
9996
10006
  if (n.startStep < fromStep) continue;
9997
10007
  notes.push({
9998
10008
  syllable: lt.syllables[i2],
9999
- pitch: n.pitchUnits + semis,
10009
+ pitch: units(n.pitchUnits + semis),
10000
10010
  startSec: (n.startStep - fromStep) * secondsPerStep,
10001
10011
  durationSec: n.durationSteps * secondsPerStep * gate
10002
10012
  });
@@ -12416,7 +12426,7 @@ var generateRandomPattern = (core, options) => {
12416
12426
  for (let i2 = 0; i2 < 12; i2++) {
12417
12427
  const noteInOctave = (i2 - rootOffset + 12) % 12;
12418
12428
  if (scale.includes(noteInOctave))
12419
- availablePitches.push(basePitch + semitoneToStep(i2) * upr);
12429
+ availablePitches.push(units(basePitch + semitoneToStep(i2) * upr));
12420
12430
  }
12421
12431
  core.beginBatch();
12422
12432
  for (let bar = 0; bar < numBars; bar++) {
@@ -12531,9 +12541,11 @@ var transposeNotes = (cores, steps) => {
12531
12541
  for (const core of cores) {
12532
12542
  const notes = [...core.getNotes()];
12533
12543
  for (const note of notes) {
12534
- const newPitch = Math.max(
12535
- PITCH_RANGE_START,
12536
- Math.min(PITCH_RANGE_END, note.pitchUnits + steps)
12544
+ const newPitch = units(
12545
+ Math.max(
12546
+ PITCH_RANGE_START,
12547
+ Math.min(PITCH_RANGE_END, note.pitchUnits + steps)
12548
+ )
12537
12549
  );
12538
12550
  if (newPitch !== note.pitchUnits) {
12539
12551
  core.moveNote(note.id, note.startStep, newPitch);
@@ -13387,9 +13399,8 @@ var MMLCore = class _MMLCore {
13387
13399
  const upr = cfg.unitsPerRow ?? UNITS_PER_SEMITONE;
13388
13400
  const pitchRangeStart = cfg.pitchRangeStart;
13389
13401
  const pitchRangeEnd = pitchRangeStart + (cfg.keyCount - 1) * upr;
13390
- const clampedPitch = Math.min(
13391
- Math.max(pitch, pitchRangeStart),
13392
- pitchRangeEnd
13402
+ const clampedPitch = units(
13403
+ Math.min(Math.max(pitch, pitchRangeStart), pitchRangeEnd)
13393
13404
  );
13394
13405
  const clampedStart = Math.min(
13395
13406
  Math.max(startStep, 0),
@@ -13783,12 +13794,12 @@ var createRenderer = (mountTarget, width = 800, height = 450, config) => {
13783
13794
  const MICRO_RATIO = 0.45;
13784
13795
  for (let y = startY; y < endY; y += keyHeight) {
13785
13796
  const rowIndex = keyCount - 1 - y / keyHeight;
13786
- const units = pitchRangeStart + rowIndex * upr;
13797
+ const units2 = pitchRangeStart + rowIndex * upr;
13787
13798
  const step = Math.round(
13788
- (units % UNITS_PER_OCTAVE + UNITS_PER_OCTAVE) % UNITS_PER_OCTAVE / upr % edo
13799
+ (units2 % UNITS_PER_OCTAVE + UNITS_PER_OCTAVE) % UNITS_PER_OCTAVE / upr % edo
13789
13800
  );
13790
13801
  const tier = keyTier(step, edo);
13791
- const octave = Math.floor(units / UNITS_PER_OCTAVE) - 1;
13802
+ const octave = Math.floor(units2 / UNITS_PER_OCTAVE) - 1;
13792
13803
  const isC4Range = octave === 4;
13793
13804
  const screenY = y - g_draw_offset_y;
13794
13805
  const bkW = Math.floor(
@@ -13888,13 +13899,13 @@ var createRenderer = (mountTarget, width = 800, height = 450, config) => {
13888
13899
  const endY = g_draw_offset_y + g_grid_canvas.height;
13889
13900
  for (let y = startY; y < endY; y += keyHeight) {
13890
13901
  const rowIndex = keyCount - 1 - y / keyHeight;
13891
- const units = pitchRangeStart + rowIndex * upr;
13902
+ const units2 = pitchRangeStart + rowIndex * upr;
13892
13903
  const step = Math.round(
13893
- (units % UNITS_PER_OCTAVE + UNITS_PER_OCTAVE) % UNITS_PER_OCTAVE / upr % edo
13904
+ (units2 % UNITS_PER_OCTAVE + UNITS_PER_OCTAVE) % UNITS_PER_OCTAVE / upr % edo
13894
13905
  );
13895
13906
  const tier = keyTier(step, edo);
13896
13907
  const isC = step === 0;
13897
- const octave = Math.floor(units / UNITS_PER_OCTAVE) - 1;
13908
+ const octave = Math.floor(units2 / UNITS_PER_OCTAVE) - 1;
13898
13909
  const isC4Range = octave === 4;
13899
13910
  const screenY = y - g_draw_offset_y;
13900
13911
  g_grid_ctx.fillStyle = g_bg_active ? tier === 2 ? "rgba(8,11,22,0.55)" : tier === 1 ? "rgba(12,16,30,0.5)" : "rgba(17,22,40,0.45)" : tier === 2 ? "#080b16" : tier === 1 ? "#0c101d" : "#111628";
@@ -14075,7 +14086,7 @@ var createRenderer = (mountTarget, width = 800, height = 450, config) => {
14075
14086
  const step = Math.floor((x2 + g_draw_offset_x) / stepWidth);
14076
14087
  const absoluteY = y + g_draw_offset_y;
14077
14088
  const yIndex = Math.floor(absoluteY / keyHeight);
14078
- const pitch = pitchRangeStart + (keyCount - 1 - yIndex) * upr;
14089
+ const pitch = units(pitchRangeStart + (keyCount - 1 - yIndex) * upr);
14079
14090
  return { step, pitch, x: x2, y };
14080
14091
  };
14081
14092
  const onClick = (callback) => {
@@ -14093,7 +14104,7 @@ var createRenderer = (mountTarget, width = 800, height = 450, config) => {
14093
14104
  const step = Math.floor((x2 + g_draw_offset_x) / stepWidth);
14094
14105
  const absoluteY = y + g_draw_offset_y;
14095
14106
  const yIndex = Math.floor(absoluteY / keyHeight);
14096
- const pitch = pitchRangeStart + (keyCount - 1 - yIndex) * upr;
14107
+ const pitch = units(pitchRangeStart + (keyCount - 1 - yIndex) * upr);
14097
14108
  if (pitch >= pitchRangeStart && pitch < pitchRangeStart + keyCount) {
14098
14109
  requestAnimationFrame(() => callback(step, pitch));
14099
14110
  }
@@ -14800,9 +14811,9 @@ var mountDAW = (target, options = {}) => {
14800
14811
  options.singingVoices?.setVolume(masterVolume / 100);
14801
14812
  };
14802
14813
  applyMasterVolume(masterVolume);
14803
- const snapToEdoGrid = (units) => {
14814
+ const snapToEdoGrid = (u) => {
14804
14815
  const upr = renderConfig.unitsPerRow ?? UNITS_PER_SEMITONE;
14805
- return Math.round(units / upr) * upr;
14816
+ return units(Math.round(u / upr) * upr);
14806
14817
  };
14807
14818
  const applyEdo = (edo, opts) => {
14808
14819
  const next = edo === 31 ? 31 : 12;
@@ -14815,7 +14826,7 @@ var mountDAW = (target, options = {}) => {
14815
14826
  for (const t of trackStates) {
14816
14827
  t.core.beginBatch();
14817
14828
  for (const note of [...t.core.getNotes()]) {
14818
- const snapped = Math.round(note.pitchUnits / upr) * upr;
14829
+ const snapped = units(Math.round(note.pitchUnits / upr) * upr);
14819
14830
  if (snapped !== note.pitchUnits)
14820
14831
  t.core.moveNote(note.id, note.startStep, snapped);
14821
14832
  }
@@ -15515,7 +15526,7 @@ var mountDAW = (target, options = {}) => {
15515
15526
  if (dragState.mode === "move") {
15516
15527
  const nextStart = step - dragState.dragOffsetStep;
15517
15528
  const snappedStart = Math.round(nextStart / snapGridSteps) * snapGridSteps;
15518
- const nextPitch = pitch - dragState.dragOffsetPitch;
15529
+ const nextPitch = units(pitch - dragState.dragOffsetPitch);
15519
15530
  if (hasNoteAt(snappedStart, nextPitch, dragState.noteId)) return;
15520
15531
  active.core.moveNote(dragState.noteId, snappedStart, nextPitch);
15521
15532
  if (nextPitch !== dragState.lastPreviewPitch) {
@@ -15571,7 +15582,7 @@ var mountDAW = (target, options = {}) => {
15571
15582
  for (const note of selectedNotes) {
15572
15583
  const orig = selectedOriginal.find((o) => o.id === note.id);
15573
15584
  if (!orig) continue;
15574
- const newPitch = orig.pitch + deltaPitch;
15585
+ const newPitch = units(orig.pitch + deltaPitch);
15575
15586
  if (newPitch >= PITCH_RANGE_START && newPitch <= PITCH_RANGE_END)
15576
15587
  active.core.moveNote(
15577
15588
  note.id,
@@ -15583,7 +15594,7 @@ var mountDAW = (target, options = {}) => {
15583
15594
  const grab = selectedNotes[0];
15584
15595
  const orig = selectedOriginal.find((o) => o.id === grab.id);
15585
15596
  if (orig) {
15586
- const newGrab = orig.pitch + deltaPitch;
15597
+ const newGrab = units(orig.pitch + deltaPitch);
15587
15598
  if (newGrab !== lastMultiPreviewPitch && newGrab >= 0 && newGrab < 128) {
15588
15599
  lastMultiPreviewPitch = newGrab;
15589
15600
  playPreview(newGrab);
@@ -15902,7 +15913,7 @@ var mountDAW = (target, options = {}) => {
15902
15913
  if (n.startStep < fromStep) continue;
15903
15914
  notes.push({
15904
15915
  syllable: lt.syllables[i2],
15905
- pitch: n.pitchUnits + semis,
15916
+ pitch: units(n.pitchUnits + semis),
15906
15917
  startSec: (n.startStep - fromStep) * secondsPerStep,
15907
15918
  durationSec: n.durationSteps * secondsPerStep * gate
15908
15919
  });
@@ -17108,7 +17119,7 @@ var mountDAW = (target, options = {}) => {
17108
17119
  }
17109
17120
  if (candidateNotes.length === 0) return null;
17110
17121
  const sum = candidateNotes.reduce((acc, note) => acc + note.pitchUnits, 0);
17111
- return Math.round(sum / candidateNotes.length);
17122
+ return units(Math.round(sum / candidateNotes.length));
17112
17123
  };
17113
17124
  const centerPitch = (pitch) => {
17114
17125
  const canvas = renderer.getGridCanvas();
@@ -17429,8 +17440,6 @@ var mountDAW = (target, options = {}) => {
17429
17440
  active.vocalOctaveUnison = "none";
17430
17441
  } else {
17431
17442
  clearAll();
17432
- applyEdo(12);
17433
- refs.edoSelect.value = String(renderConfig.edo ?? 12);
17434
17443
  for (const t of trackStates) t.core.setLoadMode(true);
17435
17444
  for (const t of trackStates) {
17436
17445
  t.lyrics = "";
@@ -17679,11 +17688,20 @@ var mountDAW = (target, options = {}) => {
17679
17688
  return;
17680
17689
  }
17681
17690
  }
17682
- applyEdo(next, { snap: true });
17683
- const first = getFirstDetectedPitch();
17684
- centerPitch(first ?? pitchV1ToUnits(48));
17685
- redrawAll();
17686
- updateUndoRedo();
17691
+ overlayDuring(() => {
17692
+ applyEdo(next, { snap: true });
17693
+ if (next === 31 && prev === 12) {
17694
+ zoomY = Math.max(50, Math.round(zoomY / 2 / 25) * 25);
17695
+ } else if (next === 12 && prev === 31) {
17696
+ zoomY = Math.min(200, Math.round(zoomY * 2 / 25) * 25);
17697
+ }
17698
+ applyZoomY();
17699
+ const first = getFirstDetectedPitch();
17700
+ centerPitch(first ?? pitchV1ToUnits(48));
17701
+ redrawAll();
17702
+ updateUndoRedo();
17703
+ notifyViewState();
17704
+ });
17687
17705
  });
17688
17706
  refs.edoInfoBtn.addEventListener("click", () => {
17689
17707
  showModal("\u97F3\u5F8B\u306E\u89E3\u8AAC", EDO_INFO_HTML);
@@ -19056,7 +19074,7 @@ var playSingingMML = async (mml, options = {}) => {
19056
19074
  if (n.startStep < fromStep) continue;
19057
19075
  notes.push({
19058
19076
  syllable: lt.syllables[i2],
19059
- pitch: n.pitchUnits + semis,
19077
+ pitch: units(n.pitchUnits + semis),
19060
19078
  startSec: (n.startStep - fromStep) * secondsPerStep,
19061
19079
  durationSec: n.durationSteps * secondsPerStep * gate
19062
19080
  });
@@ -19339,7 +19357,7 @@ var createPianoRoll = (options, handlers) => {
19339
19357
  const pitchDelta = nextPitch2 - baseNote.pitchUnits;
19340
19358
  for (const note of dragState.selectedNotes) {
19341
19359
  const newStart = note.startStep + stepDelta;
19342
- const newPitch = note.pitchUnits + pitchDelta;
19360
+ const newPitch = units(note.pitchUnits + pitchDelta);
19343
19361
  core.moveNote(note.id, newStart, newPitch);
19344
19362
  }
19345
19363
  if (options.onPreviewSound && pitch !== lastPreviewPitch) {
@@ -19350,7 +19368,7 @@ var createPianoRoll = (options, handlers) => {
19350
19368
  return;
19351
19369
  }
19352
19370
  const nextStart = step - dragState.dragOffsetStep;
19353
- const nextPitch = pitch - dragState.dragOffsetPitch;
19371
+ const nextPitch = units(pitch - dragState.dragOffsetPitch);
19354
19372
  core.moveNote(dragState.noteId, nextStart, nextPitch);
19355
19373
  return;
19356
19374
  }
@@ -21162,6 +21180,7 @@ var createDtmStudio = async (options = {}) => {
21162
21180
  VIBRATO_MIN_SEC,
21163
21181
  VOICE_IMAGES,
21164
21182
  VOICE_IMAGE_KEY,
21183
+ addUnits,
21165
21184
  analyzeMidiTracks,
21166
21185
  applyHarmonicFilter,
21167
21186
  applyMonophonic,
@@ -21206,6 +21225,7 @@ var createDtmStudio = async (options = {}) => {
21206
21225
  isValidHttpUrl,
21207
21226
  keyCountFor,
21208
21227
  koeUrl,
21228
+ midiNote,
21209
21229
  midiToUnits,
21210
21230
  mountChordPlayer,
21211
21231
  mountDAW,
@@ -21233,6 +21253,7 @@ var createDtmStudio = async (options = {}) => {
21233
21253
  stripLyrics,
21234
21254
  stripMmlMeta,
21235
21255
  transposeNotes,
21256
+ units,
21236
21257
  unitsPerRow,
21237
21258
  unitsPerStep,
21238
21259
  unitsToHz,