@marmooo/midy 0.0.2 → 0.0.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.
@@ -8,12 +8,6 @@ export class MidyGMLite {
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 MidyGMLite {
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,28 +220,30 @@ export class MidyGMLite {
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
- case "controller":
234
- this.handleControlChange(event.channel, event.controllerType, event.value);
235
- break;
236
226
  case "noteOn":
237
- await this.scheduleNoteOn(event.channel, event.noteNumber, event.velocity, time + this.startDelay - offset);
238
- break;
227
+ if (event.velocity !== 0) {
228
+ await this.scheduleNoteOn(event.channel, event.noteNumber, event.velocity, event.startTime + this.startDelay - offset);
229
+ break;
230
+ }
231
+ /* falls through */
239
232
  case "noteOff": {
240
- const notePromise = this.scheduleNoteRelease(event.channel, event.noteNumber, event.velocity, time + this.startDelay - offset);
233
+ const notePromise = this.scheduleNoteRelease(event.channel, event.noteNumber, event.velocity, event.startTime + this.startDelay - offset);
241
234
  if (notePromise) {
242
235
  this.notePromises.push(notePromise);
243
236
  }
244
237
  break;
245
238
  }
239
+ case "controller":
240
+ this.handleControlChange(event.channel, event.controllerType, event.value);
241
+ break;
246
242
  case "programChange":
247
243
  this.handleProgramChange(event.channel, event.programNumber);
248
244
  break;
249
- case "setTempo":
250
- this.secondsPerBeat = event.microsecondsPerBeat / 1000000;
245
+ case "pitchBend":
246
+ this.handlePitchBend(event.channel, event.value);
251
247
  break;
252
248
  case "sysEx":
253
249
  this.handleSysEx(event.data);
@@ -257,9 +253,8 @@ export class MidyGMLite {
257
253
  return queueIndex;
258
254
  }
259
255
  getQueueIndex(second) {
260
- const ticks = this.secondToTicks(second, this.secondsPerBeat);
261
256
  for (let i = 0; i < this.timeline.length; i++) {
262
- if (ticks <= this.timeline[i].ticks) {
257
+ if (second <= this.timeline[i].startTime) {
263
258
  return i;
264
259
  }
265
260
  }
@@ -367,18 +362,28 @@ export class MidyGMLite {
367
362
  timeline.push(event);
368
363
  });
369
364
  });
365
+ const priority = {
366
+ setTempo: 0,
367
+ controller: 1,
368
+ };
370
369
  timeline.sort((a, b) => {
371
- if (a.ticks !== b.ticks) {
370
+ if (a.ticks !== b.ticks)
372
371
  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;
372
+ return (priority[a.type] || 2) - (priority[b.type] || 2);
381
373
  });
374
+ let prevTempoTime = 0;
375
+ let prevTempoTicks = 0;
376
+ let secondsPerBeat = 0.5;
377
+ for (let i = 0; i < timeline.length; i++) {
378
+ const event = timeline[i];
379
+ const timeFromPrevTempo = this.ticksToSecond(event.ticks - prevTempoTicks, secondsPerBeat);
380
+ event.startTime = prevTempoTime + timeFromPrevTempo;
381
+ if (event.type === "setTempo") {
382
+ prevTempoTime += this.ticksToSecond(event.ticks - prevTempoTicks, secondsPerBeat);
383
+ secondsPerBeat = event.microsecondsPerBeat / 1000000;
384
+ prevTempoTicks = event.ticks;
385
+ }
386
+ }
382
387
  return { instruments, timeline };
383
388
  }
384
389
  stopNotes() {
@@ -430,32 +435,12 @@ export class MidyGMLite {
430
435
  }
431
436
  }
432
437
  calcTotalTime() {
433
- const endOfTracks = [];
434
- let prevTicks = 0;
435
438
  let totalTime = 0;
436
- let secondsPerBeat = 0.5;
437
439
  for (let i = 0; i < this.timeline.length; i++) {
438
440
  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
- }
441
+ if (totalTime < event.startTime)
442
+ totalTime = event.startTime;
450
443
  }
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
444
  return totalTime;
460
445
  }
461
446
  currentTime() {
@@ -483,43 +468,8 @@ export class MidyGMLite {
483
468
  const lfo = new OscillatorNode(audioContext, {
484
469
  frequency: 5,
485
470
  });
486
- const lfoGain = new GainNode(audioContext);
487
- lfo.connect(lfoGain);
488
471
  return {
489
472
  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
473
  };
524
474
  }
525
475
  connectNoteEffects(channel, gainNode) {
@@ -531,19 +481,23 @@ export class MidyGMLite {
531
481
  centToHz(cent) {
532
482
  return 8.176 * Math.pow(2, cent / 1200);
533
483
  }
484
+ calcSemitoneOffset(channel) {
485
+ return channel.pitchBend * channel.pitchBendRange + tuning;
486
+ }
487
+ calcPlaybackRate(noteInfo, noteNumber, semitoneOffset) {
488
+ return noteInfo.playbackRate(noteNumber) * Math.pow(2, semitoneOffset / 12);
489
+ }
534
490
  async createNoteAudioChain(channel, noteInfo, noteNumber, velocity, startTime, isSF3) {
535
- const semitoneOffset = channel.pitchBend * channel.pitchBendRange;
536
- const playbackRate = noteInfo.playbackRate(noteNumber) *
537
- Math.pow(2, semitoneOffset / 12);
538
491
  const bufferSource = await this.createNoteBufferNode(noteInfo, isSF3);
539
- bufferSource.playbackRate.value = playbackRate;
492
+ const semitoneOffset = this.calcSemitoneOffset(channel);
493
+ bufferSource.playbackRate.value = this.calcPlaybackRate(noteInfo, noteNumber, semitoneOffset);
540
494
  // volume envelope
541
495
  const gainNode = new GainNode(this.audioContext, {
542
496
  gain: 0,
543
497
  });
544
498
  let volume = (velocity / 127) * channel.volume * channel.expression;
545
499
  if (volume === 0)
546
- volume = 1e-6; // exponentialRampToValueAtTime() requirea a non-zero value
500
+ volume = 1e-6; // exponentialRampToValueAtTime() requires a non-zero value
547
501
  const attackVolume = this.cbToRatio(-noteInfo.initialAttenuation) * volume;
548
502
  const sustainVolume = attackVolume * (1 - noteInfo.volSustain);
549
503
  const volDelay = startTime + noteInfo.volDelay;
@@ -555,12 +509,6 @@ export class MidyGMLite {
555
509
  .exponentialRampToValueAtTime(attackVolume, volAttack)
556
510
  .setValueAtTime(attackVolume, volHold)
557
511
  .linearRampToValueAtTime(sustainVolume, volDecay);
558
- if (channel.modulation > 0) {
559
- const lfoGain = channel.modulationEffect.lfoGain;
560
- lfoGain.connect(bufferSource.detune);
561
- lfoGain.gain.cancelScheduledValues(startTime + channel.vibratoDelay);
562
- lfoGain.gain.setValueAtTime(channel.modulation, startTime + channel.vibratoDelay);
563
- }
564
512
  // filter envelope
565
513
  const maxFreq = this.audioContext.sampleRate / 2;
566
514
  const baseFreq = this.centToHz(noteInfo.initialFilterFc);
@@ -584,10 +532,23 @@ export class MidyGMLite {
584
532
  .exponentialRampToValueAtTime(adjustedPeekFreq, modAttack)
585
533
  .setValueAtTime(adjustedPeekFreq, modHold)
586
534
  .linearRampToValueAtTime(adjustedSustainFreq, modDecay);
535
+ let lfoGain;
536
+ if (channel.modulation > 0) {
537
+ const vibratoDelay = startTime + channel.vibratoDelay;
538
+ const vibratoAttack = vibratoDelay + 0.1;
539
+ lfoGain = new GainNode(this.audioContext, {
540
+ gain: 0,
541
+ });
542
+ lfoGain.gain
543
+ .setValueAtTime(1e-6, vibratoDelay) // exponentialRampToValueAtTime() requires a non-zero value
544
+ .exponentialRampToValueAtTime(channel.modulation, vibratoAttack);
545
+ channel.modulationEffect.lfo.connect(lfoGain);
546
+ lfoGain.connect(bufferSource.detune);
547
+ }
587
548
  bufferSource.connect(filterNode);
588
549
  filterNode.connect(gainNode);
589
550
  bufferSource.start(startTime, noteInfo.start / noteInfo.sampleRate);
590
- return { bufferSource, gainNode, filterNode };
551
+ return { bufferSource, gainNode, filterNode, lfoGain };
591
552
  }
592
553
  async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
593
554
  const channel = this.channels[channelNumber];
@@ -600,16 +561,17 @@ export class MidyGMLite {
600
561
  const noteInfo = soundFont.getInstrumentKey(bankNumber, channel.program, noteNumber);
601
562
  if (!noteInfo)
602
563
  return;
603
- const { bufferSource, gainNode, filterNode } = await this
564
+ const { bufferSource, gainNode, filterNode, lfoGain } = await this
604
565
  .createNoteAudioChain(channel, noteInfo, noteNumber, velocity, startTime, isSF3);
605
566
  this.connectNoteEffects(channel, gainNode);
606
567
  const scheduledNotes = channel.scheduledNotes;
607
568
  const scheduledNote = {
608
- gainNode,
609
- filterNode,
610
569
  bufferSource,
611
- noteNumber,
570
+ filterNode,
571
+ gainNode,
572
+ lfoGain,
612
573
  noteInfo,
574
+ noteNumber,
613
575
  startTime,
614
576
  };
615
577
  if (scheduledNotes.has(noteNumber)) {
@@ -636,7 +598,7 @@ export class MidyGMLite {
636
598
  continue;
637
599
  if (targetNote.ending)
638
600
  continue;
639
- const { bufferSource, filterNode, gainNode, noteInfo } = targetNote;
601
+ const { bufferSource, filterNode, gainNode, lfoGain, noteInfo } = targetNote;
640
602
  const velocityRate = (velocity + 127) / 127;
641
603
  const volEndTime = stopTime + noteInfo.volRelease * velocityRate;
642
604
  gainNode.gain.cancelScheduledValues(stopTime);
@@ -658,6 +620,8 @@ export class MidyGMLite {
658
620
  bufferSource.disconnect(0);
659
621
  filterNode.disconnect(0);
660
622
  gainNode.disconnect(0);
623
+ if (lfoGain)
624
+ lfoGain.disconnect(0);
661
625
  resolve();
662
626
  };
663
627
  bufferSource.stop(volEndTime);
@@ -668,28 +632,21 @@ export class MidyGMLite {
668
632
  const now = this.audioContext.currentTime;
669
633
  return this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now);
670
634
  }
671
- releaseSustainPedal(channelNumber) {
672
- const now = this.audioContext.currentTime;
635
+ releaseSustainPedal(channelNumber, halfVelocity) {
636
+ const velocity = halfVelocity * 2;
673
637
  const channel = this.channels[channelNumber];
638
+ const promises = [];
674
639
  channel.sustainPedal = false;
675
640
  channel.scheduledNotes.forEach((scheduledNotes) => {
676
641
  scheduledNotes.forEach((scheduledNote) => {
677
642
  if (scheduledNote) {
678
- const { bufferSource, gainNode, filterNode, noteInfo } = scheduledNote;
679
- const volEndTime = now + noteInfo.volRelease;
680
- gainNode.gain.cancelScheduledValues(now);
681
- gainNode.gain.linearRampToValueAtTime(0, volEndTime);
682
- const maxFreq = this.audioContext.sampleRate / 2;
683
- const baseFreq = this.centToHz(noteInfo.initialFilterFc);
684
- const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
685
- const modEndTime = now + noteInfo.modRelease;
686
- filterNode.frequency
687
- .cancelScheduledValues(stopTime)
688
- .linearRampToValueAtTime(adjustedBaseFreq, modEndTime);
689
- bufferSource.stop(volEndTime);
643
+ const { noteNumber } = scheduledNote;
644
+ const promise = this.releaseNote(channelNumber, noteNumber, velocity);
645
+ promises.push(promise);
690
646
  }
691
647
  });
692
648
  });
649
+ return promises;
693
650
  }
694
651
  handleMIDIMessage(statusByte, data1, data2) {
695
652
  const channelNumber = statusByte & 0x0F;
@@ -699,46 +656,37 @@ export class MidyGMLite {
699
656
  return this.releaseNote(channelNumber, data1, data2);
700
657
  case 0x90:
701
658
  return this.noteOn(channelNumber, data1, data2);
702
- case 0xA0:
703
- return this.handlePolyphonicKeyPressure(channelNumber, data1, data2);
704
659
  case 0xB0:
705
660
  return this.handleControlChange(channelNumber, data1, data2);
706
661
  case 0xC0:
707
662
  return this.handleProgramChange(channelNumber, data1);
708
- case 0xD0:
709
- return this.handleChannelPressure(channelNumber, data1);
710
663
  case 0xE0:
711
- return this.handlePitchBend(channelNumber, data1, data2);
664
+ return this.handlePitchBendMessage(channelNumber, data1, data2);
712
665
  default:
713
666
  console.warn(`Unsupported MIDI message: ${messageType.toString(16)}`);
714
667
  }
715
668
  }
716
- handlePolyphonicKeyPressure(channelNumber, noteNumber, pressure) {
717
- const now = this.audioContext.currentTime;
718
- const channel = this.channels[channelNumber];
719
- const scheduledNotes = channel.scheduledNotes.get(noteNumber);
720
- pressure /= 127;
721
- if (scheduledNotes) {
722
- scheduledNotes.forEach((scheduledNote) => {
723
- if (scheduledNote) {
724
- const { initialAttenuation } = scheduledNote.noteInfo;
725
- const gain = this.cbToRatio(-initialAttenuation) * pressure;
726
- scheduledNote.gainNode.gain.cancelScheduledValues(now);
727
- scheduledNote.gainNode.gain.setValueAtTime(gain, now);
728
- }
729
- });
730
- }
731
- }
732
669
  handleProgramChange(channelNumber, program) {
733
670
  const channel = this.channels[channelNumber];
734
671
  channel.program = program;
735
672
  }
736
- handleChannelPressure(channelNumber, pressure) {
737
- this.channels[channelNumber].channelPressure = pressure;
673
+ handlePitchBendMessage(channelNumber, lsb, msb) {
674
+ const pitchBend = msb * 128 + lsb;
675
+ this.handlePitchBend(channelNumber, pitchBend);
738
676
  }
739
- handlePitchBend(channelNumber, lsb, msb) {
740
- const pitchBend = (msb * 128 + lsb - 8192) / 8192;
741
- this.channels[channelNumber].pitchBend = pitchBend;
677
+ handlePitchBend(channelNumber, pitchBend) {
678
+ const now = this.audioContext.currentTime;
679
+ const channel = this.channels[channelNumber];
680
+ channel.pitchBend = (pitchBend - 8192) / 8192;
681
+ const semitoneOffset = this.calcSemitoneOffset(channel);
682
+ const activeNotes = this.getActiveNotes(channel);
683
+ activeNotes.forEach((activeNote) => {
684
+ const { bufferSource, noteInfo, noteNumber } = activeNote;
685
+ const playbackRate = calcPlaybackRate(noteInfo, noteNumber, semitoneOffset);
686
+ bufferSource.playbackRate
687
+ .cancelScheduledValues(now)
688
+ .setValueAtTime(playbackRate * pressure, now);
689
+ });
742
690
  }
743
691
  handleControlChange(channelNumber, controller, value) {
744
692
  switch (controller) {
@@ -771,13 +719,9 @@ export class MidyGMLite {
771
719
  }
772
720
  }
773
721
  setModulation(channelNumber, modulation) {
774
- const now = this.audioContext.currentTime;
775
722
  const channel = this.channels[channelNumber];
776
- channel.modulation = (modulation * 100 / 127) *
777
- channel.modulationDepthRange;
778
- const lfoGain = channel.modulationEffect.lfoGain;
779
- lfoGain.gain.cancelScheduledValues(now);
780
- lfoGain.gain.setValueAtTime(channel.modulation, now);
723
+ channel.modulation = (modulation / 127) *
724
+ (channel.modulationDepthRange * 100);
781
725
  }
782
726
  setVolume(channelNumber, volume) {
783
727
  const channel = this.channels[channelNumber];
@@ -806,7 +750,7 @@ export class MidyGMLite {
806
750
  const isOn = value >= 64;
807
751
  this.channels[channelNumber].sustainPedal = isOn;
808
752
  if (!isOn) {
809
- this.releaseSustainPedal(channelNumber);
753
+ this.releaseSustainPedal(channelNumber, value);
810
754
  }
811
755
  }
812
756
  setRPNMSB(channelNumber, value) {
@@ -902,13 +846,18 @@ export class MidyGMLite {
902
846
  }
903
847
  }
904
848
  handleMasterVolumeSysEx(data) {
905
- const volume = (data[5] * 128 + data[4] - 8192) / 8192;
849
+ const volume = (data[5] * 128 + data[4]) / 16383;
906
850
  this.handleMasterVolume(volume);
907
851
  }
908
852
  handleMasterVolume(volume) {
909
- const now = this.audioContext.currentTime;
910
- this.masterGain.gain.cancelScheduledValues(now);
911
- this.masterGain.gain.setValueAtTime(volume * volume, now);
853
+ if (volume < 0 && 1 < volume) {
854
+ console.error("Master Volume is out of range");
855
+ }
856
+ else {
857
+ const now = this.audioContext.currentTime;
858
+ this.masterGain.gain.cancelScheduledValues(now);
859
+ this.masterGain.gain.setValueAtTime(volume * volume, now);
860
+ }
912
861
  }
913
862
  handleExclusiveMessage(data) {
914
863
  console.warn(`Unsupported Exclusive Message ${data}`);
@@ -940,7 +889,7 @@ Object.defineProperty(MidyGMLite, "channelSettings", {
940
889
  configurable: true,
941
890
  writable: true,
942
891
  value: {
943
- volume: 1,
892
+ volume: 100 / 127,
944
893
  pan: 0,
945
894
  vibratoRate: 5,
946
895
  vibratoDepth: 0.5,
@@ -950,7 +899,7 @@ Object.defineProperty(MidyGMLite, "channelSettings", {
950
899
  dataLSB: 0,
951
900
  program: 0,
952
901
  pitchBend: 0,
953
- modulationDepthRange: 2,
902
+ modulationDepthRange: 0.5,
954
903
  }
955
904
  });
956
905
  Object.defineProperty(MidyGMLite, "effectSettings", {
package/esm/midy.d.ts CHANGED
@@ -32,9 +32,16 @@ export class Midy {
32
32
  channelPressure: number;
33
33
  pitchBendRange: number;
34
34
  };
35
+ static controllerDestinationSettings: {
36
+ pitchControl: number;
37
+ filterCutoffControl: number;
38
+ amplitudeControl: number;
39
+ lfoPitchDepth: number;
40
+ lfoFilterDepth: number;
41
+ lfoAmplitudeDepth: number;
42
+ };
35
43
  constructor(audioContext: any);
36
44
  ticksPerBeat: number;
37
- secondsPerBeat: number;
38
45
  totalTime: number;
39
46
  reverbFactor: number;
40
47
  masterFineTuning: number;
@@ -61,11 +68,26 @@ export class Midy {
61
68
  channels: {
62
69
  scheduledNotes: Map<any, any>;
63
70
  sostenutoNotes: Map<any, any>;
71
+ polyphonicKeyPressure: {
72
+ pitchControl: number;
73
+ filterCutoffControl: number;
74
+ amplitudeControl: number;
75
+ lfoPitchDepth: number;
76
+ lfoFilterDepth: number;
77
+ lfoAmplitudeDepth: number;
78
+ };
79
+ channelPressure: {
80
+ pitchControl: number;
81
+ filterCutoffControl: number;
82
+ amplitudeControl: number;
83
+ lfoPitchDepth: number;
84
+ lfoFilterDepth: number;
85
+ lfoAmplitudeDepth: number;
86
+ };
64
87
  gainNode: any;
65
88
  pannerNode: any;
66
89
  modulationEffect: {
67
90
  lfo: any;
68
- lfoGain: any;
69
91
  };
70
92
  reverbEffect: {
71
93
  convolverNode: any;
@@ -86,7 +108,6 @@ export class Midy {
86
108
  softPedal: number;
87
109
  rpnMSB: number;
88
110
  rpnLSB: number;
89
- channelPressure: number;
90
111
  pitchBendRange: number;
91
112
  currentBufferSource: null;
92
113
  volume: number;
@@ -117,7 +138,6 @@ export class Midy {
117
138
  pannerNode: any;
118
139
  modulationEffect: {
119
140
  lfo: any;
120
- lfoGain: any;
121
141
  };
122
142
  reverbEffect: {
123
143
  convolverNode: any;
@@ -134,11 +154,26 @@ export class Midy {
134
154
  createChannels(audioContext: any): {
135
155
  scheduledNotes: Map<any, any>;
136
156
  sostenutoNotes: Map<any, any>;
157
+ polyphonicKeyPressure: {
158
+ pitchControl: number;
159
+ filterCutoffControl: number;
160
+ amplitudeControl: number;
161
+ lfoPitchDepth: number;
162
+ lfoFilterDepth: number;
163
+ lfoAmplitudeDepth: number;
164
+ };
165
+ channelPressure: {
166
+ pitchControl: number;
167
+ filterCutoffControl: number;
168
+ amplitudeControl: number;
169
+ lfoPitchDepth: number;
170
+ lfoFilterDepth: number;
171
+ lfoAmplitudeDepth: number;
172
+ };
137
173
  gainNode: any;
138
174
  pannerNode: any;
139
175
  modulationEffect: {
140
176
  lfo: any;
141
- lfoGain: any;
142
177
  };
143
178
  reverbEffect: {
144
179
  convolverNode: any;
@@ -159,7 +194,6 @@ export class Midy {
159
194
  softPedal: number;
160
195
  rpnMSB: number;
161
196
  rpnLSB: number;
162
- channelPressure: number;
163
197
  pitchBendRange: number;
164
198
  currentBufferSource: null;
165
199
  volume: number;
@@ -205,7 +239,6 @@ export class Midy {
205
239
  getActiveChannelNotes(scheduledNotes: any): any;
206
240
  createModulationEffect(audioContext: any): {
207
241
  lfo: any;
208
- lfoGain: any;
209
242
  };
210
243
  createReverbEffect(audioContext: any, options?: {}): {
211
244
  convolverNode: any;
@@ -221,23 +254,27 @@ export class Midy {
221
254
  connectNoteEffects(channel: any, gainNode: any): void;
222
255
  cbToRatio(cb: any): number;
223
256
  centToHz(cent: any): number;
257
+ calcSemitoneOffset(channel: any): any;
258
+ calcPlaybackRate(noteInfo: any, noteNumber: any, semitoneOffset: any): number;
224
259
  createNoteAudioChain(channel: any, noteInfo: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<{
225
260
  bufferSource: any;
226
261
  gainNode: any;
227
262
  filterNode: any;
263
+ lfoGain: any;
228
264
  }>;
229
265
  calcBank(channel: any, channelNumber: any): any;
230
266
  scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
231
267
  noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
232
268
  scheduleNoteRelease(channelNumber: any, noteNumber: any, velocity: any, stopTime: any, stopPedal?: boolean): Promise<any> | undefined;
233
269
  releaseNote(channelNumber: any, noteNumber: any, velocity: any): Promise<any> | undefined;
234
- releaseSustainPedal(channelNumber: any): void;
235
- releaseSostenuto(channelNumber: any): void;
270
+ releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
271
+ releaseSostenutoPedal(channelNumber: any, halfVelocity: any): any[];
236
272
  handleMIDIMessage(statusByte: any, data1: any, data2: any): any;
237
273
  handlePolyphonicKeyPressure(channelNumber: any, noteNumber: any, pressure: any): void;
238
274
  handleProgramChange(channelNumber: any, program: any): void;
239
275
  handleChannelPressure(channelNumber: any, pressure: any): void;
240
- handlePitchBend(channelNumber: any, lsb: any, msb: any): void;
276
+ handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
277
+ handlePitchBend(channelNumber: any, pitchBend: any): void;
241
278
  handleControlChange(channelNumber: any, controller: any, value: any): any;
242
279
  setBankMSB(channelNumber: any, msb: any): void;
243
280
  setModulation(channelNumber: any, modulation: any): void;
package/esm/midy.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.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;;;;OAiFC;IAED,gDAQC;IAED,kGA+CC;IAED,0EAGC;IAED,sIA2CC;IAED,0FAGC;IAED,8CAuBC;IAED,2CAYC;IAED,gEAqBC;IAED,sFAeC;IAED,4DAIC;IAED,+DAEC;IAED,8DAGC;IAED,0EAkEC;IAED,+CAEC;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,2DAMC;IAED,6DAMC;IAED,6DASC;IAED,4CAkBC;IAED,4CAkBC;IAED,gDAEC;IAED,gDAEC;IAGD,+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.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"AAMA;IAwBE;;;;;;;;;;;;;;;;;;;;MAoBE;IAEF;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAEF,+BAMC;IAzED,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;IA+ChB,kBAAgC;IAChC,gBAA4C;IAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;;;;;;;;;;;;;;;MAuBC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAiBC;IAED,0DAyBC;IAED,8DAUC;IAED,qDAOC;IAED,2EAyDC;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,sCAKC;IAED,8EAEC;IAED;;;;;OAqFC;IAED,gDAQC;IAED,kGAgDC;IAED,0EAGC;IAED,sIA6CC;IAED,0FAGC;IAED,kEAeC;IAED,oEAYC;IAED,gEAqBC;IAED,sFAcC;IAED,4DAIC;IAED,+DAcC;IAED,qEAGC;IAED,0DAiBC;IAED,0EAkEC;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,2DAOC;IAED,6DAOC;IAED,6DASC;IAED,4CAkBC;IAED,4CAkBC;IAED,gDAEC;IAED,gDAEC;IAGD,+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,sCAQC;IAED,6CAGC;IAED,8CAMC;IAED,+CAGC;IAED,kDAMC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF"}