@marmooo/midy 0.3.6 → 0.3.7

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.
@@ -29,6 +29,7 @@ export class MidyGMLite {
29
29
  isPaused: boolean;
30
30
  isStopping: boolean;
31
31
  isSeeking: boolean;
32
+ playPromise: any;
32
33
  timeline: any[];
33
34
  notePromises: any[];
34
35
  instruments: Set<any>;
@@ -39,16 +40,16 @@ export class MidyGMLite {
39
40
  scheduler: any;
40
41
  schedulerBuffer: any;
41
42
  voiceParamsHandlers: {
42
- modLfoToPitch: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
43
- vibLfoToPitch: (_channel: any, _note: any, _prevValue: any, _scheduleTime: any) => void;
44
- modLfoToFilterFc: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
45
- modLfoToVolume: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
46
- chorusEffectsSend: (_channel: any, _note: any, _prevValue: any, _scheduleTime: any) => void;
47
- reverbEffectsSend: (_channel: any, _note: any, _prevValue: any, _scheduleTime: any) => void;
48
- delayModLFO: (_channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
49
- freqModLFO: (_channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
50
- delayVibLFO: (_channel: any, _note: any, _prevValue: any, _scheduleTime: any) => void;
51
- freqVibLFO: (_channel: any, _note: any, _prevValue: any, _scheduleTime: any) => void;
43
+ modLfoToPitch: (channel: any, note: any, scheduleTime: any) => void;
44
+ vibLfoToPitch: (_channel: any, _note: any, _scheduleTime: any) => void;
45
+ modLfoToFilterFc: (channel: any, note: any, scheduleTime: any) => void;
46
+ modLfoToVolume: (channel: any, note: any, scheduleTime: any) => void;
47
+ chorusEffectsSend: (_channel: any, _note: any, _scheduleTime: any) => void;
48
+ reverbEffectsSend: (_channel: any, _note: any, _scheduleTime: any) => void;
49
+ delayModLFO: (_channel: any, note: any, scheduleTime: any) => void;
50
+ freqModLFO: (_channel: any, note: any, scheduleTime: any) => void;
51
+ delayVibLFO: (_channel: any, _note: any, _scheduleTime: any) => void;
52
+ freqVibLFO: (_channel: any, _note: any, _scheduleTime: any) => void;
52
53
  };
53
54
  controlChangeHandlers: any[];
54
55
  channels: any[];
@@ -69,7 +70,9 @@ export class MidyGMLite {
69
70
  createBufferSource(channel: any, voiceParams: any, audioBuffer: any): any;
70
71
  scheduleTimelineEvents(t: any, resumeTime: any, queueIndex: any): Promise<any>;
71
72
  getQueueIndex(second: any): number;
72
- playNotes(): Promise<any>;
73
+ resetAllStates(): void;
74
+ updateStates(queueIndex: any, nextQueueIndex: any): void;
75
+ playNotes(): Promise<void>;
73
76
  ticksToSecond(ticks: any, secondsPerBeat: any): number;
74
77
  secondToTicks(second: any, secondsPerBeat: any): number;
75
78
  extractMidiData(midi: any): {
@@ -80,8 +83,8 @@ export class MidyGMLite {
80
83
  stopChannelNotes(channelNumber: any, velocity: any, force: any, scheduleTime: any): Promise<any[]>;
81
84
  stopNotes(velocity: any, force: any, scheduleTime: any): Promise<any[]>;
82
85
  start(): Promise<void>;
83
- stop(): void;
84
- pause(): void;
86
+ stop(): Promise<void>;
87
+ pause(): Promise<void>;
85
88
  resume(): Promise<void>;
86
89
  seekTo(second: any): void;
87
90
  calcTotalTime(): number;
@@ -123,16 +126,16 @@ export class MidyGMLite {
123
126
  setDelayModLFO(note: any, scheduleTime: any): void;
124
127
  setFreqModLFO(note: any, scheduleTime: any): void;
125
128
  createVoiceParamsHandlers(): {
126
- modLfoToPitch: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
127
- vibLfoToPitch: (_channel: any, _note: any, _prevValue: any, _scheduleTime: any) => void;
128
- modLfoToFilterFc: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
129
- modLfoToVolume: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
130
- chorusEffectsSend: (_channel: any, _note: any, _prevValue: any, _scheduleTime: any) => void;
131
- reverbEffectsSend: (_channel: any, _note: any, _prevValue: any, _scheduleTime: any) => void;
132
- delayModLFO: (_channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
133
- freqModLFO: (_channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
134
- delayVibLFO: (_channel: any, _note: any, _prevValue: any, _scheduleTime: any) => void;
135
- freqVibLFO: (_channel: any, _note: any, _prevValue: any, _scheduleTime: any) => void;
129
+ modLfoToPitch: (channel: any, note: any, scheduleTime: any) => void;
130
+ vibLfoToPitch: (_channel: any, _note: any, _scheduleTime: any) => void;
131
+ modLfoToFilterFc: (channel: any, note: any, scheduleTime: any) => void;
132
+ modLfoToVolume: (channel: any, note: any, scheduleTime: any) => void;
133
+ chorusEffectsSend: (_channel: any, _note: any, _scheduleTime: any) => void;
134
+ reverbEffectsSend: (_channel: any, _note: any, _scheduleTime: any) => void;
135
+ delayModLFO: (_channel: any, note: any, scheduleTime: any) => void;
136
+ freqModLFO: (_channel: any, note: any, scheduleTime: any) => void;
137
+ delayVibLFO: (_channel: any, _note: any, _scheduleTime: any) => void;
138
+ freqVibLFO: (_channel: any, _note: any, _scheduleTime: any) => void;
136
139
  };
137
140
  getControllerState(channel: any, noteNumber: any, velocity: any): Float32Array<any>;
138
141
  applyVoiceParams(channel: any, controllerType: any, scheduleTime: any): void;
@@ -158,7 +161,7 @@ export class MidyGMLite {
158
161
  handlePitchBendRangeRPN(channelNumber: any, scheduleTime: any): void;
159
162
  setPitchBendRange(channelNumber: any, value: any, scheduleTime: any): void;
160
163
  allSoundOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
161
- resetAllStates(channelNumber: any): void;
164
+ resetChannelStates(channelNumber: any): void;
162
165
  resetAllControllers(channelNumber: any, _value: any, scheduleTime: any): void;
163
166
  allNotesOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
164
167
  handleUniversalNonRealTimeExclusiveMessage(data: any, scheduleTime: any): void;
@@ -1 +1 @@
1
- {"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AA0GA;IA2BE;;;;;;;;;;MAUE;IAEF,+BAcC;IApDD,aAAa;IACb,oBAAiB;IACjB,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,4BAAyB;IACzB,0BAAuB;IACvB,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,gBAAc;IACd,oBAAkB;IAClB,sBAAwB;IACxB,2BAAqC;IACrC,+BAEE;IAeA,kBAAgC;IAChC,kBAA8C;IAC9C,eAAwD;IACxD,qBAGE;IACF;;;;;;;;;;;MAA2D;IAC3D,6BAA+D;IAC/D,gBAAiD;IAMnD,4BAMC;IAED,mCASC;IAED,2DAYC;IAED,yCAmBC;IAED,oCASC;IAED,sBAoCC;IAED,8DAcC;IAED;;;;MAeC;IAED,yCAaC;IAED,kDAUC;IAED,0EAUC;IAED,+EAkDC;IAED,mCAOC;IAED,0BAiEC;IAED,uDAEC;IAED,wDAEC;IAED;;;MAgEC;IAED,kGAeC;IAED,mGAeC;IAED,wEAMC;IAED,uBAMC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,yDAQC;IAED,yEASC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,wCAIC;IAED,2DAIC;IAED,+DAIC;IAED,sDAeC;IAED,qDAoBC;IAED,6CAIC;IAED,sDAsBC;IAED,kEAoBC;IAED,6FAyBC;IAED,oGAuCC;IAED,0EAiBC;IAED,8EAiBC;IAED,kGAoCC;IAED,6FASC;IAED,gCASC;IAED,iEAoBC;IAED,qGAkBC;IAED,6CAUC;IAED,qDAUC;IAED,qFASC;IAED,sFAeC;IAED,oGA2BC;IAED,mFAGC;IAED,wFAGC;IAED,sEAUC;IAED,mEAWC;IAED,wDAKC;IAED,sDAOC;IAED,mDAMC;IAED,kDAKC;IAED;;;;;;;;;;;MA2BC;IAED,oFAMC;IAED,6EAgCC;IAED,qCAeC;IAED,+FAWC;IAED,wDASC;IAED,iFAKC;IAED,oEAKC;IAED;;;MAMC;IAED,8DAKC;IAED,4EAKC;IAED,sEAGC;IAED,2DAUC;IAED,yEAWC;IAED,kFAeC;IAED,uDAYC;IAED,gDAEC;IAED,gDAEC;IAED,sEAGC;IAED,qEAKC;IAED,2EAUC;IAED,gFAGC;IAED,yCAqBC;IAGD,8EAgCC;IAED,gFAGC;IAED,+EAgBC;IAED,qCAWC;IAED,4EAaC;IAED,4DAGC;IAED,sDASC;IAED,gDAYC;IAGD,6DAgBC;CACF;AAx/CD;IAWE,0FAMC;IAhBD,cAAW;IACX,gBAAe;IACf,kBAAa;IACb,gBAAW;IACX,iBAAY;IACZ,wBAAmB;IACnB,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAGd,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}
1
+ {"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AA0GA;IA4BE;;;;;;;;;;MAUE;IAEF,+BAcC;IArDD,aAAa;IACb,oBAAiB;IACjB,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,4BAAyB;IACzB,0BAAuB;IACvB,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,iBAAY;IACZ,gBAAc;IACd,oBAAkB;IAClB,sBAAwB;IACxB,2BAAqC;IACrC,+BAEE;IAeA,kBAAgC;IAChC,kBAA8C;IAC9C,eAAwD;IACxD,qBAGE;IACF;;;;;;;;;;;MAA2D;IAC3D,6BAA+D;IAC/D,gBAAiD;IAMnD,4BAMC;IAED,mCASC;IAED,2DAYC;IAED,yCAmBC;IAED,oCASC;IAED,sBAoCC;IAED,8DAcC;IAED;;;;MAeC;IAED,yCAaC;IAED,kDAUC;IAED,0EAUC;IAED,+EAkDC;IAED,mCAOC;IAED,uBAQC;IAED,yDA2BC;IAED,2BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MAgEC;IAED,kGAeC;IAED,mGAeC;IAED,wEAMC;IAED,uBAMC;IAED,sBAKC;IAED,uBAQC;IAED,wBAKC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,yDAQC;IAED,yEASC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,wCAIC;IAED,2DAIC;IAED,+DAIC;IAED,sDAeC;IAED,qDAoBC;IAED,6CAIC;IAED,sDAsBC;IAED,kEAoBC;IAED,6FAyBC;IAED,oGAuCC;IAED,0EAiBC;IAED,8EAiBC;IAED,kGAoCC;IAED,6FASC;IAED,gCASC;IAED,iEAoBC;IAED,qGAkBC;IAED,6CAUC;IAED,qDAUC;IAED,qFASC;IAED,sFAeC;IAED,oGA2BC;IAED,mFAGC;IAED,wFAGC;IAED,sEAUC;IAED,mEAWC;IAED,wDAKC;IAED,sDAOC;IAED,mDAMC;IAED,kDAKC;IAED;;;;;;;;;;;MAiCC;IAED,oFAMC;IAED,6EA2BC;IAED,qCAeC;IAED,+FAWC;IAED,wDASC;IAED,iFAKC;IAED,oEAKC;IAED;;;MAMC;IAED,8DAKC;IAED,4EAKC;IAED,sEAGC;IAED,2DAUC;IAED,yEAWC;IAED,kFAeC;IAED,uDAYC;IAED,gDAEC;IAED,gDAEC;IAED,sEAGC;IAED,qEAKC;IAED,2EAUC;IAED,gFAGC;IAED,6CAqBC;IAGD,8EAgCC;IAED,gFAGC;IAED,+EAgBC;IAED,qCAWC;IAED,4EAaC;IAED,4DAGC;IAED,sDASC;IAED,gDAYC;IAGD,6DAgBC;CACF;AArhDD;IAWE,0FAMC;IAhBD,cAAW;IACX,gBAAe;IACf,kBAAa;IACb,gBAAW;IACX,iBAAY;IACZ,wBAAmB;IACnB,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAGd,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}
@@ -260,6 +260,12 @@ class MidyGMLite {
260
260
  writable: true,
261
261
  value: false
262
262
  });
263
+ Object.defineProperty(this, "playPromise", {
264
+ enumerable: true,
265
+ configurable: true,
266
+ writable: true,
267
+ value: void 0
268
+ });
263
269
  Object.defineProperty(this, "timeline", {
264
270
  enumerable: true,
265
271
  configurable: true,
@@ -494,70 +500,80 @@ class MidyGMLite {
494
500
  }
495
501
  return 0;
496
502
  }
497
- playNotes() {
498
- return new Promise((resolve) => {
499
- this.isPlaying = true;
500
- this.isPaused = false;
501
- this.startTime = this.audioContext.currentTime;
502
- let queueIndex = this.getQueueIndex(this.resumeTime);
503
- let resumeTime = this.resumeTime - this.startTime;
503
+ resetAllStates() {
504
+ this.exclusiveClassNotes.fill(undefined);
505
+ this.drumExclusiveClassNotes.fill(undefined);
506
+ this.voiceCache.clear();
507
+ for (let i = 0; i < this.channels.length; i++) {
508
+ this.channels[i].scheduledNotes = [];
509
+ this.resetChannelStates(i);
510
+ }
511
+ }
512
+ updateStates(queueIndex, nextQueueIndex) {
513
+ if (nextQueueIndex < queueIndex)
514
+ queueIndex = 0;
515
+ for (let i = queueIndex; i < nextQueueIndex; i++) {
516
+ const event = this.timeline[i];
517
+ switch (event.type) {
518
+ case "controller":
519
+ this.setControlChange(event.channel, event.controllerType, event.value, 0);
520
+ break;
521
+ case "programChange":
522
+ this.setProgramChange(event.channel, event.programNumber, 0);
523
+ break;
524
+ case "pitchBend":
525
+ this.setPitchBend(event.channel, event.value + 8192, 0);
526
+ break;
527
+ case "sysEx":
528
+ this.handleSysEx(event.data, 0);
529
+ }
530
+ }
531
+ }
532
+ async playNotes() {
533
+ if (this.audioContext.state === "suspended") {
534
+ await this.audioContext.resume();
535
+ }
536
+ this.isPlaying = true;
537
+ this.isPaused = false;
538
+ this.startTime = this.audioContext.currentTime;
539
+ let queueIndex = this.getQueueIndex(this.resumeTime);
540
+ let resumeTime = this.resumeTime - this.startTime;
541
+ let finished = false;
542
+ this.notePromises = [];
543
+ while (queueIndex < this.timeline.length) {
544
+ const now = this.audioContext.currentTime;
545
+ const t = now + resumeTime;
546
+ queueIndex = await this.scheduleTimelineEvents(t, resumeTime, queueIndex);
547
+ if (this.isPausing) {
548
+ await this.stopNotes(0, true, now);
549
+ await this.audioContext.suspend();
550
+ this.notePromises = [];
551
+ break;
552
+ }
553
+ else if (this.isStopping) {
554
+ await this.stopNotes(0, true, now);
555
+ await this.audioContext.suspend();
556
+ finished = true;
557
+ break;
558
+ }
559
+ else if (this.isSeeking) {
560
+ await this.stopNotes(0, true, now);
561
+ this.startTime = this.audioContext.currentTime;
562
+ const nextQueueIndex = this.getQueueIndex(this.resumeTime);
563
+ this.updateStates(queueIndex, nextQueueIndex);
564
+ queueIndex = nextQueueIndex;
565
+ resumeTime = this.resumeTime - this.startTime;
566
+ this.isSeeking = false;
567
+ continue;
568
+ }
569
+ const waitTime = now + this.noteCheckInterval;
570
+ await this.scheduleTask(() => { }, waitTime);
571
+ }
572
+ if (finished) {
504
573
  this.notePromises = [];
505
- const schedulePlayback = async () => {
506
- if (queueIndex >= this.timeline.length) {
507
- await Promise.all(this.notePromises);
508
- this.notePromises = [];
509
- this.exclusiveClassNotes.fill(undefined);
510
- this.drumExclusiveClassNotes.fill(undefined);
511
- this.voiceCache.clear();
512
- for (let i = 0; i < this.channels.length; i++) {
513
- this.resetAllStates(i);
514
- }
515
- resolve();
516
- return;
517
- }
518
- const now = this.audioContext.currentTime;
519
- const t = now + resumeTime;
520
- queueIndex = await this.scheduleTimelineEvents(t, resumeTime, queueIndex);
521
- if (this.isPausing) {
522
- await this.stopNotes(0, true, now);
523
- this.notePromises = [];
524
- this.isPausing = false;
525
- this.isPaused = true;
526
- resolve();
527
- return;
528
- }
529
- else if (this.isStopping) {
530
- await this.stopNotes(0, true, now);
531
- this.notePromises = [];
532
- this.exclusiveClassNotes.fill(undefined);
533
- this.drumExclusiveClassNotes.fill(undefined);
534
- this.voiceCache.clear();
535
- for (let i = 0; i < this.channels.length; i++) {
536
- this.resetAllStates(i);
537
- }
538
- this.isStopping = false;
539
- this.isPaused = false;
540
- resolve();
541
- return;
542
- }
543
- else if (this.isSeeking) {
544
- this.stopNotes(0, true, now);
545
- this.exclusiveClassNotes.fill(undefined);
546
- this.drumExclusiveClassNotes.fill(undefined);
547
- this.startTime = this.audioContext.currentTime;
548
- queueIndex = this.getQueueIndex(this.resumeTime);
549
- resumeTime = this.resumeTime - this.startTime;
550
- this.isSeeking = false;
551
- await schedulePlayback();
552
- }
553
- else {
554
- const waitTime = now + this.noteCheckInterval;
555
- await this.scheduleTask(() => { }, waitTime);
556
- await schedulePlayback();
557
- }
558
- };
559
- schedulePlayback();
560
- });
574
+ this.resetAllStates();
575
+ }
576
+ this.isPlaying = false;
561
577
  }
562
578
  ticksToSecond(ticks, secondsPerBeat) {
563
579
  return ticks * secondsPerBeat / this.ticksPerBeat;
@@ -658,26 +674,32 @@ class MidyGMLite {
658
674
  this.resumeTime = 0;
659
675
  if (this.voiceCounter.size === 0)
660
676
  this.cacheVoiceIds();
661
- await this.playNotes();
662
- this.isPlaying = false;
677
+ this.playPromise = this.playNotes();
678
+ await this.playPromise;
663
679
  }
664
- stop() {
680
+ async stop() {
665
681
  if (!this.isPlaying)
666
682
  return;
667
683
  this.isStopping = true;
684
+ await this.playPromise;
685
+ this.isStopping = false;
668
686
  }
669
- pause() {
687
+ async pause() {
670
688
  if (!this.isPlaying || this.isPaused)
671
689
  return;
672
690
  const now = this.audioContext.currentTime;
673
691
  this.resumeTime += now - this.startTime - this.startDelay;
674
692
  this.isPausing = true;
693
+ await this.playPromise;
694
+ this.isPausing = false;
695
+ this.isPaused = true;
675
696
  }
676
697
  async resume() {
677
698
  if (!this.isPaused)
678
699
  return;
679
- await this.playNotes();
680
- this.isPlaying = false;
700
+ this.playPromise = this.playNotes();
701
+ await this.playPromise;
702
+ this.isPaused = false;
681
703
  }
682
704
  seekTo(second) {
683
705
  this.resumeTime = second;
@@ -1100,28 +1122,36 @@ class MidyGMLite {
1100
1122
  }
1101
1123
  createVoiceParamsHandlers() {
1102
1124
  return {
1103
- modLfoToPitch: (channel, note, _prevValue, scheduleTime) => {
1125
+ modLfoToPitch: (channel, note, scheduleTime) => {
1104
1126
  if (0 < channel.state.modulationDepth) {
1105
1127
  this.setModLfoToPitch(channel, note, scheduleTime);
1106
1128
  }
1107
1129
  },
1108
- vibLfoToPitch: (_channel, _note, _prevValue, _scheduleTime) => { },
1109
- modLfoToFilterFc: (channel, note, _prevValue, scheduleTime) => {
1130
+ vibLfoToPitch: (_channel, _note, _scheduleTime) => { },
1131
+ modLfoToFilterFc: (channel, note, scheduleTime) => {
1110
1132
  if (0 < channel.state.modulationDepth) {
1111
1133
  this.setModLfoToFilterFc(note, scheduleTime);
1112
1134
  }
1113
1135
  },
1114
- modLfoToVolume: (channel, note, _prevValue, scheduleTime) => {
1136
+ modLfoToVolume: (channel, note, scheduleTime) => {
1115
1137
  if (0 < channel.state.modulationDepth) {
1116
1138
  this.setModLfoToVolume(note, scheduleTime);
1117
1139
  }
1118
1140
  },
1119
- chorusEffectsSend: (_channel, _note, _prevValue, _scheduleTime) => { },
1120
- reverbEffectsSend: (_channel, _note, _prevValue, _scheduleTime) => { },
1121
- delayModLFO: (_channel, note, _prevValue, scheduleTime) => this.setDelayModLFO(note, scheduleTime),
1122
- freqModLFO: (_channel, note, _prevValue, scheduleTime) => this.setFreqModLFO(note, scheduleTime),
1123
- delayVibLFO: (_channel, _note, _prevValue, _scheduleTime) => { },
1124
- freqVibLFO: (_channel, _note, _prevValue, _scheduleTime) => { },
1141
+ chorusEffectsSend: (_channel, _note, _scheduleTime) => { },
1142
+ reverbEffectsSend: (_channel, _note, _scheduleTime) => { },
1143
+ delayModLFO: (_channel, note, scheduleTime) => {
1144
+ if (0 < channel.state.modulationDepth) {
1145
+ this.setDelayModLFO(note, scheduleTime);
1146
+ }
1147
+ },
1148
+ freqModLFO: (_channel, note, scheduleTime) => {
1149
+ if (0 < channel.state.modulationDepth) {
1150
+ this.setFreqModLFO(note, scheduleTime);
1151
+ }
1152
+ },
1153
+ delayVibLFO: (_channel, _note, _scheduleTime) => { },
1154
+ freqVibLFO: (_channel, _note, _scheduleTime) => { },
1125
1155
  };
1126
1156
  }
1127
1157
  getControllerState(channel, noteNumber, velocity) {
@@ -1144,7 +1174,7 @@ class MidyGMLite {
1144
1174
  continue;
1145
1175
  note.voiceParams[key] = value;
1146
1176
  if (key in this.voiceParamsHandlers) {
1147
- this.voiceParamsHandlers[key](channel, note, prevValue, scheduleTime);
1177
+ this.voiceParamsHandlers[key](channel, note, scheduleTime);
1148
1178
  }
1149
1179
  else {
1150
1180
  if (volumeEnvelopeKeySet.has(key))
@@ -1301,8 +1331,8 @@ class MidyGMLite {
1301
1331
  }
1302
1332
  handlePitchBendRangeRPN(channelNumber, scheduleTime) {
1303
1333
  const channel = this.channels[channelNumber];
1304
- this.limitData(channel, 0, 127, 0, 99);
1305
- const pitchBendRange = channel.dataMSB + channel.dataLSB / 100;
1334
+ this.limitData(channel, 0, 127, 0, 127);
1335
+ const pitchBendRange = (channel.dataMSB + channel.dataLSB / 128) * 100;
1306
1336
  this.setPitchBendRange(channelNumber, pitchBendRange, scheduleTime);
1307
1337
  }
1308
1338
  setPitchBendRange(channelNumber, value, scheduleTime) {
@@ -1310,7 +1340,7 @@ class MidyGMLite {
1310
1340
  scheduleTime ??= this.audioContext.currentTime;
1311
1341
  const state = channel.state;
1312
1342
  const prev = state.pitchWheelSensitivity;
1313
- const next = value / 128;
1343
+ const next = value / 12800;
1314
1344
  state.pitchWheelSensitivity = next;
1315
1345
  channel.detune += (state.pitchWheel * 2 - 1) * (next - prev) * 12800;
1316
1346
  this.updateChannelDetune(channel, scheduleTime);
@@ -1320,7 +1350,7 @@ class MidyGMLite {
1320
1350
  scheduleTime ??= this.audioContext.currentTime;
1321
1351
  return this.stopActiveNotes(channelNumber, 0, true, scheduleTime);
1322
1352
  }
1323
- resetAllStates(channelNumber) {
1353
+ resetChannelStates(channelNumber) {
1324
1354
  const scheduleTime = this.audioContext.currentTime;
1325
1355
  const channel = this.channels[channelNumber];
1326
1356
  const state = channel.state;
package/script/midy.d.ts CHANGED
@@ -48,6 +48,7 @@ export class Midy {
48
48
  isPaused: boolean;
49
49
  isStopping: boolean;
50
50
  isSeeking: boolean;
51
+ playPromise: any;
51
52
  timeline: any[];
52
53
  notePromises: any[];
53
54
  instruments: Set<any>;
@@ -58,16 +59,16 @@ export class Midy {
58
59
  scheduler: any;
59
60
  schedulerBuffer: any;
60
61
  voiceParamsHandlers: {
61
- modLfoToPitch: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
62
- vibLfoToPitch: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
63
- modLfoToFilterFc: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
64
- modLfoToVolume: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
65
- chorusEffectsSend: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
66
- reverbEffectsSend: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
67
- delayModLFO: (_channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
68
- freqModLFO: (_channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
69
- delayVibLFO: (channel: any, note: any, prevValue: any, scheduleTime: any) => void;
70
- freqVibLFO: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
62
+ modLfoToPitch: (channel: any, note: any, scheduleTime: any) => void;
63
+ vibLfoToPitch: (channel: any, note: any, scheduleTime: any) => void;
64
+ modLfoToFilterFc: (channel: any, note: any, scheduleTime: any) => void;
65
+ modLfoToVolume: (channel: any, note: any, scheduleTime: any) => void;
66
+ chorusEffectsSend: (channel: any, note: any, scheduleTime: any) => void;
67
+ reverbEffectsSend: (channel: any, note: any, scheduleTime: any) => void;
68
+ delayModLFO: (_channel: any, note: any, _scheduleTime: any) => void;
69
+ freqModLFO: (_channel: any, note: any, scheduleTime: any) => void;
70
+ delayVibLFO: (channel: any, note: any, _scheduleTime: any) => void;
71
+ freqVibLFO: (channel: any, note: any, scheduleTime: any) => void;
71
72
  };
72
73
  controlChangeHandlers: any[];
73
74
  channels: any[];
@@ -103,7 +104,9 @@ export class Midy {
103
104
  createBufferSource(channel: any, noteNumber: any, voiceParams: any, audioBuffer: any): any;
104
105
  scheduleTimelineEvents(t: any, resumeTime: any, queueIndex: any): Promise<any>;
105
106
  getQueueIndex(second: any): number;
106
- playNotes(): Promise<any>;
107
+ resetAllStates(): void;
108
+ updateStates(queueIndex: any, nextQueueIndex: any): void;
109
+ playNotes(): Promise<void>;
107
110
  ticksToSecond(ticks: any, secondsPerBeat: any): number;
108
111
  secondToTicks(second: any, secondsPerBeat: any): number;
109
112
  extractMidiData(midi: any): {
@@ -114,8 +117,8 @@ export class Midy {
114
117
  stopChannelNotes(channelNumber: any, velocity: any, force: any, scheduleTime: any): Promise<any[]>;
115
118
  stopNotes(velocity: any, force: any, scheduleTime: any): Promise<any[]>;
116
119
  start(): Promise<void>;
117
- stop(): void;
118
- pause(): void;
120
+ stop(): Promise<void>;
121
+ pause(): Promise<void>;
119
122
  resume(): Promise<void>;
120
123
  seekTo(second: any): void;
121
124
  calcTotalTime(): number;
@@ -194,20 +197,21 @@ export class Midy {
194
197
  setModLfoToVolume(channel: any, note: any, scheduleTime: any): void;
195
198
  setReverbSend(channel: any, note: any, scheduleTime: any): void;
196
199
  setChorusSend(channel: any, note: any, scheduleTime: any): void;
197
- setDelayModLFO(note: any, scheduleTime: any): void;
200
+ setDelayModLFO(note: any): void;
198
201
  setFreqModLFO(note: any, scheduleTime: any): void;
199
202
  setFreqVibLFO(channel: any, note: any, scheduleTime: any): void;
203
+ setDelayVibLFO(channel: any, note: any): void;
200
204
  createVoiceParamsHandlers(): {
201
- modLfoToPitch: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
202
- vibLfoToPitch: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
203
- modLfoToFilterFc: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
204
- modLfoToVolume: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
205
- chorusEffectsSend: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
206
- reverbEffectsSend: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
207
- delayModLFO: (_channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
208
- freqModLFO: (_channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
209
- delayVibLFO: (channel: any, note: any, prevValue: any, scheduleTime: any) => void;
210
- freqVibLFO: (channel: any, note: any, _prevValue: any, scheduleTime: any) => void;
205
+ modLfoToPitch: (channel: any, note: any, scheduleTime: any) => void;
206
+ vibLfoToPitch: (channel: any, note: any, scheduleTime: any) => void;
207
+ modLfoToFilterFc: (channel: any, note: any, scheduleTime: any) => void;
208
+ modLfoToVolume: (channel: any, note: any, scheduleTime: any) => void;
209
+ chorusEffectsSend: (channel: any, note: any, scheduleTime: any) => void;
210
+ reverbEffectsSend: (channel: any, note: any, scheduleTime: any) => void;
211
+ delayModLFO: (_channel: any, note: any, _scheduleTime: any) => void;
212
+ freqModLFO: (_channel: any, note: any, scheduleTime: any) => void;
213
+ delayVibLFO: (channel: any, note: any, _scheduleTime: any) => void;
214
+ freqVibLFO: (channel: any, note: any, scheduleTime: any) => void;
211
215
  };
212
216
  getControllerState(channel: any, noteNumber: any, velocity: any, polyphonicKeyPressure: any): Float32Array<any>;
213
217
  applyVoiceParams(channel: any, controllerType: any, scheduleTime: any): void;
@@ -234,7 +238,8 @@ export class Midy {
234
238
  setSostenutoPedal(channelNumber: any, value: any, scheduleTime: any): void;
235
239
  getSoftPedalFactor(channel: any, note: any): number;
236
240
  setSoftPedal(channelNumber: any, softPedal: any, scheduleTime: any): void;
237
- setFilterResonance(channelNumber: any, filterResonance: any, scheduleTime: any): void;
241
+ setFilterResonance(channelNumber: any, ccValue: any, scheduleTime: any): void;
242
+ getRelativeKeyBasedValue(channel: any, note: any, controllerType: any): any;
238
243
  setReleaseTime(channelNumber: any, releaseTime: any, scheduleTime: any): void;
239
244
  setAttackTime(channelNumber: any, attackTime: any, scheduleTime: any): void;
240
245
  setBrightness(channelNumber: any, brightness: any, scheduleTime: any): void;
@@ -259,9 +264,9 @@ export class Midy {
259
264
  handleCoarseTuningRPN(channelNumber: any, scheduleTime: any): void;
260
265
  setCoarseTuning(channelNumber: any, value: any, scheduleTime: any): void;
261
266
  handleModulationDepthRangeRPN(channelNumber: any, scheduleTime: any): void;
262
- setModulationDepthRange(channelNumber: any, modulationDepthRange: any, scheduleTime: any): void;
267
+ setModulationDepthRange(channelNumber: any, value: any, scheduleTime: any): void;
263
268
  allSoundOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
264
- resetAllStates(channelNumber: any): void;
269
+ resetChannelStates(channelNumber: any): void;
265
270
  resetAllControllers(channelNumber: any, _value: any, scheduleTime: any): void;
266
271
  allNotesOff(channelNumber: any, _value: any, scheduleTime: any): Promise<any[]>;
267
272
  omniOff(channelNumber: any, value: any, scheduleTime: any): void;
@@ -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":"AA4JA;IA0CE;;;;;;;;;;;;;;;MAeE;IAEF,+BAkBC;IA5ED,aAAa;IACb,yBAAqB;IACrB,2BAAuB;IACvB;;;;MAIE;IACF;;;;;;MAME;IACF,oBAAiB;IACjB,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,4BAAyB;IACzB,0BAAuB;IACvB,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,iBAAY;IACZ,gBAAc;IACd,oBAAkB;IAClB,sBAAwB;IACxB,2BAAqC;IACrC,+BAEE;IAoBA,kBAAgC;IAChC,kBAA8C;IAC9C,eAAwD;IACxD,qBAGE;IACF;;;;;;;;;;;MAA2D;IAC3D,6BAA+D;IAC/D,gBAAiD;IACjD;;;kBAAyD;IACzD;;;;;;;;MAAyD;IAQ3D,4BAMC;IAED,mCASC;IAED,2DAYC;IAED,yCAmBC;IAED,oCASC;IAED,sBAoCC;IAED,8DAcC;IAED;;;;MAeC;IAED,sCAMC;IAED,yCAqBC;IAED,kDAUC;IAED,mDAIC;IAED,2FAWC;IAED,+EA6DC;IAED,mCAOC;IAED,uBAQC;IAED,yDA2BC;IAED,2BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MAoGC;IAED,kGAeC;IAED,mGAeC;IAED,wEAMC;IAED,uBAMC;IAED,sBAKC;IAED,uBAQC;IAED,wBAKC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,yDAQC;IAED,yEASC;IAED,kFAuBC;IAED;;;;MASC;IAED,gFAUC;IAED,mFAYC;IAED,sGAcC;IAID;;;MA8BC;IAED;;;kBA6BC;IAED;;;;;;;;MA0CC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,qCAkBC;IAED,6CAEC;IAED,2DAIC;IAED,+DAiBC;IAED,mDAIC;IAED,2CAoDC;IAED,8EAYC;IAED,oEAkBC;IAED,+DAKC;IAED,qDAoBC;IAED,6CAIC;IAED,8EAqBC;IAED,oEAyBC;IAED,kEAoBC;IAED,+DAcC;IAED,6FAyBC;IAED,oGAmEC;IAED,4BAYC;IAED,0EAiBC;IAED,8EAoBC;IAED,kGAiDC;IAED,6FASC;IAED,gCAmBC;IAED,iEAqBC;IAED,qGAuBC;IAED,6CAUC;IAED,qDAUC;IAED,qFASC;IAED,sFAeC;IAED,wFAkBC;IAED,oGAoCC;IAED,sGAeC;IAED,mFAeC;IAED,4EAgBC;IAED,wFAGC;IAED,sEAWC;IAED,mEAYC;IAED,mEAaC;IAED,sEAMC;IAED,oEAQC;IAED,gEAyBC;IAED,gEAyBC;IAED,gCAKC;IAED,kDAKC;IAED,gEAMC;IAED,8CAOC;IAED;;;;;;;;;;;MAiDC;IAED,gHAQC;IAED,6EAgCC;IAED,qCAqCC;IAED,+FAYC;IAED,+CAEC;IAED,wDASC;IAED,iFAMC;IAED,wDAkBC;IAED,oFAMC;IAED,oEAWC;IAED;;;MAMC;IAED,8DAWC;IAED,4EAKC;IAED,+CAEC;IAED,sEAGC;IAED,2DAUC;IAED,4EAoBC;IAED,yEAYC;IAED,uEAMC;IAED,2EAcC;IAED,oDAEC;IAED,0EAeC;IAED,8EAWC;IAED,4EAUC;IAED,8EAKC;IAED,4EAUC;IAED,4EAaC;IAED,0EAQC;IAED,8EASC;IAED,gFAeC;IAED,gFAUC;IAED,sFAQC;IAED,sFAQC;IAED,kFAeC;IAED,2DAMC;IAED,mEAyBC;IAGD,2DAGC;IAGD,2DAGC;IAED,gDAEC;IAED,gDAEC;IAED,sEAGC;IAED,qEAKC;IAED,2EAWC;IAED,iEAMC;IAED,uEASC;IAED,mEAKC;IAED,yEASC;IAED,2EAKC;IAED,iFAMC;IAED,gFAGC;IAED,6CAwBC;IAGD,8EAqCC;IAED,gFAGC;IAED,iEAEC;IAED,gEAEC;IAED,gEAIC;IAED,gEAIC;IAED,+EAuCC;IAED,qCAcC;IAED,qCAcC;IAED,4EAqEC;IAED,4DAGC;IAED,sDASC;IAED,gEAIC;IAED,yDAWC;IAED,kEAGC;IAED,2DAWC;IAED,sEAeC;IAED,4CAOC;IAED,+BAIC;IAED,qDAiBC;IAED,gCAGC;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,iDAMC;IAED,wDAUC;IAED,qDAUC;IAED,kDAUC;IAED,mDAUC;IAED,sDAUC;IAED,yEAgBC;IAED,wEAaC;IAED,2CAIC;IAED,oFAOC;IAED,6DAcC;IAED,yEAIC;IAED,yEAwGC;IAED,gDAYC;IAGD,6DAgBC;CACF;AAzvGD;IAiBE,0FAMC;IAtBD,cAAW;IACX,gBAAe;IACf,kBAAa;IACb,gBAAW;IACX,iBAAY;IACZ,wBAAmB;IACnB,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAChB,gBAAW;IACX,kBAAa;IACb,gBAAW;IACX,gBAAW;IACX,6BAA0B;IAC1B,iBAAa;IAGX,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}