@marmooo/midy 0.0.1 → 0.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/esm/midy-GM1.d.ts CHANGED
@@ -24,7 +24,6 @@ export class MidyGM1 {
24
24
  };
25
25
  constructor(audioContext: any);
26
26
  ticksPerBeat: number;
27
- secondsPerBeat: number;
28
27
  totalTime: number;
29
28
  noteCheckInterval: number;
30
29
  lookAhead: number;
@@ -50,7 +49,6 @@ export class MidyGM1 {
50
49
  pannerNode: any;
51
50
  modulationEffect: {
52
51
  lfo: any;
53
- lfoGain: any;
54
52
  };
55
53
  expression: number;
56
54
  modulation: number;
@@ -81,7 +79,6 @@ export class MidyGM1 {
81
79
  pannerNode: any;
82
80
  modulationEffect: {
83
81
  lfo: any;
84
- lfoGain: any;
85
82
  };
86
83
  };
87
84
  createChannels(audioContext: any): {
@@ -91,7 +88,6 @@ export class MidyGM1 {
91
88
  pannerNode: any;
92
89
  modulationEffect: {
93
90
  lfo: any;
94
- lfoGain: any;
95
91
  };
96
92
  expression: number;
97
93
  modulation: number;
@@ -137,12 +133,6 @@ export class MidyGM1 {
137
133
  getActiveChannelNotes(scheduledNotes: any): any;
138
134
  createModulationEffect(audioContext: any): {
139
135
  lfo: any;
140
- lfoGain: any;
141
- };
142
- createReverbEffect(audioContext: any, options?: {}): {
143
- convolverNode: any;
144
- dryGain: any;
145
- wetGain: any;
146
136
  };
147
137
  connectNoteEffects(channel: any, gainNode: any): void;
148
138
  cbToRatio(cb: any): number;
@@ -151,12 +141,13 @@ export class MidyGM1 {
151
141
  bufferSource: any;
152
142
  gainNode: any;
153
143
  filterNode: any;
144
+ lfoGain: any;
154
145
  }>;
155
146
  scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
156
147
  noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
157
148
  scheduleNoteRelease(channelNumber: any, noteNumber: any, velocity: any, stopTime: any, stopPedal?: boolean): Promise<any> | undefined;
158
149
  releaseNote(channelNumber: any, noteNumber: any, velocity: any): Promise<any> | undefined;
159
- releaseSustainPedal(channelNumber: any): void;
150
+ releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
160
151
  handleMIDIMessage(statusByte: any, data1: any, data2: any): void | any[] | Promise<any>;
161
152
  handlePolyphonicKeyPressure(channelNumber: any, noteNumber: any, pressure: any): void;
162
153
  handleProgramChange(channelNumber: any, program: any): void;
@@ -1 +1 @@
1
- {"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAMA;IAoBE;;;;;;;;;;;;;;MAcE;IAEF;;;;;;;MAOE;IAEF,+BAMC;IAlDD,qBAAmB;IACnB,uBAAqB;IACrB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,gBAAc;IACd,mBAAiB;IACjB,oBAAkB;IA4BhB,kBAAgC;IAChC,gBAA4C;IAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;;;;;MAgBC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAWC;IAED,0DAyBC;IAED,8DAUC;IAED,qDAOC;IAED,2EA6CC;IAED,mCAQC;IAED,0BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MA0DC;IAED,4BAsBC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBA2BC;IAED,sBAGC;IAED,4CASC;IAED,gDAKC;IAED;;;MAUC;IAED;;;;MAoCC;IAED,sDAEC;IAED,2BAEC;IAED,4BAEC;IAED;;;;OAoEC;IAED,kGAsCC;IAED,0EAGC;IAED,sIAuCC;IAED,0FAGC;IAED,8CAmBC;IAED,wFAqBC;IAED,sFAeC;IAED,4DAGC;IAED,+DAEC;IAED,8DAGC;IAED,mFA+BC;IAED,yDAQC;IAED,iDAIC;IAED,2CAMC;IAED,yDAIC;IAED,sCAKC;IAED,sDAKC;IAED,gDAEC;IAED,gDAEC;IAED,+DAoBC;IAED,uCAoBC;IAED,8CAEC;IAED,uCAoBC;IAED,4DAgBC;IAED,oBAQC;IAED,yDAaC;IAED,yCAGC;IAED,sCAIC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF"}
1
+ {"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAMA;IAmBE;;;;;;;;;;;;;;MAcE;IAEF;;;;;;;MAOE;IAEF,+BAMC;IAjDD,qBAAmB;IACnB,kBAAc;IACd,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,gBAAc;IACd,mBAAiB;IACjB,oBAAkB;IA4BhB,kBAAgC;IAChC,gBAA4C;IAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;QAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;;;;MAgBC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;QAWC;IAED,0DAyBC;IAED,8DAUC;IAED,qDAOC;IAED,2EA4CC;IAED,mCAOC;IAED,0BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MAyEC;IAED,4BAsBC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,4CASC;IAED,gDAKC;IAED;;MAOC;IAED,sDAEC;IAED,2BAEC;IAED,4BAEC;IAED;;;;;OA6EC;IAED,kGAuCC;IAED,0EAGC;IAED,sIA4CC;IAED,0FAGC;IAED,kEAeC;IAED,wFAqBC;IAED,sFAeC;IAED,4DAGC;IAED,+DAEC;IAED,8DAGC;IAED,mFA+BC;IAED,yDAIC;IAED,iDAIC;IAED,2CAMC;IAED,yDAIC;IAED,sCAKC;IAED,sDAMC;IAED,gDAEC;IAED,gDAEC;IAED,+DAoBC;IAED,uCAoBC;IAED,8CAEC;IAED,uCAoBC;IAED,4DAgBC;IAED,oBAQC;IAED,yDAaC;IAED,yCAGC;IAED,sCAIC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF"}
package/esm/midy-GM1.js CHANGED
@@ -8,12 +8,6 @@ export class MidyGM1 {
8
8
  writable: true,
9
9
  value: 120
10
10
  });
11
- Object.defineProperty(this, "secondsPerBeat", {
12
- enumerable: true,
13
- configurable: true,
14
- writable: true,
15
- value: 0.5
16
- });
17
11
  Object.defineProperty(this, "totalTime", {
18
12
  enumerable: true,
19
13
  configurable: true,
@@ -144,10 +138,10 @@ export class MidyGM1 {
144
138
  const response = await fetch(midiUrl);
145
139
  const arrayBuffer = await response.arrayBuffer();
146
140
  const midi = parseMidi(new Uint8Array(arrayBuffer));
141
+ this.ticksPerBeat = midi.header.ticksPerBeat;
147
142
  const midiData = this.extractMidiData(midi);
148
143
  this.instruments = midiData.instruments;
149
144
  this.timeline = midiData.timeline;
150
- this.ticksPerBeat = midi.header.ticksPerBeat;
151
145
  this.totalTime = this.calcTotalTime();
152
146
  }
153
147
  setChannelAudioNodes(audioContext) {
@@ -226,18 +220,20 @@ export class MidyGM1 {
226
220
  async scheduleTimelineEvents(t, offset, queueIndex) {
227
221
  while (queueIndex < this.timeline.length) {
228
222
  const event = this.timeline[queueIndex];
229
- const time = this.ticksToSecond(event.ticks, this.secondsPerBeat);
230
- if (time > t + this.lookAhead)
223
+ if (event.startTime > t + this.lookAhead)
231
224
  break;
232
225
  switch (event.type) {
233
226
  case "controller":
234
227
  this.handleControlChange(event.channel, event.controllerType, event.value);
235
228
  break;
236
229
  case "noteOn":
237
- await this.scheduleNoteOn(event.channel, event.noteNumber, event.velocity, time + this.startDelay - offset);
238
- break;
230
+ if (event.velocity !== 0) {
231
+ await this.scheduleNoteOn(event.channel, event.noteNumber, event.velocity, event.startTime + this.startDelay - offset);
232
+ break;
233
+ }
234
+ /* falls through */
239
235
  case "noteOff": {
240
- const notePromise = this.scheduleNoteRelease(event.channel, event.noteNumber, event.velocity, time + this.startDelay - offset);
236
+ const notePromise = this.scheduleNoteRelease(event.channel, event.noteNumber, event.velocity, event.startTime + this.startDelay - offset);
241
237
  if (notePromise) {
242
238
  this.notePromises.push(notePromise);
243
239
  }
@@ -246,9 +242,6 @@ export class MidyGM1 {
246
242
  case "programChange":
247
243
  this.handleProgramChange(event.channel, event.programNumber);
248
244
  break;
249
- case "setTempo":
250
- this.secondsPerBeat = event.microsecondsPerBeat / 1000000;
251
- break;
252
245
  case "sysEx":
253
246
  this.handleSysEx(event.data);
254
247
  }
@@ -257,9 +250,8 @@ export class MidyGM1 {
257
250
  return queueIndex;
258
251
  }
259
252
  getQueueIndex(second) {
260
- const ticks = this.secondToTicks(second, this.secondsPerBeat);
261
253
  for (let i = 0; i < this.timeline.length; i++) {
262
- if (ticks <= this.timeline[i].ticks) {
254
+ if (second <= this.timeline[i].startTime) {
263
255
  return i;
264
256
  }
265
257
  }
@@ -367,18 +359,28 @@ export class MidyGM1 {
367
359
  timeline.push(event);
368
360
  });
369
361
  });
362
+ const priority = {
363
+ setTempo: 0,
364
+ controller: 1,
365
+ };
370
366
  timeline.sort((a, b) => {
371
- if (a.ticks !== b.ticks) {
367
+ if (a.ticks !== b.ticks)
372
368
  return a.ticks - b.ticks;
373
- }
374
- if (a.type !== "controller" && b.type === "controller") {
375
- return -1;
376
- }
377
- if (a.type === "controller" && b.type !== "controller") {
378
- return 1;
379
- }
380
- return 0;
369
+ return (priority[a.type] || 2) - (priority[b.type] || 2);
381
370
  });
371
+ let prevTempoTime = 0;
372
+ let prevTempoTicks = 0;
373
+ let secondsPerBeat = 0.5;
374
+ for (let i = 0; i < timeline.length; i++) {
375
+ const event = timeline[i];
376
+ const timeFromPrevTempo = this.ticksToSecond(event.ticks - prevTempoTicks, secondsPerBeat);
377
+ event.startTime = prevTempoTime + timeFromPrevTempo;
378
+ if (event.type === "setTempo") {
379
+ prevTempoTime += this.ticksToSecond(event.ticks - prevTempoTicks, secondsPerBeat);
380
+ secondsPerBeat = event.microsecondsPerBeat / 1000000;
381
+ prevTempoTicks = event.ticks;
382
+ }
383
+ }
382
384
  return { instruments, timeline };
383
385
  }
384
386
  stopNotes() {
@@ -430,32 +432,12 @@ export class MidyGM1 {
430
432
  }
431
433
  }
432
434
  calcTotalTime() {
433
- const endOfTracks = [];
434
- let prevTicks = 0;
435
435
  let totalTime = 0;
436
- let secondsPerBeat = 0.5;
437
436
  for (let i = 0; i < this.timeline.length; i++) {
438
437
  const event = this.timeline[i];
439
- switch (event.type) {
440
- case "setTempo": {
441
- const durationTicks = event.ticks - prevTicks;
442
- totalTime += this.ticksToSecond(durationTicks, secondsPerBeat);
443
- secondsPerBeat = event.microsecondsPerBeat / 1000000;
444
- prevTicks = event.ticks;
445
- break;
446
- }
447
- case "endOfTrack":
448
- endOfTracks.push(event);
449
- }
438
+ if (totalTime < event.startTime)
439
+ totalTime = event.startTime;
450
440
  }
451
- let maxTicks = 0;
452
- for (let i = 0; i < endOfTracks.length; i++) {
453
- const event = endOfTracks[i];
454
- if (maxTicks < event.ticks)
455
- maxTicks = event.ticks;
456
- }
457
- const durationTicks = maxTicks - prevTicks;
458
- totalTime += this.ticksToSecond(durationTicks, secondsPerBeat);
459
441
  return totalTime;
460
442
  }
461
443
  currentTime() {
@@ -464,7 +446,7 @@ export class MidyGM1 {
464
446
  }
465
447
  getActiveNotes(channel) {
466
448
  const activeNotes = new Map();
467
- channel.scheduledNotes.forEeach((scheduledNotes) => {
449
+ channel.scheduledNotes.forEach((scheduledNotes) => {
468
450
  const activeNote = this.getActiveChannelNotes(scheduledNotes);
469
451
  if (activeNote) {
470
452
  activeNotes.set(activeNote.noteNumber, activeNote);
@@ -483,43 +465,8 @@ export class MidyGM1 {
483
465
  const lfo = new OscillatorNode(audioContext, {
484
466
  frequency: 5,
485
467
  });
486
- const lfoGain = new GainNode(audioContext);
487
- lfo.connect(lfoGain);
488
468
  return {
489
469
  lfo,
490
- lfoGain,
491
- };
492
- }
493
- createReverbEffect(audioContext, options = {}) {
494
- const { decay = 0.8, preDecay = 0, } = options;
495
- const sampleRate = audioContext.sampleRate;
496
- const length = sampleRate * decay;
497
- const impulse = new AudioBuffer({
498
- numberOfChannels: 2,
499
- length,
500
- sampleRate,
501
- });
502
- const preDecayLength = Math.min(sampleRate * preDecay, length);
503
- for (let channel = 0; channel < impulse.numberOfChannels; channel++) {
504
- const channelData = impulse.getChannelData(channel);
505
- for (let i = 0; i < preDecayLength; i++) {
506
- channelData[i] = Math.random() * 2 - 1;
507
- }
508
- for (let i = preDecayLength; i < length; i++) {
509
- const attenuation = Math.exp(-(i - preDecayLength) / sampleRate / decay);
510
- channelData[i] = (Math.random() * 2 - 1) * attenuation;
511
- }
512
- }
513
- const convolverNode = new ConvolverNode(audioContext, {
514
- buffer: impulse,
515
- });
516
- const dryGain = new GainNode(audioContext);
517
- const wetGain = new GainNode(audioContext);
518
- convolverNode.connect(wetGain);
519
- return {
520
- convolverNode,
521
- dryGain,
522
- wetGain,
523
470
  };
524
471
  }
525
472
  connectNoteEffects(channel, gainNode) {
@@ -556,35 +503,46 @@ export class MidyGM1 {
556
503
  .exponentialRampToValueAtTime(attackVolume, volAttack)
557
504
  .setValueAtTime(attackVolume, volHold)
558
505
  .linearRampToValueAtTime(sustainVolume, volDecay);
559
- if (channel.modulation > 0) {
560
- const lfoGain = channel.modulationEffect.lfoGain;
561
- lfoGain.connect(bufferSource.detune);
562
- lfoGain.gain.cancelScheduledValues(startTime + channel.vibratoDelay);
563
- lfoGain.gain.setValueAtTime(channel.modulation, startTime + channel.vibratoDelay);
564
- }
565
506
  // filter envelope
507
+ const maxFreq = this.audioContext.sampleRate / 2;
566
508
  const baseFreq = this.centToHz(noteInfo.initialFilterFc);
567
509
  const peekFreq = this.centToHz(noteInfo.initialFilterFc + noteInfo.modEnvToFilterFc);
568
510
  const sustainFreq = baseFreq +
569
511
  (peekFreq - baseFreq) * (1 - noteInfo.modSustain);
512
+ const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
513
+ const adjustedPeekFreq = Math.min(maxFreq, peekFreq);
514
+ const adjustedSustainFreq = Math.min(maxFreq, sustainFreq);
570
515
  const filterNode = new BiquadFilterNode(this.audioContext, {
571
516
  type: "lowpass",
572
- Q: this.cbToRatio(noteInfo.initialFilterQ),
573
- frequency: baseFreq,
517
+ Q: noteInfo.initialFilterQ / 10, // dB
518
+ frequency: adjustedBaseFreq,
574
519
  });
575
520
  const modDelay = startTime + noteInfo.modDelay;
576
521
  const modAttack = modDelay + noteInfo.modAttack;
577
522
  const modHold = modAttack + noteInfo.modHold;
578
523
  const modDecay = modHold + noteInfo.modDecay;
579
524
  filterNode.frequency
580
- .setValueAtTime(baseFreq, modDelay)
581
- .exponentialRampToValueAtTime(peekFreq, modAttack)
582
- .setValueAtTime(peekFreq, modHold)
583
- .linearRampToValueAtTime(sustainFreq, modDecay);
525
+ .setValueAtTime(adjustedBaseFreq, modDelay)
526
+ .exponentialRampToValueAtTime(adjustedPeekFreq, modAttack)
527
+ .setValueAtTime(adjustedPeekFreq, modHold)
528
+ .linearRampToValueAtTime(adjustedSustainFreq, modDecay);
529
+ let lfoGain;
530
+ if (channel.modulation > 0) {
531
+ const vibratoDelay = startTime + channel.vibratoDelay;
532
+ const vibratoAttack = vibratoDelay + 0.1;
533
+ lfoGain = new GainNode(this.audioContext, {
534
+ gain: 0,
535
+ });
536
+ lfoGain.gain
537
+ .setValueAtTime(1e-6, vibratoDelay) // exponentialRampToValueAtTime() requires a non-zero value
538
+ .exponentialRampToValueAtTime(channel.modulation, vibratoAttack);
539
+ channel.modulationEffect.lfo.connect(lfoGain);
540
+ lfoGain.connect(bufferSource.detune);
541
+ }
584
542
  bufferSource.connect(filterNode);
585
543
  filterNode.connect(gainNode);
586
544
  bufferSource.start(startTime, noteInfo.start / noteInfo.sampleRate);
587
- return { bufferSource, gainNode, filterNode };
545
+ return { bufferSource, gainNode, filterNode, lfoGain };
588
546
  }
589
547
  async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
590
548
  const channel = this.channels[channelNumber];
@@ -597,16 +555,17 @@ export class MidyGM1 {
597
555
  const noteInfo = soundFont.getInstrumentKey(bankNumber, channel.program, noteNumber);
598
556
  if (!noteInfo)
599
557
  return;
600
- const { bufferSource, gainNode, filterNode } = await this
558
+ const { bufferSource, gainNode, filterNode, lfoGain } = await this
601
559
  .createNoteAudioChain(channel, noteInfo, noteNumber, velocity, startTime, isSF3);
602
560
  this.connectNoteEffects(channel, gainNode);
603
561
  const scheduledNotes = channel.scheduledNotes;
604
562
  const scheduledNote = {
605
- gainNode,
606
- filterNode,
607
563
  bufferSource,
608
- noteNumber,
564
+ filterNode,
565
+ gainNode,
566
+ lfoGain,
609
567
  noteInfo,
568
+ noteNumber,
610
569
  startTime,
611
570
  };
612
571
  if (scheduledNotes.has(noteNumber)) {
@@ -633,15 +592,18 @@ export class MidyGM1 {
633
592
  continue;
634
593
  if (targetNote.ending)
635
594
  continue;
636
- const { bufferSource, filterNode, gainNode, noteInfo } = targetNote;
595
+ const { bufferSource, filterNode, gainNode, lfoGain, noteInfo } = targetNote;
637
596
  const velocityRate = (velocity + 127) / 127;
638
597
  const volEndTime = stopTime + noteInfo.volRelease * velocityRate;
639
598
  gainNode.gain.cancelScheduledValues(stopTime);
640
599
  gainNode.gain.linearRampToValueAtTime(0, volEndTime);
600
+ const maxFreq = this.audioContext.sampleRate / 2;
641
601
  const baseFreq = this.centToHz(noteInfo.initialFilterFc);
602
+ const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
642
603
  const modEndTime = stopTime + noteInfo.modRelease * velocityRate;
643
- filterNode.frequency.cancelScheduledValues(stopTime);
644
- filterNode.frequency.linearRampToValueAtTime(baseFreq, modEndTime);
604
+ filterNode.frequency
605
+ .cancelScheduledValues(stopTime)
606
+ .linearRampToValueAtTime(adjustedBaseFreq, modEndTime);
645
607
  targetNote.ending = true;
646
608
  this.scheduleTask(() => {
647
609
  bufferSource.loop = false;
@@ -652,6 +614,8 @@ export class MidyGM1 {
652
614
  bufferSource.disconnect(0);
653
615
  filterNode.disconnect(0);
654
616
  gainNode.disconnect(0);
617
+ if (lfoGain)
618
+ lfoGain.disconnect(0);
655
619
  resolve();
656
620
  };
657
621
  bufferSource.stop(volEndTime);
@@ -662,25 +626,21 @@ export class MidyGM1 {
662
626
  const now = this.audioContext.currentTime;
663
627
  return this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now);
664
628
  }
665
- releaseSustainPedal(channelNumber) {
666
- const now = this.audioContext.currentTime;
629
+ releaseSustainPedal(channelNumber, halfVelocity) {
630
+ const velocity = halfVelocity * 2;
667
631
  const channel = this.channels[channelNumber];
632
+ const promises = [];
668
633
  channel.sustainPedal = false;
669
634
  channel.scheduledNotes.forEach((scheduledNotes) => {
670
635
  scheduledNotes.forEach((scheduledNote) => {
671
636
  if (scheduledNote) {
672
- const { gainNode, bufferSource, noteInfo } = scheduledNote;
673
- const volEndTime = now + noteInfo.volRelease;
674
- gainNode.gain.cancelScheduledValues(now);
675
- gainNode.gain.linearRampToValueAtTime(0, volEndTime);
676
- const baseFreq = this.centToHz(noteInfo.initialFilterFc);
677
- const modEndTime = stopTime + noteInfo.modRelease;
678
- filterNode.frequency.cancelScheduledValues(stopTime);
679
- filterNode.frequency.linearRampToValueAtTime(baseFreq, modEndTime);
680
- bufferSource.stop(volEndTime);
637
+ const { noteNumber } = scheduledNote;
638
+ const promise = this.releaseNote(channelNumber, noteNumber, velocity);
639
+ promises.push(promise);
681
640
  }
682
641
  });
683
642
  });
643
+ return promises;
684
644
  }
685
645
  handleMIDIMessage(statusByte, data1, data2) {
686
646
  const channelNumber = statusByte & 0x0F;
@@ -713,7 +673,7 @@ export class MidyGM1 {
713
673
  scheduledNotes.forEach((scheduledNote) => {
714
674
  if (scheduledNote) {
715
675
  const { initialAttenuation } = scheduledNote.noteInfo;
716
- const gain = this.cbToRatio(initialAttenuation) * pressure;
676
+ const gain = this.cbToRatio(-initialAttenuation) * pressure;
717
677
  scheduledNote.gainNode.gain.cancelScheduledValues(now);
718
678
  scheduledNote.gainNode.gain.setValueAtTime(gain, now);
719
679
  }
@@ -762,13 +722,9 @@ export class MidyGM1 {
762
722
  }
763
723
  }
764
724
  setModulation(channelNumber, modulation) {
765
- const now = this.audioContext.currentTime;
766
725
  const channel = this.channels[channelNumber];
767
- channel.modulation = (modulation * 100 / 127) *
768
- channel.modulationDepthRange;
769
- const lfoGain = channel.modulationEffect.lfoGain;
770
- lfoGain.gain.cancelScheduledValues(now);
771
- lfoGain.gain.setValueAtTime(channel.modulation, now);
726
+ channel.modulation = (modulation / 127) *
727
+ (channel.modulationDepthRange * 100);
772
728
  }
773
729
  setVolume(channelNumber, volume) {
774
730
  const channel = this.channels[channelNumber];
@@ -794,9 +750,10 @@ export class MidyGM1 {
794
750
  channel.gainNode.gain.setValueAtTime(volume, now);
795
751
  }
796
752
  setSustainPedal(channelNumber, value) {
797
- this.channels[channelNumber].sustainPedal = value >= 64;
753
+ const isOn = value >= 64;
754
+ this.channels[channelNumber].sustainPedal = isOn;
798
755
  if (!isOn) {
799
- this.releaseSustainPedal(channelNumber);
756
+ this.releaseSustainPedal(channelNumber, value);
800
757
  }
801
758
  }
802
759
  setRPNMSB(channelNumber, value) {
@@ -936,7 +893,7 @@ Object.defineProperty(MidyGM1, "channelSettings", {
936
893
  configurable: true,
937
894
  writable: true,
938
895
  value: {
939
- volume: 1,
896
+ volume: 100 / 127,
940
897
  pan: 0,
941
898
  vibratoRate: 5,
942
899
  vibratoDepth: 0.5,
@@ -948,7 +905,7 @@ Object.defineProperty(MidyGM1, "channelSettings", {
948
905
  pitchBend: 0,
949
906
  fineTuning: 0,
950
907
  coarseTuning: 0,
951
- modulationDepthRange: 2,
908
+ modulationDepthRange: 0.5,
952
909
  }
953
910
  });
954
911
  Object.defineProperty(MidyGM1, "effectSettings", {
package/esm/midy-GM2.d.ts CHANGED
@@ -34,7 +34,6 @@ export class MidyGM2 {
34
34
  };
35
35
  constructor(audioContext: any);
36
36
  ticksPerBeat: number;
37
- secondsPerBeat: number;
38
37
  totalTime: number;
39
38
  reverbFactor: number;
40
39
  masterFineTuning: number;
@@ -65,7 +64,6 @@ export class MidyGM2 {
65
64
  pannerNode: any;
66
65
  modulationEffect: {
67
66
  lfo: any;
68
- lfoGain: any;
69
67
  };
70
68
  reverbEffect: {
71
69
  convolverNode: any;
@@ -117,7 +115,6 @@ export class MidyGM2 {
117
115
  pannerNode: any;
118
116
  modulationEffect: {
119
117
  lfo: any;
120
- lfoGain: any;
121
118
  };
122
119
  reverbEffect: {
123
120
  convolverNode: any;
@@ -138,7 +135,6 @@ export class MidyGM2 {
138
135
  pannerNode: any;
139
136
  modulationEffect: {
140
137
  lfo: any;
141
- lfoGain: any;
142
138
  };
143
139
  reverbEffect: {
144
140
  convolverNode: any;
@@ -205,7 +201,6 @@ export class MidyGM2 {
205
201
  getActiveChannelNotes(scheduledNotes: any): any;
206
202
  createModulationEffect(audioContext: any): {
207
203
  lfo: any;
208
- lfoGain: any;
209
204
  };
210
205
  createReverbEffect(audioContext: any, options?: {}): {
211
206
  convolverNode: any;
@@ -225,14 +220,15 @@ export class MidyGM2 {
225
220
  bufferSource: any;
226
221
  gainNode: any;
227
222
  filterNode: any;
223
+ lfoGain: any;
228
224
  }>;
229
225
  calcBank(channel: any, channelNumber: any): any;
230
226
  scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
231
227
  noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
232
228
  scheduleNoteRelease(channelNumber: any, noteNumber: any, velocity: any, stopTime: any, stopPedal?: boolean): Promise<any> | undefined;
233
229
  releaseNote(channelNumber: any, noteNumber: any, velocity: any): Promise<any> | undefined;
234
- releaseSustainPedal(channelNumber: any): void;
235
- releaseSostenuto(channelNumber: any): void;
230
+ releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
231
+ releaseSostenutoPedal(channelNumber: any, halfVelocity: any): any[];
236
232
  handleMIDIMessage(statusByte: any, data1: any, data2: any): void | any[] | Promise<any>;
237
233
  handlePolyphonicKeyPressure(channelNumber: any, noteNumber: any, pressure: any): void;
238
234
  handleProgramChange(channelNumber: any, program: any): void;
@@ -1 +1 @@
1
- {"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"AAMA;IAyBE;;;;;;;;;;;;;;;;;;;;MAoBE;IAEF;;;;;;;;;;;MAWE;IAEF,+BAMC;IAjED,qBAAmB;IACnB,uBAAqB;IACrB,kBAAc;IACd,qBAAmB;IACnB,yBAAqB;IACrB,2BAAuB;IACvB,cAAa;IACb,cAAa;IACb,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,gBAAc;IACd,mBAAiB;IACjB,oBAAkB;IAsChB,kBAAgC;IAChC,gBAA4C;IAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;;;;;;;;;;;;;;;;MAuBC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAWC;IAED,0DAyBC;IAED,8DAUC;IAED,qDAOC;IAED,2EA6CC;IAED,mCAQC;IAED,0BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MA4FC;IAED,4BAsBC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBA2BC;IAED,sBAGC;IAED,4CASC;IAED,gDAKC;IAED;;;MAUC;IAED;;;;MAoCC;IAED;;;;;MA2CC;IAED,sDA2BC;IAED,2BAEC;IAED,4BAEC;IAED;;;;OA6EC;IAED,gDAQC;IAED,kGA+CC;IAED,0EAGC;IAED,sIAwCC;IAED,0FAGC;IAED,8CAmBC;IAED,2CAYC;IAED,wFAqBC;IAED,sFAeC;IAED,4DAIC;IAED,+DAEC;IAED,8DAGC;IAED,mFAuDC;IAED,+CAGC;IAED,yDAQC;IAED,iEAEC;IAED,iDAIC;IAED,2CAMC;IAED,yDAIC;IAED,+CAEC;IAED,sCAKC;IAED,sDAMC;IAED,oDAEC;IAED,iDASC;IAED,iDAIC;IAED,wDAQC;IAED,uDAIC;IAED,gDAEC;IAED,gDAEC;IAED,+DAuBC;IAED,uCAoBC;IAED,8CAEC;IAED,uCAoBC;IAED,gBAEC;IAED,eAEC;IAED,eAEC;IAED,eAEC;IAED,4DAmBC;IAED,oBAQC;IAED,oBAQC;IAED,yDAgDC;IAED,yCAGC;IAED,sCAIC;IAED,6CAGC;IAED,8CAMC;IAED,+CAGC;IAED,kDAMC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF"}
1
+ {"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"AAMA;IAwBE;;;;;;;;;;;;;;;;;;;;MAoBE;IAEF;;;;;;;;;;;MAWE;IAEF,+BAMC;IAhED,qBAAmB;IACnB,kBAAc;IACd,qBAAmB;IACnB,yBAAqB;IACrB,2BAAuB;IACvB,cAAa;IACb,cAAa;IACb,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,sBAA2C;IAC3C,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,gBAAc;IACd,mBAAiB;IACjB,oBAAkB;IAsChB,kBAAgC;IAChC,gBAA4C;IAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;;;;;;;;;;;;;;;MAuBC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAWC;IAED,0DAyBC;IAED,8DAUC;IAED,qDAOC;IAED,2EA4CC;IAED,mCAOC;IAED,0BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MA2GC;IAED,4BAsBC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,4CASC;IAED,gDAKC;IAED;;MAOC;IAED;;;;MAoCC;IAED;;;;;MA2CC;IAED,sDA2BC;IAED,2BAEC;IAED,4BAEC;IAED;;;;;OAsFC;IAED,gDAQC;IAED,kGAgDC;IAED,0EAGC;IAED,sIA6CC;IAED,0FAGC;IAED,kEAeC;IAED,oEAYC;IAED,wFAqBC;IAED,sFAeC;IAED,4DAIC;IAED,+DAEC;IAED,8DAGC;IAED,mFAuDC;IAED,+CAEC;IAED,yDAIC;IAED,iEAEC;IAED,iDAIC;IAED,2CAMC;IAED,yDAIC;IAED,+CAEC;IAED,sCAKC;IAED,sDAMC;IAED,oDAEC;IAED,iDASC;IAED,iDAIC;IAED,wDAUC;IAED,uDAGC;IAED,gDAEC;IAED,gDAEC;IAED,+DAuBC;IAED,uCAoBC;IAED,8CAEC;IAED,uCAoBC;IAED,gBAEC;IAED,eAEC;IAED,eAEC;IAED,eAEC;IAED,4DAmBC;IAED,oBAQC;IAED,oBAQC;IAED,yDAgDC;IAED,yCAGC;IAED,sCAIC;IAED,6CAGC;IAED,8CAMC;IAED,+CAGC;IAED,kDAMC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF"}