@onjmin/dtm 1.0.5 → 1.0.6

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
@@ -2810,7 +2810,7 @@ var KOE_VOICEBANKS = {
2810
2810
  mgroid: "MGRoid_\u539F\u97F3\u8A2D\u5B9A\u6E08\u307F.koe",
2811
2811
  motroid: "MOTRoid\u5B8C\u5168\u7248V2.koe",
2812
2812
  nynroid: "NYNRoidver1.4.koe",
2813
- uc: "\u84C4\u97F3\u30AD\u30EA\u30B3 \uFF08beta1.0\uFF09.koe"
2813
+ uc: "\u84C4\u97F3\u30AD\u30EA\u30B3 \uFF08beta1.1\uFF09.koe"
2814
2814
  };
2815
2815
  var KOE_VOICEBANK_LABELS = {
2816
2816
  tsukuyomi: "\u3064\u304F\u3088\u307F\u3061\u3083\u3093",
@@ -4024,6 +4024,7 @@ var reverbAmountToGain = (amount) => Math.max(0, Math.min(100, amount)) / 100;
4024
4024
  var STEPS_PER_BEAT = 48;
4025
4025
  var PLAN_TIME = 0.5;
4026
4026
  var TICK_INTERVAL_MS = 20;
4027
+ var STEP_EPSILON = 1e-4;
4027
4028
  var resolveLoopPoint = (point, _bpm, stepsPerBar, sps) => {
4028
4029
  if ("step" in point) {
4029
4030
  return point.step;
@@ -4055,6 +4056,8 @@ var createSequencer = (options) => {
4055
4056
  let loopDurationSec = 0;
4056
4057
  let loopStartIndex = 0;
4057
4058
  let loopBase = 0;
4059
+ let drumCursor = 0;
4060
+ let lastDrumStep = Number.NEGATIVE_INFINITY;
4058
4061
  let lastPlayStep = 0;
4059
4062
  const secondsPerStep = () => 60 / options.getBpm() / STEPS_PER_BEAT;
4060
4063
  const getWrappedPlayStep = (time, sps) => {
@@ -4164,24 +4167,32 @@ var createSequencer = (options) => {
4164
4167
  }
4165
4168
  const { stepsPerBar } = options;
4166
4169
  const currentStep = getWrappedPlayStep(time, sps);
4167
- const currentBar = Math.floor(currentStep / stepsPerBar) + 1;
4168
- const pattern = options.getDrumPattern(currentBar);
4169
- if (pattern && pattern.length > 0) {
4170
- const currentStepInBar = currentStep % stepsPerBar;
4171
- const nextStep = currentStepInBar + 4;
4172
- const crossedBar = currentStepInBar < 4;
4173
- for (const drum of pattern) {
4174
- const shouldPlay = crossedBar && drum.step === 0 || drum.step >= currentStepInBar && drum.step < nextStep;
4175
- if (!shouldPlay) continue;
4176
- const whenSeconds = (drum.step - currentStepInBar) * sps;
4177
- if (whenSeconds < -0.1 || whenSeconds > PLAN_TIME) continue;
4178
- options.onPlayDrum({
4179
- pitch: drum.pitch,
4180
- velocity: drum.velocity ?? 1,
4181
- when: Math.max(0, whenSeconds),
4182
- duration: 0.1
4183
- });
4170
+ if (isLooping && loopDurationSec > 0 && currentStep + STEP_EPSILON < lastDrumStep) {
4171
+ drumCursor = loopStartStep - STEP_EPSILON;
4172
+ }
4173
+ lastDrumStep = currentStep;
4174
+ let drumScanTo = currentStep + PLAN_TIME / sps;
4175
+ if (isLooping && loopDurationSec > 0) {
4176
+ drumScanTo = Math.min(drumScanTo, loopEndStep - STEP_EPSILON);
4177
+ }
4178
+ if (drumScanTo > drumCursor) {
4179
+ const firstBar = Math.floor(Math.max(0, drumCursor) / stepsPerBar);
4180
+ const lastBar = Math.floor(Math.max(0, drumScanTo) / stepsPerBar);
4181
+ for (let bar = firstBar; bar <= lastBar; bar++) {
4182
+ const pattern = options.getDrumPattern(bar + 1);
4183
+ if (!pattern || pattern.length === 0) continue;
4184
+ for (const drum of pattern) {
4185
+ const absStep = bar * stepsPerBar + drum.step;
4186
+ if (absStep <= drumCursor || absStep > drumScanTo) continue;
4187
+ options.onPlayDrum({
4188
+ pitch: drum.pitch,
4189
+ velocity: drum.velocity ?? 1,
4190
+ when: Math.max(0, (absStep - currentStep) * sps),
4191
+ duration: 0.1
4192
+ });
4193
+ }
4184
4194
  }
4195
+ drumCursor = drumScanTo;
4185
4196
  }
4186
4197
  if (time >= 0) {
4187
4198
  const currentStep2 = getWrappedPlayStep(time, sps);
@@ -4252,6 +4263,8 @@ var createSequencer = (options) => {
4252
4263
  nowIndex++;
4253
4264
  }
4254
4265
  loopBase = 0;
4266
+ drumCursor = fromStepValue - STEP_EPSILON;
4267
+ lastDrumStep = Number.NEGATIVE_INFINITY;
4255
4268
  lastPlayStep = fromStepValue - 1e-4;
4256
4269
  lastRealTime = -1;
4257
4270
  lastAudioTime = -1;
@@ -12232,6 +12245,7 @@ var shiftNotes = (cores, shiftSteps) => {
12232
12245
  if (newStart < 0) core.deleteNoteById(note.id);
12233
12246
  else core.moveNote(note.id, newStart, note.pitch);
12234
12247
  }
12248
+ core.saveHistory();
12235
12249
  }
12236
12250
  };
12237
12251
  var transposeNotes = (cores, semitones) => {
@@ -12244,6 +12258,7 @@ var transposeNotes = (cores, semitones) => {
12244
12258
  core.moveNote(note.id, note.startStep, newPitch);
12245
12259
  }
12246
12260
  }
12261
+ core.saveHistory();
12247
12262
  }
12248
12263
  };
12249
12264
 
@@ -12852,7 +12867,8 @@ var LinkedList = class {
12852
12867
  * Undo可能かチェック(カーソル移動なし)
12853
12868
  */
12854
12869
  canUndo() {
12855
- return this.#cursor.prev?.value !== null;
12870
+ const { prev } = this.#cursor;
12871
+ return prev !== null && prev.value !== null;
12856
12872
  }
12857
12873
  /**
12858
12874
  * Redo可能かチェック(カーソル移動なし)
@@ -13070,7 +13086,7 @@ var drawGrid = (noteLengthSteps = 1) => {
13070
13086
  for (let y = startY; y < endY; y += keyHeight) {
13071
13087
  const pitchIndex = keyCount - 1 - y / keyHeight;
13072
13088
  const totalPitch = pitchIndex + pitchRangeStart;
13073
- const pitchMod12 = pitchIndex % 12;
13089
+ const pitchMod12 = totalPitch % 12;
13074
13090
  const isBlackKey = blackKeyPitches.has(pitchMod12);
13075
13091
  const isC = pitchMod12 === 0;
13076
13092
  const octave = Math.floor(totalPitch / 12) - 1;
@@ -18659,6 +18675,10 @@ var createPianoRoll = (options, handlers) => {
18659
18675
  selectionStart = null;
18660
18676
  }
18661
18677
  if (dragState) {
18678
+ if (hasDragged) {
18679
+ if (dragState.mode === "move") core.moveNoteEnd(dragState.noteId);
18680
+ else core.resizeNoteEnd(dragState.noteId);
18681
+ }
18662
18682
  dragState = null;
18663
18683
  if (hasDragged) {
18664
18684
  suppressClick = true;
package/dist/index.mjs CHANGED
@@ -2677,7 +2677,7 @@ var KOE_VOICEBANKS = {
2677
2677
  mgroid: "MGRoid_\u539F\u97F3\u8A2D\u5B9A\u6E08\u307F.koe",
2678
2678
  motroid: "MOTRoid\u5B8C\u5168\u7248V2.koe",
2679
2679
  nynroid: "NYNRoidver1.4.koe",
2680
- uc: "\u84C4\u97F3\u30AD\u30EA\u30B3 \uFF08beta1.0\uFF09.koe"
2680
+ uc: "\u84C4\u97F3\u30AD\u30EA\u30B3 \uFF08beta1.1\uFF09.koe"
2681
2681
  };
2682
2682
  var KOE_VOICEBANK_LABELS = {
2683
2683
  tsukuyomi: "\u3064\u304F\u3088\u307F\u3061\u3083\u3093",
@@ -3891,6 +3891,7 @@ var reverbAmountToGain = (amount) => Math.max(0, Math.min(100, amount)) / 100;
3891
3891
  var STEPS_PER_BEAT = 48;
3892
3892
  var PLAN_TIME = 0.5;
3893
3893
  var TICK_INTERVAL_MS = 20;
3894
+ var STEP_EPSILON = 1e-4;
3894
3895
  var resolveLoopPoint = (point, _bpm, stepsPerBar, sps) => {
3895
3896
  if ("step" in point) {
3896
3897
  return point.step;
@@ -3922,6 +3923,8 @@ var createSequencer = (options) => {
3922
3923
  let loopDurationSec = 0;
3923
3924
  let loopStartIndex = 0;
3924
3925
  let loopBase = 0;
3926
+ let drumCursor = 0;
3927
+ let lastDrumStep = Number.NEGATIVE_INFINITY;
3925
3928
  let lastPlayStep = 0;
3926
3929
  const secondsPerStep = () => 60 / options.getBpm() / STEPS_PER_BEAT;
3927
3930
  const getWrappedPlayStep = (time, sps) => {
@@ -4031,24 +4034,32 @@ var createSequencer = (options) => {
4031
4034
  }
4032
4035
  const { stepsPerBar } = options;
4033
4036
  const currentStep = getWrappedPlayStep(time, sps);
4034
- const currentBar = Math.floor(currentStep / stepsPerBar) + 1;
4035
- const pattern = options.getDrumPattern(currentBar);
4036
- if (pattern && pattern.length > 0) {
4037
- const currentStepInBar = currentStep % stepsPerBar;
4038
- const nextStep = currentStepInBar + 4;
4039
- const crossedBar = currentStepInBar < 4;
4040
- for (const drum of pattern) {
4041
- const shouldPlay = crossedBar && drum.step === 0 || drum.step >= currentStepInBar && drum.step < nextStep;
4042
- if (!shouldPlay) continue;
4043
- const whenSeconds = (drum.step - currentStepInBar) * sps;
4044
- if (whenSeconds < -0.1 || whenSeconds > PLAN_TIME) continue;
4045
- options.onPlayDrum({
4046
- pitch: drum.pitch,
4047
- velocity: drum.velocity ?? 1,
4048
- when: Math.max(0, whenSeconds),
4049
- duration: 0.1
4050
- });
4037
+ if (isLooping && loopDurationSec > 0 && currentStep + STEP_EPSILON < lastDrumStep) {
4038
+ drumCursor = loopStartStep - STEP_EPSILON;
4039
+ }
4040
+ lastDrumStep = currentStep;
4041
+ let drumScanTo = currentStep + PLAN_TIME / sps;
4042
+ if (isLooping && loopDurationSec > 0) {
4043
+ drumScanTo = Math.min(drumScanTo, loopEndStep - STEP_EPSILON);
4044
+ }
4045
+ if (drumScanTo > drumCursor) {
4046
+ const firstBar = Math.floor(Math.max(0, drumCursor) / stepsPerBar);
4047
+ const lastBar = Math.floor(Math.max(0, drumScanTo) / stepsPerBar);
4048
+ for (let bar = firstBar; bar <= lastBar; bar++) {
4049
+ const pattern = options.getDrumPattern(bar + 1);
4050
+ if (!pattern || pattern.length === 0) continue;
4051
+ for (const drum of pattern) {
4052
+ const absStep = bar * stepsPerBar + drum.step;
4053
+ if (absStep <= drumCursor || absStep > drumScanTo) continue;
4054
+ options.onPlayDrum({
4055
+ pitch: drum.pitch,
4056
+ velocity: drum.velocity ?? 1,
4057
+ when: Math.max(0, (absStep - currentStep) * sps),
4058
+ duration: 0.1
4059
+ });
4060
+ }
4051
4061
  }
4062
+ drumCursor = drumScanTo;
4052
4063
  }
4053
4064
  if (time >= 0) {
4054
4065
  const currentStep2 = getWrappedPlayStep(time, sps);
@@ -4119,6 +4130,8 @@ var createSequencer = (options) => {
4119
4130
  nowIndex++;
4120
4131
  }
4121
4132
  loopBase = 0;
4133
+ drumCursor = fromStepValue - STEP_EPSILON;
4134
+ lastDrumStep = Number.NEGATIVE_INFINITY;
4122
4135
  lastPlayStep = fromStepValue - 1e-4;
4123
4136
  lastRealTime = -1;
4124
4137
  lastAudioTime = -1;
@@ -12099,6 +12112,7 @@ var shiftNotes = (cores, shiftSteps) => {
12099
12112
  if (newStart < 0) core.deleteNoteById(note.id);
12100
12113
  else core.moveNote(note.id, newStart, note.pitch);
12101
12114
  }
12115
+ core.saveHistory();
12102
12116
  }
12103
12117
  };
12104
12118
  var transposeNotes = (cores, semitones) => {
@@ -12111,6 +12125,7 @@ var transposeNotes = (cores, semitones) => {
12111
12125
  core.moveNote(note.id, note.startStep, newPitch);
12112
12126
  }
12113
12127
  }
12128
+ core.saveHistory();
12114
12129
  }
12115
12130
  };
12116
12131
 
@@ -12719,7 +12734,8 @@ var LinkedList = class {
12719
12734
  * Undo可能かチェック(カーソル移動なし)
12720
12735
  */
12721
12736
  canUndo() {
12722
- return this.#cursor.prev?.value !== null;
12737
+ const { prev } = this.#cursor;
12738
+ return prev !== null && prev.value !== null;
12723
12739
  }
12724
12740
  /**
12725
12741
  * Redo可能かチェック(カーソル移動なし)
@@ -12937,7 +12953,7 @@ var drawGrid = (noteLengthSteps = 1) => {
12937
12953
  for (let y = startY; y < endY; y += keyHeight) {
12938
12954
  const pitchIndex = keyCount - 1 - y / keyHeight;
12939
12955
  const totalPitch = pitchIndex + pitchRangeStart;
12940
- const pitchMod12 = pitchIndex % 12;
12956
+ const pitchMod12 = totalPitch % 12;
12941
12957
  const isBlackKey = blackKeyPitches.has(pitchMod12);
12942
12958
  const isC = pitchMod12 === 0;
12943
12959
  const octave = Math.floor(totalPitch / 12) - 1;
@@ -18526,6 +18542,10 @@ var createPianoRoll = (options, handlers) => {
18526
18542
  selectionStart = null;
18527
18543
  }
18528
18544
  if (dragState) {
18545
+ if (hasDragged) {
18546
+ if (dragState.mode === "move") core.moveNoteEnd(dragState.noteId);
18547
+ else core.resizeNoteEnd(dragState.noteId);
18548
+ }
18529
18549
  dragState = null;
18530
18550
  if (hasDragged) {
18531
18551
  suppressClick = true;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "author": "onjmin",
3
3
  "license": "MIT",
4
4
  "name": "@onjmin/dtm",
5
- "version": "1.0.5",
5
+ "version": "1.0.6",
6
6
  "description": "MMLを中間言語に用いた、モバイルファーストなDAW / ピアノロール打ち込みコンポーネント",
7
7
  "homepage": "https://onjmin.github.io/dtm",
8
8
  "repository": {