@marmooo/midy 0.1.2 → 0.1.4

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.
Files changed (35) hide show
  1. package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.d.ts +153 -0
  2. package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.d.ts.map +1 -0
  3. package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/{soundfont-parser@0.0.2 → soundfont-parser@0.0.4}/+esm.js +73 -66
  4. package/esm/midy-GM1.d.ts +19 -13
  5. package/esm/midy-GM1.d.ts.map +1 -1
  6. package/esm/midy-GM1.js +171 -131
  7. package/esm/midy-GM2.d.ts +22 -14
  8. package/esm/midy-GM2.d.ts.map +1 -1
  9. package/esm/midy-GM2.js +186 -133
  10. package/esm/midy-GMLite.d.ts +17 -13
  11. package/esm/midy-GMLite.d.ts.map +1 -1
  12. package/esm/midy-GMLite.js +159 -131
  13. package/esm/midy.d.ts +30 -16
  14. package/esm/midy.d.ts.map +1 -1
  15. package/esm/midy.js +266 -166
  16. package/package.json +1 -1
  17. package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.d.ts +153 -0
  18. package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.d.ts.map +1 -0
  19. package/script/deps/cdn.jsdelivr.net/npm/@marmooo/{soundfont-parser@0.0.2 → soundfont-parser@0.0.4}/+esm.js +75 -68
  20. package/script/midy-GM1.d.ts +19 -13
  21. package/script/midy-GM1.d.ts.map +1 -1
  22. package/script/midy-GM1.js +171 -131
  23. package/script/midy-GM2.d.ts +22 -14
  24. package/script/midy-GM2.d.ts.map +1 -1
  25. package/script/midy-GM2.js +186 -133
  26. package/script/midy-GMLite.d.ts +17 -13
  27. package/script/midy-GMLite.d.ts.map +1 -1
  28. package/script/midy-GMLite.js +159 -131
  29. package/script/midy.d.ts +30 -16
  30. package/script/midy.d.ts.map +1 -1
  31. package/script/midy.js +266 -166
  32. package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.d.ts +0 -135
  33. package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.d.ts.map +0 -1
  34. package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.d.ts +0 -135
  35. package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.d.ts.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { parseMidi } from "./deps/cdn.jsdelivr.net/npm/midi-file@1.2.4/+esm.js";
