@marmooo/midy 0.3.0 → 0.3.1

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/script/midy.d.ts CHANGED
@@ -99,7 +99,7 @@ export class Midy {
99
99
  66: (channelNumber: any, value: any, scheduleTime: any) => void;
100
100
  67: (channelNumber: any, softPedal: any, scheduleTime: any) => void;
101
101
  71: (channelNumber: any, filterResonance: any, scheduleTime: any) => void;
102
- 72: (channelNumber: any, releaseTime: any, _scheduleTime: any) => void;
102
+ 72: (channelNumber: any, releaseTime: any, scheduleTime: any) => void;
103
103
  73: (channelNumber: any, attackTime: any, scheduleTime: any) => void;
104
104
  74: (channelNumber: any, brightness: any, scheduleTime: any) => void;
105
105
  75: (channelNumber: any, dacayTime: any, scheduleTime: any) => void;
@@ -157,6 +157,7 @@ export class Midy {
157
157
  instruments: Set<any>;
158
158
  timeline: any[];
159
159
  };
160
+ stopActiveNotes(channelNumber: any, velocity: any, force: any, scheduleTime: any): Promise<any[]>;
160
161
  stopChannelNotes(channelNumber: any, velocity: any, force: any, scheduleTime: any): Promise<any[]>;
161
162
  stopNotes(velocity: any, force: any, scheduleTime: any): Promise<any[]>;
162
163
  start(): Promise<void>;
@@ -216,8 +217,9 @@ export class Midy {
216
217
  isDrumNoteOffException(channel: any, noteNumber: any): boolean;
217
218
  scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any, portamento: any): Promise<void>;
218
219
  noteOn(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<void>;
219
- disconnectNote(note: any, scheduledNotes: any, index: any): void;
220
- stopNote(endTime: any, stopTime: any, scheduledNotes: any, index: any): Promise<any>;
220
+ disconnectNote(note: any): void;
221
+ stopNote(endTime: any, stopTime: any, noteList: any, index: any): Promise<any>;
222
+ findNoteOffTarget(noteList: any): any[] | undefined;
221
223
  scheduleNoteOff(channelNumber: any, noteNumber: any, _velocity: any, endTime: any, force: any, portamentoNoteNumber: any): Promise<any> | undefined;
222
224
  noteOff(channelNumber: any, noteNumber: any, velocity: any, scheduleTime: any): Promise<any> | undefined;
223
225
  releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
@@ -266,7 +268,7 @@ export class Midy {
266
268
  66: (channelNumber: any, value: any, scheduleTime: any) => void;
267
269
  67: (channelNumber: any, softPedal: any, scheduleTime: any) => void;
268
270
  71: (channelNumber: any, filterResonance: any, scheduleTime: any) => void;
269
- 72: (channelNumber: any, releaseTime: any, _scheduleTime: any) => void;
271
+ 72: (channelNumber: any, releaseTime: any, scheduleTime: any) => void;
270
272
  73: (channelNumber: any, attackTime: any, scheduleTime: any) => void;
271
273
  74: (channelNumber: any, brightness: any, scheduleTime: any) => void;
272
274
  75: (channelNumber: any, dacayTime: any, scheduleTime: any) => void;
@@ -309,7 +311,7 @@ export class Midy {
309
311
  setSostenutoPedal(channelNumber: any, value: any, scheduleTime: any): void;
310
312
  setSoftPedal(channelNumber: any, softPedal: any, scheduleTime: any): void;
311
313
  setFilterResonance(channelNumber: any, filterResonance: any, scheduleTime: any): void;
312
- setReleaseTime(channelNumber: any, releaseTime: any, _scheduleTime: any): void;
314
+ setReleaseTime(channelNumber: any, releaseTime: any, scheduleTime: any): void;
313
315
  setAttackTime(channelNumber: any, attackTime: any, scheduleTime: any): void;
314
316
  setBrightness(channelNumber: any, brightness: any, scheduleTime: any): void;
315
317
  setDecayTime(channelNumber: any, dacayTime: any, scheduleTime: any): void;
@@ -1 +1 @@
1
- {"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"AAkNA;IAwCE;;;;;;;;;;;;;;MAcE;IAgCF;;;;;OAmBC;IAxGD,aAAa;IACb,yBAAqB;IACrB,2BAAuB;IACvB;;;MAGE;IACF;;;;;;MAME;IACF,oBAAiB;IACjB,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,kCAA+B;IAC/B,gCAA6B;IAC7B,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,gBAAc;IACd,mBAAiB;IACjB,oBAAkB;IAClB,2BAAqC;IACrC,+BAEE;IAkBF;;;;;MA4BE;IAGA,kBAAgC;IAChC;;;;;MAAqD;IACrD,kBAA8C;IAC9C,eAAwD;IACxD,qBAGE;IACF;;;;;;;;;;;MAA2D;IAC3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IACjD;;;MAA8D;IAC9D;;;;;;;;MAAyD;IAQ3D,4BAMC;IAED,mCAWC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAmBC;IAED,6DA2BC;IAED,4DASC;IAED,2CAcC;IAED,2EAqEC;IAED,mCAOC;IAED,0BAuDC;IAED,uDAEC;IAED,wDAEC;IAED,6EAEC;IAED;;;MAgHC;IAED,mGAiBC;IAED,wEAMC;IAED,uBAKC;IAED,aAMC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,yDAQC;IAED,2DASC;IAED,qDAQC;IAED,kFAuBC;IAED;;;;MAWC;IAED,gFAUC;IAED,mFAYC;IAED,sGAcC;IAID;;;MA8BC;IAED;;;;;;;;MA0CC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,qCAYC;IAED,6CAEC;IAED,2DAIC;IAED,+DAOC;IAED,wCAGC;IAED,mFAUC;IAED,oEAiBC;IAED,qDAoBC;IAED,6CAIC;IAED,mFAsBC;IAED,oEA2BC;IAED,kEAoBC;IAED,+DAaC;IAED,+GA0BC;IAED,iIAqEC;IAED,4BAYC;IAED,0EAkBC;IAED,8EAqBC;IAED,+DAKC;IAED,mHA0DC;IAED,6FASC;IAED,iEAuBC;IAED,qFAgBC;IAED,oJAyCC;IAED,yGAUC;IAED,4GAeC;IAED,uFAgBC;IAED,mGAoCC;IAED,yGAeC;IAED,sFAcC;IAED,+EAeC;IAED,wFAGC;IAED,sEAWC;IAED,mEAQC;IAED,mEAQC;IAED,sEAMC;IAED,oEAQC;IAED,uFA0BC;IAED,uFA0BC;IAED,mDAMC;IAED,kDAKC;IAED,gEAKC;IAED;;;;;;;;;;;MAiDC;IAED,oFAMC;IAED,6EAmDC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAqCC;IAED,kGAYC;IAED,+CAEC;IAED,wDAUC;IAED,iFAMC;IAED,iEAGC;IAED,yDAaC;IAED,oEAMC;IAED;;;MAMC;IAED,sDAiBC;IAED,8DAMC;IAED,4EAKC;IAED,+CAEC;IAED,sEAGC;IAED,2DAUC;IAED,yEAYC;IAED,oDAIC;IAED,2EAUC;IAED,0EAcC;IAED,sFAUC;IAED,+EAKC;IAED,4EASC;IAED,4EAYC;IAED,0EAQC;IAED,8EASC;IAED,gFAeC;IAED,6DAUC;IAED,sFA4BC;IAED,sFA4BC;IAED,kFAeC;IAED,2DAMC;IAED,mEAyBC;IAGD,wCAEC;IAGD,wCAEC;IAED,gDAEC;IAED,gDAEC;IAED,sEAGC;IAED,qEAKC;IAED,2EAWC;IAED,iEAKC;IAED,uEASC;IAED,mEAKC;IAED,yEASC;IAED,2EASC;IAED,gGAMC;IAED,gFAGC;IAED,yCAYC;IAGD,8CA0BC;IAED,gFAGC;IAED,iEAEC;IAED,gEAEC;IAED,gEAIC;IAED,gEAIC;IAED,+EAuCC;IAED,qCAcC;IAED,qCAcC;IAED,4EA6DC;IAED,4DAGC;IAED,sDASC;IAED,gEAGC;IAED,yDAWC;IAED,kEAGC;IAED,2DAWC;IAED,sEAeC;IAED,4CAOC;IAED,+BAKC;IAED,qDAiBC;IAED,gCAIC;IAED,kCAEC;IA6BD,4CAEC;IAED,+DAaC;IAED,kDAiBC;IAED,2GAKC;IAED,sDAIC;IAED,qCAEC;IAED,uDAMC;IAED,sCAEC;IAED,uDASC;IAED,sCAEC;IAED,2DAqBC;IAED,0CAEC;IAED,mCAeC;IAED,2FAgBC;IAED,2FAoBC;IAED,iDAIC;IAED,wDAMC;IAED,qDAMC;IAED,kDAMC;IAED,mDAMC;IAED,sDAMC;IAED,mEASC;IAED,qDAUC;IAED,4CAUC;IAED,2DAOC;IAED,0CAWC;IAED,6FAIC;IAED,yEAiBC;IAED,gDAYC;IAGD,6DAgBC;CACF;AAngGD;IACE,uBAGC;IAFC,YAA2B;IAC3B,qBAAuB;IAGzB,gCAKC;IAED,mBAEC;IAED,0BAUC;IAED,uBAEC;IAED,mBAEC;IAED,cAMC;IASD,6BAKC;IAZD,qDAKC;CAQF;AAED;IAkBE,0FAMC;IAvBD,kBAAa;IACb,gBAAW;IACX,iBAAY;IACZ,wBAAmB;IACnB,iBAAY;IACZ,gBAAW;IACX,WAAM;IACN,WAAM;IACN,mBAAc;IACd,qBAAgB;IAChB,gBAAW;IACX,kBAAa;IACb,uBAAkB;IAClB,uBAAkB;IAClB,gBAAW;IACX,iBAAa;IAGX,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}
1
+ {"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"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"}
package/script/midy.js CHANGED
@@ -629,7 +629,7 @@ class Midy {
629
629
  const startTime = event.startTime + this.startDelay - offset;
630
630
  switch (event.type) {
631
631
  case "noteOn":
632
- if (event.velocity !== 0) {
632
+ if (0 < event.velocity) {
633
633
  await this.scheduleNoteOn(event.channel, event.noteNumber, event.velocity, startTime, event.portamento);
634
634
  break;
635
635
  }
@@ -845,6 +845,17 @@ class Midy {
845
845
  }
846
846
  return { instruments, timeline };
847
847
  }
848
+ stopActiveNotes(channelNumber, velocity, force, scheduleTime) {
849
+ const channel = this.channels[channelNumber];
850
+ const promises = [];
851
+ const activeNotes = this.getActiveNotes(channel, scheduleTime);
852
+ activeNotes.forEach((note) => {
853
+ const promise = this.scheduleNoteOff(channelNumber, note.noteNumber, velocity, scheduleTime, force, undefined);
854
+ this.notePromises.push(promise);
855
+ promises.push(promise);
856
+ });
857
+ return Promise.all(promises);
858
+ }
848
859
  stopChannelNotes(channelNumber, velocity, force, scheduleTime) {
849
860
  const channel = this.channels[channelNumber];
850
861
  const promises = [];
@@ -916,6 +927,8 @@ class Midy {
916
927
  const note = noteList[i];
917
928
  if (!note)
918
929
  continue;
930
+ if (note.ending)
931
+ continue;
919
932
  callback(note);
920
933
  }
921
934
  });
@@ -1285,7 +1298,7 @@ class Midy {
1285
1298
  type: "lowpass",
1286
1299
  Q: voiceParams.initialFilterQ / 5 * state.filterResonance, // dB
1287
1300
  });
1288
- if (portamento) {
1301
+ if (0.5 <= state.portamento && portamento) {
1289
1302
  note.portamento = true;
1290
1303
  this.setPortamentoStartVolumeEnvelope(channel, note, now);
1291
1304
  this.setPortamentoStartFilterEnvelope(channel, note, now);
@@ -1375,8 +1388,8 @@ class Midy {
1375
1388
  if (!channel.isDrum)
1376
1389
  return false;
1377
1390
  const programNumber = channel.programNumber;
1378
- return (programNumber === 48 && noteNumber === 88) ||
1379
- (programNumber === 56 && 47 <= noteNumber && noteNumber <= 84);
1391
+ return !((programNumber === 48 && noteNumber === 88) ||
1392
+ (programNumber === 56 && 47 <= noteNumber && noteNumber <= 84));
1380
1393
  }
1381
1394
  async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime, portamento) {
1382
1395
  const channel = this.channels[channelNumber];
@@ -1398,20 +1411,21 @@ class Midy {
1398
1411
  this.handleExclusiveClass(note, channelNumber, startTime);
1399
1412
  this.handleDrumExclusiveClass(note, channelNumber, startTime);
1400
1413
  const scheduledNotes = channel.scheduledNotes;
1401
- let notes = scheduledNotes.get(noteNumber);
1402
- if (notes) {
1403
- notes.push(note);
1414
+ let noteList = scheduledNotes.get(noteNumber);
1415
+ if (noteList) {
1416
+ noteList.push(note);
1404
1417
  }
1405
1418
  else {
1406
- notes = [note];
1407
- scheduledNotes.set(noteNumber, notes);
1419
+ noteList = [note];
1420
+ scheduledNotes.set(noteNumber, noteList);
1408
1421
  }
1409
1422
  if (this.isDrumNoteOffException(channel, noteNumber)) {
1410
1423
  const stopTime = startTime + note.bufferSource.buffer.duration;
1411
- const index = notes.length - 1;
1424
+ const index = noteList.length - 1;
1412
1425
  const promise = new Promise((resolve) => {
1413
1426
  note.bufferSource.onended = () => {
1414
- this.disconnectNote(note, scheduledNotes, index);
1427
+ noteList[index] = undefined;
1428
+ this.disconnectNote(note);
1415
1429
  resolve();
1416
1430
  };
1417
1431
  note.bufferSource.stop(stopTime);
@@ -1423,8 +1437,7 @@ class Midy {
1423
1437
  scheduleTime ??= this.audioContext.currentTime;
1424
1438
  return this.scheduleNoteOn(channelNumber, noteNumber, velocity, scheduleTime, false);
1425
1439
  }
1426
- disconnectNote(note, scheduledNotes, index) {
1427
- scheduledNotes[index] = null;
1440
+ disconnectNote(note) {
1428
1441
  note.bufferSource.disconnect();
1429
1442
  note.filterNode.disconnect();
1430
1443
  note.volumeEnvelopeNode.disconnect();
@@ -1447,8 +1460,8 @@ class Midy {
1447
1460
  note.chorusEffectsSend.disconnect();
1448
1461
  }
1449
1462
  }
1450
- stopNote(endTime, stopTime, scheduledNotes, index) {
1451
- const note = scheduledNotes[index];
1463
+ stopNote(endTime, stopTime, noteList, index) {
1464
+ const note = noteList[index];
1452
1465
  note.volumeEnvelopeNode.gain
1453
1466
  .cancelScheduledValues(endTime)
1454
1467
  .linearRampToValueAtTime(0, stopTime);
@@ -1458,12 +1471,23 @@ class Midy {
1458
1471
  }, stopTime);
1459
1472
  return new Promise((resolve) => {
1460
1473
  note.bufferSource.onended = () => {
1461
- this.disconnectNote(note, scheduledNotes, index);
1474
+ noteList[index] = undefined;
1475
+ this.disconnectNote(note);
1462
1476
  resolve();
1463
1477
  };
1464
1478
  note.bufferSource.stop(stopTime);
1465
1479
  });
1466
1480
  }
1481
+ findNoteOffTarget(noteList) {
1482
+ for (let i = 0; i < noteList.length; i++) {
1483
+ const note = noteList[i];
1484
+ if (!note)
1485
+ continue;
1486
+ if (note.ending)
1487
+ continue;
1488
+ return [note, i];
1489
+ }
1490
+ }
1467
1491
  scheduleNoteOff(channelNumber, noteNumber, _velocity, endTime, force, portamentoNoteNumber) {
1468
1492
  const channel = this.channels[channelNumber];
1469
1493
  if (this.isDrumNoteOffException(channel, noteNumber))
@@ -1475,35 +1499,32 @@ class Midy {
1475
1499
  if (channel.sostenutoNotes.has(noteNumber))
1476
1500
  return;
1477
1501
  }
1478
- if (!channel.scheduledNotes.has(noteNumber))
1502
+ const noteList = channel.scheduledNotes.get(noteNumber);
1503
+ if (!noteList)
1504
+ return; // be careful with drum channel
1505
+ const noteOffTarget = this.findNoteOffTarget(noteList, endTime);
1506
+ if (!noteOffTarget)
1479
1507
  return;
1480
- const scheduledNotes = channel.scheduledNotes.get(noteNumber);
1481
- for (let i = 0; i < scheduledNotes.length; i++) {
1482
- const note = scheduledNotes[i];
1483
- if (!note)
1484
- continue;
1485
- if (note.ending)
1486
- continue;
1487
- if (portamentoNoteNumber === undefined) {
1488
- const volRelease = endTime +
1489
- note.voiceParams.volRelease * state.releaseTime * 2;
1490
- const modRelease = endTime + note.voiceParams.modRelease;
1491
- note.filterNode.frequency
1492
- .cancelScheduledValues(endTime)
1493
- .linearRampToValueAtTime(0, modRelease);
1494
- const stopTime = Math.min(volRelease, modRelease);
1495
- return this.stopNote(endTime, stopTime, scheduledNotes, i);
1496
- }
1497
- else {
1498
- const portamentoTime = endTime + this.getPortamentoTime(channel);
1499
- const deltaNote = portamentoNoteNumber - noteNumber;
1500
- const baseRate = note.voiceParams.playbackRate;
1501
- const targetRate = baseRate * Math.pow(2, deltaNote / 12);
1502
- note.bufferSource.playbackRate
1503
- .cancelScheduledValues(endTime)
1504
- .linearRampToValueAtTime(targetRate, portamentoTime);
1505
- return this.stopNote(endTime, portamentoTime, scheduledNotes, i);
1506
- }
1508
+ const [note, i] = noteOffTarget;
1509
+ if (0.5 <= state.portamento && portamentoNoteNumber !== undefined) {
1510
+ const portamentoTime = endTime + this.getPortamentoTime(channel);
1511
+ const deltaNote = portamentoNoteNumber - noteNumber;
1512
+ const baseRate = note.voiceParams.playbackRate;
1513
+ const targetRate = baseRate * Math.pow(2, deltaNote / 12);
1514
+ note.bufferSource.playbackRate
1515
+ .cancelScheduledValues(endTime)
1516
+ .linearRampToValueAtTime(targetRate, portamentoTime);
1517
+ return this.stopNote(endTime, portamentoTime, noteList, i);
1518
+ }
1519
+ else {
1520
+ const volRelease = endTime +
1521
+ note.voiceParams.volRelease * state.releaseTime * 2;
1522
+ const modRelease = endTime + note.voiceParams.modRelease;
1523
+ note.filterNode.frequency
1524
+ .cancelScheduledValues(endTime)
1525
+ .linearRampToValueAtTime(0, modRelease);
1526
+ const stopTime = Math.min(volRelease, modRelease);
1527
+ return this.stopNote(endTime, stopTime, noteList, i);
1507
1528
  }
1508
1529
  }
1509
1530
  noteOff(channelNumber, noteNumber, velocity, scheduleTime) {
@@ -1565,7 +1586,7 @@ class Midy {
1565
1586
  const note = activeNotes.get(noteNumber);
1566
1587
  this.setControllerParameters(channel, note, table);
1567
1588
  }
1568
- // this.applyVoiceParams(channel, 10);
1589
+ this.applyVoiceParams(channel, 10);
1569
1590
  }
1570
1591
  handleProgramChange(channelNumber, programNumber, _scheduleTime) {
1571
1592
  const channel = this.channels[channelNumber];
@@ -1597,7 +1618,7 @@ class Midy {
1597
1618
  this.getActiveNotes(channel, scheduleTime).forEach((note) => {
1598
1619
  this.setControllerParameters(channel, note, table);
1599
1620
  });
1600
- // this.applyVoiceParams(channel, 13);
1621
+ this.applyVoiceParams(channel, 13);
1601
1622
  }
1602
1623
  handlePitchBendMessage(channelNumber, lsb, msb, scheduleTime) {
1603
1624
  const pitchBend = msb * 128 + lsb;
@@ -1774,6 +1795,8 @@ class Midy {
1774
1795
  state.set(channel.state.array);
1775
1796
  state[2] = velocity / 127;
1776
1797
  state[3] = noteNumber / 127;
1798
+ state[10] = state.polyphonicKeyPressure / 127;
1799
+ state[13] = state.channelPressure / 127;
1777
1800
  return state;
1778
1801
  }
1779
1802
  applyVoiceParams(channel, controllerType, scheduleTime) {
@@ -1800,7 +1823,7 @@ class Midy {
1800
1823
  if (key in voiceParams)
1801
1824
  noteVoiceParams[key] = voiceParams[key];
1802
1825
  }
1803
- if (note.portamento) {
1826
+ if (0.5 <= channel.state.portamento && note.portamento) {
1804
1827
  this.setPortamentoStartFilterEnvelope(channel, note, scheduleTime);
1805
1828
  }
1806
1829
  else {
@@ -2007,10 +2030,11 @@ class Midy {
2007
2030
  const channel = this.channels[channelNumber];
2008
2031
  if (channel.isDrum)
2009
2032
  return;
2033
+ const state = channel.state;
2010
2034
  scheduleTime ??= this.audioContext.currentTime;
2011
- channel.state.softPedal = softPedal / 127;
2035
+ state.softPedal = softPedal / 127;
2012
2036
  this.processScheduledNotes(channel, (note) => {
2013
- if (note.portamento) {
2037
+ if (0.5 <= state.portamento && note.portamento) {
2014
2038
  this.setPortamentoStartVolumeEnvelope(channel, note, scheduleTime);
2015
2039
  this.setPortamentoStartFilterEnvelope(channel, note, scheduleTime);
2016
2040
  }
@@ -2032,7 +2056,7 @@ class Midy {
2032
2056
  note.filterNode.Q.setValueAtTime(Q, scheduleTime);
2033
2057
  });
2034
2058
  }
2035
- setReleaseTime(channelNumber, releaseTime, _scheduleTime) {
2059
+ setReleaseTime(channelNumber, releaseTime, scheduleTime) {
2036
2060
  const channel = this.channels[channelNumber];
2037
2061
  if (channel.isDrum)
2038
2062
  return;
@@ -2055,10 +2079,11 @@ class Midy {
2055
2079
  const channel = this.channels[channelNumber];
2056
2080
  if (channel.isDrum)
2057
2081
  return;
2082
+ const state = channel.state;
2058
2083
  scheduleTime ??= this.audioContext.currentTime;
2059
- channel.state.brightness = brightness / 64;
2084
+ state.brightness = brightness / 64;
2060
2085
  this.processScheduledNotes(channel, (note) => {
2061
- if (note.portamento) {
2086
+ if (0.5 <= state.portamento && note.portamento) {
2062
2087
  this.setPortamentoStartFilterEnvelope(channel, note, scheduleTime);
2063
2088
  }
2064
2089
  else {
@@ -2319,7 +2344,7 @@ class Midy {
2319
2344
  }
2320
2345
  allSoundOff(channelNumber, _value, scheduleTime) {
2321
2346
  scheduleTime ??= this.audioContext.currentTime;
2322
- return this.stopChannelNotes(channelNumber, 0, true, scheduleTime);
2347
+ return this.stopActiveNotes(channelNumber, 0, true, scheduleTime);
2323
2348
  }
2324
2349
  resetAllStates(channelNumber) {
2325
2350
  const channel = this.channels[channelNumber];
@@ -2364,7 +2389,7 @@ class Midy {
2364
2389
  }
2365
2390
  allNotesOff(channelNumber, _value, scheduleTime) {
2366
2391
  scheduleTime ??= this.audioContext.currentTime;
2367
- return this.stopChannelNotes(channelNumber, 0, false, scheduleTime);
2392
+ return this.stopActiveNotes(channelNumber, 0, false, scheduleTime);
2368
2393
  }
2369
2394
  omniOff(channelNumber, value, scheduleTime) {
2370
2395
  this.allNotesOff(channelNumber, value, scheduleTime);