@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.mjs CHANGED
@@ -1569,6 +1569,9 @@ var createChannelStrip = (ctx, destination, options = {}) => {
1569
1569
  };
1570
1570
 
1571
1571
  // src/tuning.ts
1572
+ var units = (n) => n;
1573
+ var midiNote = (n) => n;
1574
+ var addUnits = (a, delta) => a + delta;
1572
1575
  var UNITS_PER_OCTAVE = 372;
1573
1576
  var UNITS_PER_SEMITONE = 372 / 12;
1574
1577
  var UNITS_PER_EDO31_DEGREE = 372 / 31;
@@ -1578,13 +1581,13 @@ var A4_HZ = 440;
1578
1581
  var DEFAULT_EDO = 12;
1579
1582
  var unitsPerStep = (edo) => UNITS_PER_OCTAVE / edo;
1580
1583
  var midiToUnits = (midi) => midi * UNITS_PER_SEMITONE;
1581
- var unitsToMidi = (units) => units / UNITS_PER_SEMITONE;
1582
- var unitsToHz = (units) => A4_HZ * 2 ** ((units - A4_UNITS) / UNITS_PER_OCTAVE);
1583
- var unitsToMidiDetune = (units) => {
1584
- const midi = Math.round(units / UNITS_PER_SEMITONE);
1584
+ var unitsToMidi = (u) => u / UNITS_PER_SEMITONE;
1585
+ var unitsToHz = (u) => A4_HZ * 2 ** ((u - A4_UNITS) / UNITS_PER_OCTAVE);
1586
+ var unitsToMidiDetune = (u) => {
1587
+ const midi = Math.round(u / UNITS_PER_SEMITONE);
1585
1588
  return {
1586
1589
  midi,
1587
- detuneCents: (units - midi * UNITS_PER_SEMITONE) * CENTS_PER_UNIT
1590
+ detuneCents: (u - midi * UNITS_PER_SEMITONE) * CENTS_PER_UNIT
1588
1591
  };
1589
1592
  };
1590
1593
  var NATURAL_STEPS = {
@@ -1610,7 +1613,7 @@ var fifthToStep = (fifthIndex, edo) => {
1610
1613
  var fifthToUnits = (fifthIndex, edo) => fifthToStep(fifthIndex, edo) * unitsPerStep(edo);
1611
1614
  var PITCH_ENCODING_VERSION = 2;
1612
1615
  var pitchV1ToUnits = (pitch) => pitch * UNITS_PER_SEMITONE;
1613
- var unitsToPitchV1 = (units) => Math.round(units / UNITS_PER_SEMITONE);
1616
+ var unitsToPitchV1 = (u) => Math.round(u / UNITS_PER_SEMITONE);
1614
1617
 
1615
1618
  // src/chords.ts
1616
1619
  var C3 = 48;
@@ -1623,7 +1626,9 @@ var chordToneToUnits = (relSemitone, relFifth, rootSemitone, rootFifth, edo) =>
1623
1626
  const relWithin12 = (relSemitone % 12 + 12) % 12;
1624
1627
  const relOct = Math.round((relSemitone - relWithin12) / 12);
1625
1628
  const relStep = (fifthToStep(relFifth, edo) - fifthToStep(rootFifth, edo) + edo) % edo;
1626
- return (rootOct + relOct) * UNITS_PER_OCTAVE + (rootStep + relStep) * perStep;
1629
+ return units(
1630
+ (rootOct + relOct) * UNITS_PER_OCTAVE + (rootStep + relStep) * perStep
1631
+ );
1627
1632
  };
1628
1633
  var buildChordPlacements = (options) => {
1629
1634
  const {
@@ -2199,7 +2204,7 @@ var Worldline = class _Worldline {
2199
2204
  const WL = this.wasm;
2200
2205
  const FS = WORLDLINE_SAMPLE_RATE;
2201
2206
  const basePitch = sampleCurve(preMs + durationMs / 2, pitch, preMs + durationMs);
2202
- const midiNote = Math.round(69 + 12 * Math.log2(basePitch / 440));
2207
+ const midiNote2 = Math.round(69 + 12 * Math.log2(basePitch / 440));
2203
2208
  const posMs = 0;
2204
2209
  const reqLen = preMs + durationMs;
2205
2210
  const cutMs = WL_FRAME_MS * 2;
@@ -2223,7 +2228,7 @@ var Worldline = class _Worldline {
2223
2228
  sv(8, samplePtr, "*");
2224
2229
  sv(12, 0, "i32");
2225
2230
  sv(16, 0, "*");
2226
- sv(20, midiNote, "i32");
2231
+ sv(20, midiNote2, "i32");
2227
2232
  sv(24, 100, "double");
2228
2233
  sv(32, 0, "double");
2229
2234
  sv(40, reqLen, "double");
@@ -2720,8 +2725,8 @@ var FORMANTS = {
2720
2725
  // 撥音(ん)は鼻音寄りの低フォルマント
2721
2726
  N: [250, 1e3]
2722
2727
  };
2723
- var unitsToFreq = (units) => 440 * 2 ** ((units - 2139) / 372);
2724
- var unitsToMidiFloat = (units) => units / 31;
2728
+ var unitsToFreq = (units2) => 440 * 2 ** ((units2 - 2139) / 372);
2729
+ var unitsToMidiFloat = (units2) => units2 / 31;
2725
2730
  var createKlattVoice = (ctx, destination, reverbBus, delayBus) => {
2726
2731
  const active = /* @__PURE__ */ new Set();
2727
2732
  const voice = (syllable, e) => {
@@ -3530,7 +3535,7 @@ var createSingingVoices = (ctx, destination, options = {}) => {
3530
3535
  };
3531
3536
  dispatchNote(note.pitch, 1);
3532
3537
  for (const offset of octaveUnisonOffsets(track.octaveUnison)) {
3533
- dispatchNote(note.pitch + offset, OCTAVE_UNISON_PEAK_SCALE);
3538
+ dispatchNote(units(note.pitch + offset), OCTAVE_UNISON_PEAK_SCALE);
3534
3539
  }
3535
3540
  if (!(model.renderToCache && model.scheduleCached)) {
3536
3541
  await new Promise((resolve) => setTimeout(resolve, 0));
@@ -3956,7 +3961,9 @@ var parseMML = (mml, options = {}) => {
3956
3961
  let pitchSteps = naturals[c];
3957
3962
  j++;
3958
3963
  pitchSteps += readAccidentals();
3959
- chordNotes.push((octave + 1) * 372 + pitchSteps * unitsPerStep2);
3964
+ chordNotes.push(
3965
+ units((octave + 1) * 372 + pitchSteps * unitsPerStep2)
3966
+ );
3960
3967
  } else if (c === ">") {
3961
3968
  octave = Math.min(8, octave + 1);
3962
3969
  j++;
@@ -3994,7 +4001,7 @@ var parseMML = (mml, options = {}) => {
3994
4001
  let pitchSteps = naturals[ch];
3995
4002
  j++;
3996
4003
  pitchSteps += readAccidentals();
3997
- const midiPitch = (octave + 1) * 372 + pitchSteps * unitsPerStep2;
4004
+ const midiPitch = units((octave + 1) * 372 + pitchSteps * unitsPerStep2);
3998
4005
  const steps = parseLength();
3999
4006
  recordContributor();
4000
4007
  placements.push({
@@ -9851,7 +9858,7 @@ var mountMmlPlayer = (target, mml, options = {}) => {
9851
9858
  if (n.startStep < fromStep) continue;
9852
9859
  notes.push({
9853
9860
  syllable: lt.syllables[i2],
9854
- pitch: n.pitchUnits + semis,
9861
+ pitch: units(n.pitchUnits + semis),
9855
9862
  startSec: (n.startStep - fromStep) * secondsPerStep,
9856
9863
  durationSec: n.durationSteps * secondsPerStep * gate
9857
9864
  });
@@ -12271,7 +12278,7 @@ var generateRandomPattern = (core, options) => {
12271
12278
  for (let i2 = 0; i2 < 12; i2++) {
12272
12279
  const noteInOctave = (i2 - rootOffset + 12) % 12;
12273
12280
  if (scale.includes(noteInOctave))
12274
- availablePitches.push(basePitch + semitoneToStep(i2) * upr);
12281
+ availablePitches.push(units(basePitch + semitoneToStep(i2) * upr));
12275
12282
  }
12276
12283
  core.beginBatch();
12277
12284
  for (let bar = 0; bar < numBars; bar++) {
@@ -12386,9 +12393,11 @@ var transposeNotes = (cores, steps) => {
12386
12393
  for (const core of cores) {
12387
12394
  const notes = [...core.getNotes()];
12388
12395
  for (const note of notes) {
12389
- const newPitch = Math.max(
12390
- PITCH_RANGE_START,
12391
- Math.min(PITCH_RANGE_END, note.pitchUnits + steps)
12396
+ const newPitch = units(
12397
+ Math.max(
12398
+ PITCH_RANGE_START,
12399
+ Math.min(PITCH_RANGE_END, note.pitchUnits + steps)
12400
+ )
12392
12401
  );
12393
12402
  if (newPitch !== note.pitchUnits) {
12394
12403
  core.moveNote(note.id, note.startStep, newPitch);
@@ -13242,9 +13251,8 @@ var MMLCore = class _MMLCore {
13242
13251
  const upr = cfg.unitsPerRow ?? UNITS_PER_SEMITONE;
13243
13252
  const pitchRangeStart = cfg.pitchRangeStart;
13244
13253
  const pitchRangeEnd = pitchRangeStart + (cfg.keyCount - 1) * upr;
13245
- const clampedPitch = Math.min(
13246
- Math.max(pitch, pitchRangeStart),
13247
- pitchRangeEnd
13254
+ const clampedPitch = units(
13255
+ Math.min(Math.max(pitch, pitchRangeStart), pitchRangeEnd)
13248
13256
  );
13249
13257
  const clampedStart = Math.min(
13250
13258
  Math.max(startStep, 0),
@@ -13638,12 +13646,12 @@ var createRenderer = (mountTarget, width = 800, height = 450, config) => {
13638
13646
  const MICRO_RATIO = 0.45;
13639
13647
  for (let y = startY; y < endY; y += keyHeight) {
13640
13648
  const rowIndex = keyCount - 1 - y / keyHeight;
13641
- const units = pitchRangeStart + rowIndex * upr;
13649
+ const units2 = pitchRangeStart + rowIndex * upr;
13642
13650
  const step = Math.round(
13643
- (units % UNITS_PER_OCTAVE + UNITS_PER_OCTAVE) % UNITS_PER_OCTAVE / upr % edo
13651
+ (units2 % UNITS_PER_OCTAVE + UNITS_PER_OCTAVE) % UNITS_PER_OCTAVE / upr % edo
13644
13652
  );
13645
13653
  const tier = keyTier(step, edo);
13646
- const octave = Math.floor(units / UNITS_PER_OCTAVE) - 1;
13654
+ const octave = Math.floor(units2 / UNITS_PER_OCTAVE) - 1;
13647
13655
  const isC4Range = octave === 4;
13648
13656
  const screenY = y - g_draw_offset_y;
13649
13657
  const bkW = Math.floor(
@@ -13743,13 +13751,13 @@ var createRenderer = (mountTarget, width = 800, height = 450, config) => {
13743
13751
  const endY = g_draw_offset_y + g_grid_canvas.height;
13744
13752
  for (let y = startY; y < endY; y += keyHeight) {
13745
13753
  const rowIndex = keyCount - 1 - y / keyHeight;
13746
- const units = pitchRangeStart + rowIndex * upr;
13754
+ const units2 = pitchRangeStart + rowIndex * upr;
13747
13755
  const step = Math.round(
13748
- (units % UNITS_PER_OCTAVE + UNITS_PER_OCTAVE) % UNITS_PER_OCTAVE / upr % edo
13756
+ (units2 % UNITS_PER_OCTAVE + UNITS_PER_OCTAVE) % UNITS_PER_OCTAVE / upr % edo
13749
13757
  );
13750
13758
  const tier = keyTier(step, edo);
13751
13759
  const isC = step === 0;
13752
- const octave = Math.floor(units / UNITS_PER_OCTAVE) - 1;
13760
+ const octave = Math.floor(units2 / UNITS_PER_OCTAVE) - 1;
13753
13761
  const isC4Range = octave === 4;
13754
13762
  const screenY = y - g_draw_offset_y;
13755
13763
  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";
@@ -13930,7 +13938,7 @@ var createRenderer = (mountTarget, width = 800, height = 450, config) => {
13930
13938
  const step = Math.floor((x2 + g_draw_offset_x) / stepWidth);
13931
13939
  const absoluteY = y + g_draw_offset_y;
13932
13940
  const yIndex = Math.floor(absoluteY / keyHeight);
13933
- const pitch = pitchRangeStart + (keyCount - 1 - yIndex) * upr;
13941
+ const pitch = units(pitchRangeStart + (keyCount - 1 - yIndex) * upr);
13934
13942
  return { step, pitch, x: x2, y };
13935
13943
  };
13936
13944
  const onClick = (callback) => {
@@ -13948,7 +13956,7 @@ var createRenderer = (mountTarget, width = 800, height = 450, config) => {
13948
13956
  const step = Math.floor((x2 + g_draw_offset_x) / stepWidth);
13949
13957
  const absoluteY = y + g_draw_offset_y;
13950
13958
  const yIndex = Math.floor(absoluteY / keyHeight);
13951
- const pitch = pitchRangeStart + (keyCount - 1 - yIndex) * upr;
13959
+ const pitch = units(pitchRangeStart + (keyCount - 1 - yIndex) * upr);
13952
13960
  if (pitch >= pitchRangeStart && pitch < pitchRangeStart + keyCount) {
13953
13961
  requestAnimationFrame(() => callback(step, pitch));
13954
13962
  }
@@ -14655,9 +14663,9 @@ var mountDAW = (target, options = {}) => {
14655
14663
  options.singingVoices?.setVolume(masterVolume / 100);
14656
14664
  };
14657
14665
  applyMasterVolume(masterVolume);
14658
- const snapToEdoGrid = (units) => {
14666
+ const snapToEdoGrid = (u) => {
14659
14667
  const upr = renderConfig.unitsPerRow ?? UNITS_PER_SEMITONE;
14660
- return Math.round(units / upr) * upr;
14668
+ return units(Math.round(u / upr) * upr);
14661
14669
  };
14662
14670
  const applyEdo = (edo, opts) => {
14663
14671
  const next = edo === 31 ? 31 : 12;
@@ -14670,7 +14678,7 @@ var mountDAW = (target, options = {}) => {
14670
14678
  for (const t of trackStates) {
14671
14679
  t.core.beginBatch();
14672
14680
  for (const note of [...t.core.getNotes()]) {
14673
- const snapped = Math.round(note.pitchUnits / upr) * upr;
14681
+ const snapped = units(Math.round(note.pitchUnits / upr) * upr);
14674
14682
  if (snapped !== note.pitchUnits)
14675
14683
  t.core.moveNote(note.id, note.startStep, snapped);
14676
14684
  }
@@ -15370,7 +15378,7 @@ var mountDAW = (target, options = {}) => {
15370
15378
  if (dragState.mode === "move") {
15371
15379
  const nextStart = step - dragState.dragOffsetStep;
15372
15380
  const snappedStart = Math.round(nextStart / snapGridSteps) * snapGridSteps;
15373
- const nextPitch = pitch - dragState.dragOffsetPitch;
15381
+ const nextPitch = units(pitch - dragState.dragOffsetPitch);
15374
15382
  if (hasNoteAt(snappedStart, nextPitch, dragState.noteId)) return;
15375
15383
  active.core.moveNote(dragState.noteId, snappedStart, nextPitch);
15376
15384
  if (nextPitch !== dragState.lastPreviewPitch) {
@@ -15426,7 +15434,7 @@ var mountDAW = (target, options = {}) => {
15426
15434
  for (const note of selectedNotes) {
15427
15435
  const orig = selectedOriginal.find((o) => o.id === note.id);
15428
15436
  if (!orig) continue;
15429
- const newPitch = orig.pitch + deltaPitch;
15437
+ const newPitch = units(orig.pitch + deltaPitch);
15430
15438
  if (newPitch >= PITCH_RANGE_START && newPitch <= PITCH_RANGE_END)
15431
15439
  active.core.moveNote(
15432
15440
  note.id,
@@ -15438,7 +15446,7 @@ var mountDAW = (target, options = {}) => {
15438
15446
  const grab = selectedNotes[0];
15439
15447
  const orig = selectedOriginal.find((o) => o.id === grab.id);
15440
15448
  if (orig) {
15441
- const newGrab = orig.pitch + deltaPitch;
15449
+ const newGrab = units(orig.pitch + deltaPitch);
15442
15450
  if (newGrab !== lastMultiPreviewPitch && newGrab >= 0 && newGrab < 128) {
15443
15451
  lastMultiPreviewPitch = newGrab;
15444
15452
  playPreview(newGrab);
@@ -15757,7 +15765,7 @@ var mountDAW = (target, options = {}) => {
15757
15765
  if (n.startStep < fromStep) continue;
15758
15766
  notes.push({
15759
15767
  syllable: lt.syllables[i2],
15760
- pitch: n.pitchUnits + semis,
15768
+ pitch: units(n.pitchUnits + semis),
15761
15769
  startSec: (n.startStep - fromStep) * secondsPerStep,
15762
15770
  durationSec: n.durationSteps * secondsPerStep * gate
15763
15771
  });
@@ -16963,7 +16971,7 @@ var mountDAW = (target, options = {}) => {
16963
16971
  }
16964
16972
  if (candidateNotes.length === 0) return null;
16965
16973
  const sum = candidateNotes.reduce((acc, note) => acc + note.pitchUnits, 0);
16966
- return Math.round(sum / candidateNotes.length);
16974
+ return units(Math.round(sum / candidateNotes.length));
16967
16975
  };
16968
16976
  const centerPitch = (pitch) => {
16969
16977
  const canvas = renderer.getGridCanvas();
@@ -17284,8 +17292,6 @@ var mountDAW = (target, options = {}) => {
17284
17292
  active.vocalOctaveUnison = "none";
17285
17293
  } else {
17286
17294
  clearAll();
17287
- applyEdo(12);
17288
- refs.edoSelect.value = String(renderConfig.edo ?? 12);
17289
17295
  for (const t of trackStates) t.core.setLoadMode(true);
17290
17296
  for (const t of trackStates) {
17291
17297
  t.lyrics = "";
@@ -17534,11 +17540,20 @@ var mountDAW = (target, options = {}) => {
17534
17540
  return;
17535
17541
  }
17536
17542
  }
17537
- applyEdo(next, { snap: true });
17538
- const first = getFirstDetectedPitch();
17539
- centerPitch(first ?? pitchV1ToUnits(48));
17540
- redrawAll();
17541
- updateUndoRedo();
17543
+ overlayDuring(() => {
17544
+ applyEdo(next, { snap: true });
17545
+ if (next === 31 && prev === 12) {
17546
+ zoomY = Math.max(50, Math.round(zoomY / 2 / 25) * 25);
17547
+ } else if (next === 12 && prev === 31) {
17548
+ zoomY = Math.min(200, Math.round(zoomY * 2 / 25) * 25);
17549
+ }
17550
+ applyZoomY();
17551
+ const first = getFirstDetectedPitch();
17552
+ centerPitch(first ?? pitchV1ToUnits(48));
17553
+ redrawAll();
17554
+ updateUndoRedo();
17555
+ notifyViewState();
17556
+ });
17542
17557
  });
17543
17558
  refs.edoInfoBtn.addEventListener("click", () => {
17544
17559
  showModal("\u97F3\u5F8B\u306E\u89E3\u8AAC", EDO_INFO_HTML);
@@ -18911,7 +18926,7 @@ var playSingingMML = async (mml, options = {}) => {
18911
18926
  if (n.startStep < fromStep) continue;
18912
18927
  notes.push({
18913
18928
  syllable: lt.syllables[i2],
18914
- pitch: n.pitchUnits + semis,
18929
+ pitch: units(n.pitchUnits + semis),
18915
18930
  startSec: (n.startStep - fromStep) * secondsPerStep,
18916
18931
  durationSec: n.durationSteps * secondsPerStep * gate
18917
18932
  });
@@ -19194,7 +19209,7 @@ var createPianoRoll = (options, handlers) => {
19194
19209
  const pitchDelta = nextPitch2 - baseNote.pitchUnits;
19195
19210
  for (const note of dragState.selectedNotes) {
19196
19211
  const newStart = note.startStep + stepDelta;
19197
- const newPitch = note.pitchUnits + pitchDelta;
19212
+ const newPitch = units(note.pitchUnits + pitchDelta);
19198
19213
  core.moveNote(note.id, newStart, newPitch);
19199
19214
  }
19200
19215
  if (options.onPreviewSound && pitch !== lastPreviewPitch) {
@@ -19205,7 +19220,7 @@ var createPianoRoll = (options, handlers) => {
19205
19220
  return;
19206
19221
  }
19207
19222
  const nextStart = step - dragState.dragOffsetStep;
19208
- const nextPitch = pitch - dragState.dragOffsetPitch;
19223
+ const nextPitch = units(pitch - dragState.dragOffsetPitch);
19209
19224
  core.moveNote(dragState.noteId, nextStart, nextPitch);
19210
19225
  return;
19211
19226
  }
@@ -21015,6 +21030,7 @@ export {
21015
21030
  VIBRATO_MIN_SEC,
21016
21031
  VOICE_IMAGES,
21017
21032
  VOICE_IMAGE_KEY,
21033
+ addUnits,
21018
21034
  analyzeMidiTracks,
21019
21035
  applyHarmonicFilter,
21020
21036
  applyMonophonic,
@@ -21059,6 +21075,7 @@ export {
21059
21075
  isValidHttpUrl,
21060
21076
  keyCountFor,
21061
21077
  koeUrl,
21078
+ midiNote,
21062
21079
  midiToUnits,
21063
21080
  mountChordPlayer,
21064
21081
  mountDAW,
@@ -21086,6 +21103,7 @@ export {
21086
21103
  stripLyrics,
21087
21104
  stripMmlMeta,
21088
21105
  transposeNotes,
21106
+ units,
21089
21107
  unitsPerRow,
21090
21108
  unitsPerStep,
21091
21109
  unitsToHz,
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "author": "onjmin",
3
3
  "license": "MIT",
4
4
  "name": "@onjmin/dtm",
5
- "version": "2.0.2",
5
+ "version": "2.0.3",
6
6
  "description": "MMLを中間言語に用いた、モバイルファーストなDAW / ピアノロール打ち込みコンポーネント",
7
7
  "homepage": "https://onjmin.github.io/dtm",
8
8
  "repository": {