2
- import { parse, SoundFont, } from "./deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.js";
2
+ import { parse, SoundFont, } from "./deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.js";
3
3
  class Note {
4
4
  constructor(noteNumber, velocity, startTime, instrumentKey) {
5
5
  Object.defineProperty(this, "bufferSource", {
@@ -8,25 +8,31 @@ class Note {
8
8
  writable: true,
9
9
  value: void 0
10
10
  });
11
- Object.defineProperty(this, "gainNode", {
11
+ Object.defineProperty(this, "filterNode", {
12
12
  enumerable: true,
13
13
  configurable: true,
14
14
  writable: true,
15
15
  value: void 0
16
16
  });
17
- Object.defineProperty(this, "filterNode", {
17
+ Object.defineProperty(this, "volumeNode", {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value: void 0
22
+ });
23
+ Object.defineProperty(this, "volumeDepth", {
18
24
  enumerable: true,
19
25
  configurable: true,
20
26
  writable: true,
21
27
  value: void 0
22
28
  });
23
- Object.defineProperty(this, "modLFO", {
29
+ Object.defineProperty(this, "modulationLFO", {
24
30
  enumerable: true,
25
31
  configurable: true,
26
32
  writable: true,
27
33
  value: void 0
28
34
  });
29
- Object.defineProperty(this, "modLFOGain", {
35
+ Object.defineProperty(this, "modulationDepth", {
30
36
  enumerable: true,
31
37
  configurable: true,
32
38
  writable: true,
@@ -313,7 +319,7 @@ export class MidyGMLite {
313
319
  const t = this.audioContext.currentTime + offset;
314
320
  queueIndex = await this.scheduleTimelineEvents(t, offset, queueIndex);
315
321
  if (this.isPausing) {
316
- await this.stopNotes();
322
+ await this.stopNotes(0, true);
317
323
  this.notePromises = [];
318
324
  resolve();
319
325
  this.isPausing = false;
@@ -321,7 +327,7 @@ export class MidyGMLite {
321
327
  return;
322
328
  }
323
329
  else if (this.isStopping) {
324
- await this.stopNotes();
330
+ await this.stopNotes(0, true);
325
331
  this.notePromises = [];
326
332
  resolve();
327
333
  this.isStopping = false;
@@ -329,7 +335,7 @@ export class MidyGMLite {
329
335
  return;
330
336
  }
331
337
  else if (this.isSeeking) {
332
- this.stopNotes();
338
+ this.stopNotes(0, true);
333
339
  this.startTime = this.audioContext.currentTime;
334
340
  queueIndex = this.getQueueIndex(this.resumeTime);
335
341
  offset = this.resumeTime - this.startTime;
@@ -410,21 +416,25 @@ export class MidyGMLite {
410
416
  }
411
417
  return { instruments, timeline };
412
418
  }
413
- stopNotes() {
419
+ async stopChannelNotes(channelNumber, velocity, stopPedal) {
414
420
  const now = this.audioContext.currentTime;
415
- const velocity = 0;
416
- const stopPedal = true;
417
- this.channels.forEach((channel, channelNumber) => {
418
- channel.scheduledNotes.forEach((scheduledNotes) => {
419
- scheduledNotes.forEach((scheduledNote) => {
420
- if (scheduledNote) {
421
- const promise = this.scheduleNoteRelease(channelNumber, scheduledNote.noteNumber, velocity, now, stopPedal);
422
- this.notePromises.push(promise);
423
- }
424
- });
425
- });
426
- channel.scheduledNotes.clear();
421
+ const channel = this.channels[channelNumber];
422
+ channel.scheduledNotes.forEach((noteList) => {
423
+ for (let i = 0; i < noteList.length; i++) {
424
+ const note = noteList[i];
425
+ if (!note)
426
+ continue;
427
+ const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now, stopPedal);
428
+ this.notePromises.push(promise);
429
+ }
427
430
  });
431
+ channel.scheduledNotes.clear();
432
+ await Promise.all(this.notePromises);
433
+ }
434
+ stopNotes(velocity, stopPedal) {
435
+ for (let i = 0; i < this.channels.length; i++) {
436
+ this.stopChannelNotes(i, velocity, stopPedal);
437
+ }
428
438
  return Promise.all(this.notePromises);
429
439
  }
430
440
  async start() {
@@ -507,75 +517,111 @@ export class MidyGMLite {
507
517
  }
508
518
  setVolumeEnvelope(note) {
509
519
  const { instrumentKey, startTime } = note;
510
- note.gainNode = new GainNode(this.audioContext, { gain: 0 });
511
520
  const attackVolume = this.cbToRatio(-instrumentKey.initialAttenuation);
512
521
  const sustainVolume = attackVolume * (1 - instrumentKey.volSustain);
513
522
  const volDelay = startTime + instrumentKey.volDelay;
514
523
  const volAttack = volDelay + instrumentKey.volAttack;
515
524
  const volHold = volAttack + instrumentKey.volHold;
516
525
  const volDecay = volHold + instrumentKey.volDecay;
517
- note.gainNode.gain
526
+ note.volumeNode.gain
527
+ .cancelScheduledValues(startTime)
528
+ .setValueAtTime(0, startTime)
518
529
  .setValueAtTime(1e-6, volDelay) // exponentialRampToValueAtTime() requires a non-zero value
519
530
  .exponentialRampToValueAtTime(attackVolume, volAttack)
520
531
  .setValueAtTime(attackVolume, volHold)
521
532
  .linearRampToValueAtTime(sustainVolume, volDecay);
522
533
  }
523
- setFilterEnvelope(channel, note) {
524
- const { instrumentKey, startTime, noteNumber } = note;
525
- const softPedalFactor = 1 -
526
- (0.1 + (noteNumber / 127) * 0.2) * channel.softPedal;
527
- const maxFreq = this.audioContext.sampleRate / 2;
528
- const baseFreq = this.centToHz(instrumentKey.initialFilterFc) *
529
- softPedalFactor;
530
- const peekFreq = this.centToHz(instrumentKey.initialFilterFc + instrumentKey.modEnvToFilterFc) * softPedalFactor;
531
- const sustainFreq = (baseFreq +
532
- (peekFreq - baseFreq) * (1 - instrumentKey.modSustain)) * softPedalFactor;
534
+ setPitch(note, semitoneOffset) {
535
+ const { instrumentKey, noteNumber, startTime } = note;
536
+ const modEnvToPitch = instrumentKey.modEnvToPitch / 100;
537
+ note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
538
+ if (modEnvToPitch === 0)
539
+ return;
540
+ const basePitch = note.bufferSource.playbackRate.value;
541
+ const peekPitch = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset + modEnvToPitch);
542
+ const modDelay = startTime + instrumentKey.modDelay;
543
+ const modAttack = modDelay + instrumentKey.modAttack;
544
+ const modHold = modAttack + instrumentKey.modHold;
545
+ const modDecay = modHold + instrumentKey.modDecay;
546
+ note.bufferSource.playbackRate.value
547
+ .setValueAtTime(basePitch, modDelay)
548
+ .exponentialRampToValueAtTime(peekPitch, modAttack)
549
+ .setValueAtTime(peekPitch, modHold)
550
+ .linearRampToValueAtTime(basePitch, modDecay);
551
+ }
552
+ clampCutoffFrequency(frequency) {
553
+ const minFrequency = 20; // min Hz of initialFilterFc
554
+ const maxFrequency = 20000; // max Hz of initialFilterFc
555
+ return Math.max(minFrequency, Math.min(frequency, maxFrequency));
556
+ }
557
+ setFilterEnvelope(note) {
558
+ const { instrumentKey, startTime } = note;
559
+ const baseFreq = this.centToHz(instrumentKey.initialFilterFc);
560
+ const peekFreq = this.centToHz(instrumentKey.initialFilterFc + instrumentKey.modEnvToFilterFc);
561
+ const sustainFreq = baseFreq +
562
+ (peekFreq - baseFreq) * (1 - instrumentKey.modSustain);
563
+ const adjustedBaseFreq = this.clampCutoffFrequency(baseFreq);
564
+ const adjustedPeekFreq = this.clampCutoffFrequency(peekFreq);
565
+ const adjustedSustainFreq = this.clampCutoffFrequency(sustainFreq);
533
566
  const modDelay = startTime + instrumentKey.modDelay;
534
567
  const modAttack = modDelay + instrumentKey.modAttack;
535
568
  const modHold = modAttack + instrumentKey.modHold;
536
569
  const modDecay = modHold + instrumentKey.modDecay;
537
- const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
538
- const adjustedPeekFreq = Math.min(maxFreq, peekFreq);
539
- const adjustedSustainFreq = Math.min(maxFreq, sustainFreq);
540
- note.filterNode = new BiquadFilterNode(this.audioContext, {
541
- type: "lowpass",
542
- Q: instrumentKey.initialFilterQ / 10, // dB
543
- frequency: adjustedBaseFreq,
544
- });
545
570
  note.filterNode.frequency
571
+ .cancelScheduledValues(startTime)
572
+ .setValueAtTime(adjustedBaseFreq, startTime)
546
573
  .setValueAtTime(adjustedBaseFreq, modDelay)
547
574
  .exponentialRampToValueAtTime(adjustedPeekFreq, modAttack)
548
575
  .setValueAtTime(adjustedPeekFreq, modHold)
549
576
  .linearRampToValueAtTime(adjustedSustainFreq, modDecay);
550
- note.bufferSource.detune.setValueAtTime(note.bufferSource.detune.value + instrumentKey.modEnvToPitch, modDelay);
551
577
  }
552
- startModulation(channel, note, time) {
578
+ startModulation(channel, note, startTime) {
553
579
  const { instrumentKey } = note;
554
- note.modLFOGain = new GainNode(this.audioContext, {
555
- gain: this.cbToRatio(instrumentKey.modLfoToVolume + channel.modulation),
556
- });
557
- note.modLFO = new OscillatorNode(this.audioContext, {
580
+ const { modLfoToPitch, modLfoToVolume } = instrumentKey;
581
+ note.modulationLFO = new OscillatorNode(this.audioContext, {
558
582
  frequency: this.centToHz(instrumentKey.freqModLFO),
559
583
  });
560
- note.modLFO.start(time);
561
- note.filterNode.frequency.setValueAtTime(note.filterNode.frequency.value + instrumentKey.modLfoToFilterFc, time);
562
- note.bufferSource.detune.setValueAtTime(note.bufferSource.detune.value + instrumentKey.modLfoToPitch, time);
563
- note.modLFO.connect(note.modLFOGain);
564
- note.modLFOGain.connect(note.bufferSource.detune);
584
+ note.filterDepth = new GainNode(this.audioContext, {
585
+ gain: instrumentKey.modLfoToFilterFc,
586
+ });
587
+ const modulationDepth = Math.abs(modLfoToPitch) + channel.modulationDepth;
588
+ const modulationDepthSign = (0 < modLfoToPitch) ? 1 : -1;
589
+ note.modulationDepth = new GainNode(this.audioContext, {
590
+ gain: modulationDepth * modulationDepthSign,
591
+ });
592
+ const volumeDepth = this.cbToRatio(Math.abs(modLfoToVolume)) - 1;
593
+ const volumeDepthSign = (0 < modLfoToVolume) ? 1 : -1;
594
+ note.volumeDepth = new GainNode(this.audioContext, {
595
+ gain: volumeDepth * volumeDepthSign,
596
+ });
597
+ note.modulationLFO.start(startTime + instrumentKey.delayModLFO);
598
+ note.modulationLFO.connect(note.filterDepth);
599
+ note.filterDepth.connect(note.filterNode.frequency);
600
+ note.modulationLFO.connect(note.modulationDepth);
601
+ note.modulationDepth.connect(note.bufferSource.detune);
602
+ note.modulationLFO.connect(note.volumeDepth);
603
+ note.volumeDepth.connect(note.volumeNode.gain);
565
604
  }
566
605
  async createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3) {
567
606
  const semitoneOffset = this.calcSemitoneOffset(channel);
568
607
  const note = new Note(noteNumber, velocity, startTime, instrumentKey);
569
608
  note.bufferSource = await this.createNoteBufferNode(instrumentKey, isSF3);
570
- note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
609
+ note.volumeNode = new GainNode(this.audioContext);
610
+ note.filterNode = new BiquadFilterNode(this.audioContext, {
611
+ type: "lowpass",
612
+ Q: instrumentKey.initialFilterQ / 10 * channel.filterResonance, // dB
613
+ });
571
614
  this.setVolumeEnvelope(note);
572
- this.setFilterEnvelope(channel, note);
573
- if (channel.modulation > 0) {
574
- const delayModLFO = startTime + instrumentKey.delayModLFO;
575
- this.startModulation(channel, note, delayModLFO);
615
+ this.setFilterEnvelope(note);
616
+ if (0 < channel.modulationDepth) {
617
+ this.setPitch(note, semitoneOffset);
618
+ this.startModulation(channel, note, startTime);
619
+ }
620
+ else {
621
+ note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
576
622
  }
577
623
  note.bufferSource.connect(note.filterNode);
578
- note.filterNode.connect(note.gainNode);
624
+ note.filterNode.connect(note.volumeNode);
579
625
  note.bufferSource.start(startTime, instrumentKey.start / instrumentKey.sampleRate);
580
626
  return note;
581
627
  }
@@ -591,8 +637,8 @@ export class MidyGMLite {
591
637
  if (!instrumentKey)
592
638
  return;
593
639
  const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
594
- note.gainNode.connect(channel.gainL);
595
- note.gainNode.connect(channel.gainR);
640
+ note.volumeNode.connect(channel.gainL);
641
+ note.volumeNode.connect(channel.gainR);
596
642
  const scheduledNotes = channel.scheduledNotes;
597
643
  if (scheduledNotes.has(noteNumber)) {
598
644
  scheduledNotes.get(noteNumber).push(note);
@@ -605,7 +651,7 @@ export class MidyGMLite {
605
651
  const now = this.audioContext.currentTime;
606
652
  return this.scheduleNoteOn(channelNumber, noteNumber, velocity, now);
607
653
  }
608
- scheduleNoteRelease(channelNumber, noteNumber, velocity, stopTime, stopPedal = false) {
654
+ scheduleNoteRelease(channelNumber, noteNumber, _velocity, stopTime, stopPedal = false) {
609
655
  const channel = this.channels[channelNumber];
610
656
  if (stopPedal && channel.sustainPedal)
611
657
  return;
@@ -618,20 +664,14 @@ export class MidyGMLite {
618
664
  continue;
619
665
  if (note.ending)
620
666
  continue;
621
- const velocityRate = (velocity + 127) / 127;
622
- const volEndTime = stopTime +
623
- note.instrumentKey.volRelease * velocityRate;
624
- note.gainNode.gain
667
+ const volEndTime = stopTime + note.instrumentKey.volRelease;
668
+ note.volumeNode.gain
625
669
  .cancelScheduledValues(stopTime)
626
670
  .linearRampToValueAtTime(0, volEndTime);
627
- const maxFreq = this.audioContext.sampleRate / 2;
628
- const baseFreq = this.centToHz(note.instrumentKey.initialFilterFc);
629
- const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
630
- const modEndTime = stopTime +
631
- note.instrumentKey.modRelease * velocityRate;
671
+ const modRelease = stopTime + note.instrumentKey.modRelease;
632
672
  note.filterNode.frequency
633
673
  .cancelScheduledValues(stopTime)
634
- .linearRampToValueAtTime(adjustedBaseFreq, modEndTime);
674
+ .linearRampToValueAtTime(0, modRelease);
635
675
  note.ending = true;
636
676
  this.scheduleTask(() => {
637
677
  note.bufferSource.loop = false;
@@ -640,15 +680,17 @@ export class MidyGMLite {
640
680
  note.bufferSource.onended = () => {
641
681
  scheduledNotes[i] = null;
642
682
  note.bufferSource.disconnect();
683
+ note.volumeNode.disconnect();
643
684
  note.filterNode.disconnect();
644
- note.gainNode.disconnect();
645
- if (note.modLFOGain)
646
- note.modLFOGain.disconnect();
647
- if (note.modLFO)
648
- note.modLFO.stop();
685
+ if (note.volumeDepth)
686
+ note.volumeDepth.disconnect();
687
+ if (note.modulationDepth)
688
+ note.modulationDepth.disconnect();
689
+ if (note.modulationLFO)
690
+ note.modulationLFO.stop();
649
691
  resolve();
650
692
  };
651
- bufferSource.stop(volEndTime);
693
+ note.bufferSource.stop(volEndTime);
652
694
  });
653
695
  }
654
696
  }
@@ -661,14 +703,15 @@ export class MidyGMLite {
661
703
  const channel = this.channels[channelNumber];
662
704
  const promises = [];
663
705
  channel.sustainPedal = false;
664
- channel.scheduledNotes.forEach((scheduledNotes) => {
665
- scheduledNotes.forEach((scheduledNote) => {
666
- if (scheduledNote) {
667
- const { noteNumber } = scheduledNote;
668
- const promise = this.releaseNote(channelNumber, noteNumber, velocity);
669
- promises.push(promise);
670
- }
671
- });
706
+ channel.scheduledNotes.forEach((noteList) => {
707
+ for (let i = 0; i < noteList.length; i++) {
708
+ const note = noteList[i];
709
+ if (!note)
710
+ continue;
711
+ const { noteNumber } = note;
712
+ const promise = this.releaseNote(channelNumber, noteNumber, velocity);
713
+ promises.push(promise);
714
+ }
672
715
  });
673
716
  return promises;
674
717
  }
@@ -709,7 +752,7 @@ export class MidyGMLite {
709
752
  handleControlChange(channelNumber, controller, value) {
710
753
  switch (controller) {
711
754
  case 1:
712
- return this.setModulation(channelNumber, value);
755
+ return this.setModulationDepth(channelNumber, value);
713
756
  case 6:
714
757
  return this.dataEntryMSB(channelNumber, value);
715
758
  case 7:
@@ -738,20 +781,25 @@ export class MidyGMLite {
738
781
  }
739
782
  updateModulation(channel) {
740
783
  const now = this.audioContext.currentTime;
741
- const activeNotes = this.getActiveNotes(channel, now);
742
- activeNotes.forEach((activeNote) => {
743
- if (activeNote.modLFO) {
744
- const { gainNode, instrumentKey } = activeNote;
745
- gainNode.gain.setValueAtTime(this.cbToRatio(instrumentKey.modLfoToVolume + channel.modulation), now);
746
- }
747
- else {
748
- this.startModulation(channel, activeNote, now);
784
+ channel.scheduledNotes.forEach((noteList) => {
785
+ for (let i = 0; i < noteList.length; i++) {
786
+ const note = noteList[i];
787
+ if (!note)
788
+ continue;
789
+ if (note.modulationDepth) {
790
+ note.modulationDepth.gain.setValueAtTime(channel.modulationDepth, now);
791
+ }
792
+ else {
793
+ const semitoneOffset = this.calcSemitoneOffset(channel);
794
+ this.setPitch(note, semitoneOffset);
795
+ this.startModulation(channel, note, now);
796
+ }
749
797
  }
750
798
  });
751
799
  }
752
- setModulation(channelNumber, modulation) {
800
+ setModulationDepth(channelNumber, modulation) {
753
801
  const channel = this.channels[channelNumber];
754
- channel.modulation = (modulation / 127) * channel.modulationDepthRange;
802
+ channel.modulationDepth = (modulation / 127) * channel.modulationDepthRange;
755
803
  this.updateModulation(channel);
756
804
  }
757
805
  setVolume(channelNumber, volume) {
@@ -821,13 +869,17 @@ export class MidyGMLite {
821
869
  }
822
870
  updateDetune(channel, detuneChange) {
823
871
  const now = this.audioContext.currentTime;
824
- const activeNotes = this.getActiveNotes(channel, now);
825
- activeNotes.forEach((activeNote) => {
826
- const { bufferSource } = activeNote;
827
- const detune = bufferSource.detune.value + detuneChange;
828
- bufferSource.detune
829
- .cancelScheduledValues(now)
830
- .setValueAtTime(detune, now);
872
+ channel.scheduledNotes.forEach((noteList) => {
873
+ for (let i = 0; i < noteList.length; i++) {
874
+ const note = noteList[i];
875
+ if (!note)
876
+ continue;
877
+ const { bufferSource } = note;
878
+ const detune = bufferSource.detune.value + detuneChange;
879
+ bufferSource.detune
880
+ .cancelScheduledValues(now)
881
+ .setValueAtTime(detune, now);
882
+ }
831
883
  });
832
884
  }
833
885
  handlePitchBendRangeRPN(channelNumber) {
@@ -845,37 +897,13 @@ export class MidyGMLite {
845
897
  this.updateDetune(channel, detuneChange);
846
898
  }
847
899
  allSoundOff(channelNumber) {
848
- const now = this.audioContext.currentTime;
849
- const channel = this.channels[channelNumber];
850
- const velocity = 0;
851
- const stopPedal = true;
852
- const promises = [];
853
- channel.scheduledNotes.forEach((noteList) => {
854
- const activeNote = this.getActiveNote(noteList, now);
855
- if (activeNote) {
856
- const notePromise = this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now, stopPedal);
857
- promises.push(notePromise);
858
- }
859
- });
860
- return promises;
900
+ return this.stopChannelNotes(channelNumber, 0, true);
861
901
  }
862
902
  resetAllControllers(channelNumber) {
863
903
  Object.assign(this.channels[channelNumber], this.effectSettings);
864
904
  }
865
905
  allNotesOff(channelNumber) {
866
- const now = this.audioContext.currentTime;
867
- const channel = this.channels[channelNumber];
868
- const velocity = 0;
869
- const stopPedal = false;
870
- const promises = [];
871
- channel.scheduledNotes.forEach((noteList) => {
872
- const activeNote = this.getActiveNote(noteList, now);
873
- if (activeNote) {
874
- const notePromise = this.scheduleNoteRelease(channelNumber, activeNote.noteNumber, velocity, now, stopPedal);
875
- promises.push(notePromise);
876
- }
877
- });
878
- return promises;
906
+ return this.stopChannelNotes(channelNumber, 0, false);
879
907
  }
880
908
  handleUniversalNonRealTimeExclusiveMessage(data) {
881
909
  switch (data[2]) {
@@ -968,7 +996,7 @@ Object.defineProperty(MidyGMLite, "channelSettings", {
968
996
  dataLSB: 0,
969
997
  program: 0,
970
998
  pitchBend: 0,
971
- modulationDepthRange: 0.5, // cb
999
+ modulationDepthRange: 50, // cent
972
1000
  }
973
1001
  });
974
1002
  Object.defineProperty(MidyGMLite, "effectSettings", {
@@ -977,7 +1005,7 @@ Object.defineProperty(MidyGMLite, "effectSettings", {
977
1005
  writable: true,
978
1006
  value: {
979
1007
  expression: 1,
980
- modulation: 0,
1008
+ modulationDepth: 0,
981
1009
  sustainPedal: false,
982
1010
  rpnMSB: 127,
983
1011
  rpnLSB: 127,
package/esm/midy.d.ts CHANGED
@@ -4,6 +4,11 @@ export class Midy {
4
4
  volume: number;
5
5
  pan: number;
6
6
  portamentoTime: number;
7
+ filterResonance: number;
8
+ releaseTime: number;
9
+ attackTime: number;
10
+ brightness: number;
11
+ decayTime: number;
7
12
  reverbSendLevel: number;
8
13
  chorusSendLevel: number;
9
14
  vibratoRate: number;
@@ -22,7 +27,7 @@ export class Midy {
22
27
  };
23
28
  static effectSettings: {
24
29
  expression: number;
25
- modulation: number;
30
+ modulationDepth: number;
26
31
  sustainPedal: boolean;
27
32
  portamento: boolean;
28
33
  sostenutoPedal: boolean;
@@ -128,7 +133,8 @@ export class Midy {
128
133
  instruments: Set<any>;
129
134
  timeline: any[];
130
135
  };
131
- stopNotes(): Promise<any[]>;
136
+ stopChannelNotes(channelNumber: any, velocity: any, stopPedal: any): Promise<void>;
137
+ stopNotes(velocity: any, stopPedal: any): Promise<any[]>;
132
138
  start(): Promise<void>;
133
139
  stop(): void;
134
140
  pause(): void;
@@ -164,28 +170,30 @@ export class Midy {
164
170
  centToHz(cent: any): number;
165
171
  calcSemitoneOffset(channel: any): any;
166
172
  calcPlaybackRate(instrumentKey: any, noteNumber: any, semitoneOffset: any): number;
167
- setVolumeEnvelope(note: any): void;
173
+ setVolumeEnvelope(channel: any, note: any): void;
174
+ setPitch(note: any, semitoneOffset: any): void;
175
+ clampCutoffFrequency(frequency: any): number;
168
176
  setFilterEnvelope(channel: any, note: any): void;
169
- startModulation(channel: any, note: any, time: any): void;
170
- startVibrato(channel: any, note: any, time: any): void;
177
+ startModulation(channel: any, note: any, startTime: any): void;
178
+ startVibrato(channel: any, note: any, startTime: any): void;
171
179
  createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
172
180
  calcBank(channel: any, channelNumber: any): any;
173
181
  scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
174
182
  noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
175
- scheduleNoteRelease(channelNumber: any, noteNumber: any, velocity: any, stopTime: any, stopPedal?: boolean): Promise<any> | undefined;
183
+ scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, stopTime: any, stopPedal?: boolean): Promise<any> | undefined;
176
184
  releaseNote(channelNumber: any, noteNumber: any, velocity: any): Promise<any> | undefined;
177
185
  releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
178
186
  releaseSostenutoPedal(channelNumber: any, halfVelocity: any): any[];
179
- handleMIDIMessage(statusByte: any, data1: any, data2: any): void | any[] | Promise<any>;
187
+ handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
180
188
  handlePolyphonicKeyPressure(channelNumber: any, noteNumber: any, pressure: any): void;
181
189
  handleProgramChange(channelNumber: any, program: any): void;
182
190
  handleChannelPressure(channelNumber: any, pressure: any): void;
183
191
  handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
184
192
  setPitchBend(channelNumber: any, pitchBend: any): void;
185
- handleControlChange(channelNumber: any, controller: any, value: any): void | any[];
193
+ handleControlChange(channelNumber: any, controller: any, value: any): void | Promise<void>;
186
194
  setBankMSB(channelNumber: any, msb: any): void;
187
195
  updateModulation(channel: any): void;
188
- setModulation(channelNumber: any, modulation: any): void;
196
+ setModulationDepth(channelNumber: any, modulation: any): void;
189
197
  setPortamentoTime(channelNumber: any, portamentoTime: any): void;
190
198
  setVolume(channelNumber: any, volume: any): void;
191
199
  panToGain(pan: any): {
@@ -203,6 +211,11 @@ export class Midy {
203
211
  setChorusSendLevel(channelNumber: any, chorusSendLevel: any): void;
204
212
  setSostenutoPedal(channelNumber: any, value: any): void;
205
213
  setSoftPedal(channelNumber: any, softPedal: any): void;
214
+ setFilterResonance(channelNumber: any, filterResonance: any): void;
215
+ setReleaseTime(channelNumber: any, releaseTime: any): void;
216
+ setAttackTime(channelNumber: any, attackTime: any): void;
217
+ setBrightness(channelNumber: any, brightness: any): void;
218
+ setDecayTime(channelNumber: any, dacayTime: any): void;
206
219
  setVibratoRate(channelNumber: any, vibratoRate: any): void;
207
220
  setVibratoDepth(channelNumber: any, vibratoDepth: any): void;
208
221
  setVibratoDelay(channelNumber: any, vibratoDelay: any): void;
@@ -223,9 +236,9 @@ export class Midy {
223
236
  setCoarseTuning(channelNumber: any, coarseTuning: any): void;
224
237
  handleModulationDepthRangeRPN(channelNumber: any): void;
225
238
  setModulationDepthRange(channelNumber: any, modulationDepthRange: any): void;
226
- allSoundOff(channelNumber: any): any[];
239
+ allSoundOff(channelNumber: any): Promise<void>;
227
240
  resetAllControllers(channelNumber: any): void;
228
- allNotesOff(channelNumber: any): any[];
241
+ allNotesOff(channelNumber: any): Promise<void>;
229
242
  omniOff(): void;
230
243
  omniOn(): void;
231
244
  monoOn(): void;
@@ -265,12 +278,13 @@ export class Midy {
265
278
  declare class Note {
266
279
  constructor(noteNumber: any, velocity: any, startTime: any, instrumentKey: any);
267
280
  bufferSource: any;
268
- gainNode: any;
269
281
  filterNode: any;
270
- modLFO: any;
271
- modLFOGain: any;
272
- vibLFO: any;
273
- vibLFOGain: any;
282
+ volumeNode: any;
283
+ volumeDepth: any;
284
+ modulationLFO: any;
285
+ modulationDepth: any;
286
+ vibratoLFO: any;
287
+ vibratoDepth: any;
274
288
  noteNumber: any;
275
289
  velocity: any;
276
290
  startTime: any;
package/esm/midy.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"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"}