@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.
@@ -11,12 +11,6 @@ class MidyGMLite {
11
11
  writable: true,
12
12
  value: 120
13
13
  });
14
- Object.defineProperty(this, "secondsPerBeat", {
15
- enumerable: true,
16
- configurable: true,
17
- writable: true,
18
- value: 0.5
19
- });
20
14
  Object.defineProperty(this, "totalTime", {
21
15
  enumerable: true,
22
16
  configurable: true,
@@ -147,10 +141,10 @@ class MidyGMLite {
147
141
  const response = await fetch(midiUrl);
148
142
  const arrayBuffer = await response.arrayBuffer();
149
143
  const midi = (0, _esm_js_1.parseMidi)(new Uint8Array(arrayBuffer));
144
+ this.ticksPerBeat = midi.header.ticksPerBeat;
150
145
  const midiData = this.extractMidiData(midi);
151
146
  this.instruments = midiData.instruments;
152
147
  this.timeline = midiData.timeline;
153
- this.ticksPerBeat = midi.header.ticksPerBeat;
154
148
  this.totalTime = this.calcTotalTime();
155
149
  }
156
150
  setChannelAudioNodes(audioContext) {
@@ -229,28 +223,30 @@ class MidyGMLite {
229
223
  async scheduleTimelineEvents(t, offset, queueIndex) {
230
224
  while (queueIndex < this.timeline.length) {
231
225
  const event = this.timeline[queueIndex];
232
- const time = this.ticksToSecond(event.ticks, this.secondsPerBeat);
233
- if (time > t + this.lookAhead)
226
+ if (event.startTime > t + this.lookAhead)
234
227
  break;
235
228
  switch (event.type) {
236
- case "controller":
237
- this.handleControlChange(event.channel, event.controllerType, event.value);
238
- break;
239
229
  case "noteOn":
240
- await this.scheduleNoteOn(event.channel, event.noteNumber, event.velocity, time + this.startDelay - offset);
241
- 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 */
242
235
  case "noteOff": {
243
- 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);
244
237
  if (notePromise) {
245
238
  this.notePromises.push(notePromise);
246
239
  }
247
240
  break;
248
241
  }
242
+ case "controller":
243
+ this.handleControlChange(event.channel, event.controllerType, event.value);
244
+ break;
249
245
  case "programChange":
250
246
  this.handleProgramChange(event.channel, event.programNumber);
251
247
  break;
252
- case "setTempo":
253
- this.secondsPerBeat = event.microsecondsPerBeat / 1000000;
248
+ case "pitchBend":
249
+ this.handlePitchBend(event.channel, event.value);
254
250
  break;
255
251
  case "sysEx":
256
252
  this.handleSysEx(event.data);
@@ -260,9 +256,8 @@ class MidyGMLite {
260
256
  return queueIndex;
261
257
  }
262
258
  getQueueIndex(second) {
263
- const ticks = this.secondToTicks(second, this.secondsPerBeat);
264
259
  for (let i = 0; i < this.timeline.length; i++) {
265
- if (ticks <= this.timeline[i].ticks) {
260
+ if (second <= this.timeline[i].startTime) {
266
261
  return i;
267
262
  }
268
263
  }
@@ -370,18 +365,28 @@ class MidyGMLite {
370
365
  timeline.push(event);
371
366
  });
372
367
  });
368
+ const priority = {
369
+ setTempo: 0,
370
+ controller: 1,
371
+ };
373
372
  timeline.sort((a, b) => {
374
- if (a.ticks !== b.ticks) {
373
+ if (a.ticks !== b.ticks)
375
374
  return a.ticks - b.ticks;
376
- }
377
- if (a.type !== "controller" && b.type === "controller") {
378
- return -1;
379
- }
380
- if (a.type === "controller" && b.type !== "controller") {
381
- return 1;
382
- }
383
- return 0;
375
+ return (priority[a.type] || 2) - (priority[b.type] || 2);
384
376
  });
377
+ let prevTempoTime = 0;
378
+ let prevTempoTicks = 0;
379
+ let secondsPerBeat = 0.5;
380
+ for (let i = 0; i < timeline.length; i++) {
381
+ const event = timeline[i];
382
+ const timeFromPrevTempo = this.ticksToSecond(event.ticks - prevTempoTicks, secondsPerBeat);
383
+ event.startTime = prevTempoTime + timeFromPrevTempo;
384
+ if (event.type === "setTempo") {
385
+ prevTempoTime += this.ticksToSecond(event.ticks - prevTempoTicks, secondsPerBeat);
386
+ secondsPerBeat = event.microsecondsPerBeat / 1000000;
387
+ prevTempoTicks = event.ticks;
388
+ }
389
+ }
385
390
  return { instruments, timeline };
386
391
  }
387
392
  stopNotes() {
@@ -433,32 +438,12 @@ class MidyGMLite {
433
438
  }
434
439
  }
435
440
  calcTotalTime() {
436
- const endOfTracks = [];
437
- let prevTicks = 0;
438
441
  let totalTime = 0;
439
- let secondsPerBeat = 0.5;
440
442
  for (let i = 0; i < this.timeline.length; i++) {
441
443
  const event = this.timeline[i];
442
- switch (event.type) {
443
- case "setTempo": {
444
- const durationTicks = event.ticks - prevTicks;
445
- totalTime += this.ticksToSecond(durationTicks, secondsPerBeat);
446
- secondsPerBeat = event.microsecondsPerBeat / 1000000;
447
- prevTicks = event.ticks;
448
- break;
449
- }
450
- case "endOfTrack":
451
- endOfTracks.push(event);
452
- }
444
+ if (totalTime < event.startTime)
445
+ totalTime = event.startTime;
453
446
  }
454
- let maxTicks = 0;
455
- for (let i = 0; i < endOfTracks.length; i++) {
456
- const event = endOfTracks[i];
457
- if (maxTicks < event.ticks)
458
- maxTicks = event.ticks;
459
- }
460
- const durationTicks = maxTicks - prevTicks;
461
- totalTime += this.ticksToSecond(durationTicks, secondsPerBeat);
462
447
  return totalTime;
463
448
  }
464
449
  currentTime() {
@@ -486,43 +471,8 @@ class MidyGMLite {
486
471
  const lfo = new OscillatorNode(audioContext, {
487
472
  frequency: 5,
488
473
  });
489
- const lfoGain = new GainNode(audioContext);
490
- lfo.connect(lfoGain);
491
474
  return {
492
475
  lfo,
493
- lfoGain,
494
- };
495
- }
496
- createReverbEffect(audioContext, options = {}) {
497
- const { decay = 0.8, preDecay = 0, } = options;
498
- const sampleRate = audioContext.sampleRate;
499
- const length = sampleRate * decay;
500
- const impulse = new AudioBuffer({
501
- numberOfChannels: 2,
502
- length,
503
- sampleRate,
504
- });
505
- const preDecayLength = Math.min(sampleRate * preDecay, length);
506
- for (let channel = 0; channel < impulse.numberOfChannels; channel++) {
507
- const channelData = impulse.getChannelData(channel);
508
- for (let i = 0; i < preDecayLength; i++) {
509
- channelData[i] = Math.random() * 2 - 1;
510
- }
511
- for (let i = preDecayLength; i < length; i++) {
512
- const attenuation = Math.exp(-(i - preDecayLength) / sampleRate / decay);
513
- channelData[i] = (Math.random() * 2 - 1) * attenuation;
514
- }
515
- }
516
- const convolverNode = new ConvolverNode(audioContext, {
517
- buffer: impulse,
518
- });
519
- const dryGain = new GainNode(audioContext);
520
- const wetGain = new GainNode(audioContext);
521
- convolverNode.connect(wetGain);
522
- return {
523
- convolverNode,
524
- dryGain,
525
- wetGain,
526
476
  };
527
477
  }
528
478
  connectNoteEffects(channel, gainNode) {
@@ -534,19 +484,23 @@ class MidyGMLite {
534
484
  centToHz(cent) {
535
485
  return 8.176 * Math.pow(2, cent / 1200);
536
486
  }
487
+ calcSemitoneOffset(channel) {
488
+ return channel.pitchBend * channel.pitchBendRange + tuning;
489
+ }
490
+ calcPlaybackRate(noteInfo, noteNumber, semitoneOffset) {
491
+ return noteInfo.playbackRate(noteNumber) * Math.pow(2, semitoneOffset / 12);
492
+ }
537
493
  async createNoteAudioChain(channel, noteInfo, noteNumber, velocity, startTime, isSF3) {
538
- const semitoneOffset = channel.pitchBend * channel.pitchBendRange;
539
- const playbackRate = noteInfo.playbackRate(noteNumber) *
540
- Math.pow(2, semitoneOffset / 12);
541
494
  const bufferSource = await this.createNoteBufferNode(noteInfo, isSF3);
542
- bufferSource.playbackRate.value = playbackRate;
495
+ const semitoneOffset = this.calcSemitoneOffset(channel);
496
+ bufferSource.playbackRate.value = this.calcPlaybackRate(noteInfo, noteNumber, semitoneOffset);
543
497
  // volume envelope
544
498
  const gainNode = new GainNode(this.audioContext, {
545
499
  gain: 0,
546
500
  });
547
501
  let volume = (velocity / 127) * channel.volume * channel.expression;
548
502
  if (volume === 0)
549
- volume = 1e-6; // exponentialRampToValueAtTime() requirea a non-zero value
503
+ volume = 1e-6; // exponentialRampToValueAtTime() requires a non-zero value
550
504
  const attackVolume = this.cbToRatio(-noteInfo.initialAttenuation) * volume;
551
505
  const sustainVolume = attackVolume * (1 - noteInfo.volSustain);
552
506
  const volDelay = startTime + noteInfo.volDelay;
@@ -558,12 +512,6 @@ class MidyGMLite {
558
512
  .exponentialRampToValueAtTime(attackVolume, volAttack)
559
513
  .setValueAtTime(attackVolume, volHold)
560
514
  .linearRampToValueAtTime(sustainVolume, volDecay);
561
- if (channel.modulation > 0) {
562
- const lfoGain = channel.modulationEffect.lfoGain;
563
- lfoGain.connect(bufferSource.detune);
564
- lfoGain.gain.cancelScheduledValues(startTime + channel.vibratoDelay);
565
- lfoGain.gain.setValueAtTime(channel.modulation, startTime + channel.vibratoDelay);
566
- }
567
515
  // filter envelope
568
516
  const maxFreq = this.audioContext.sampleRate / 2;
569
517
  const baseFreq = this.centToHz(noteInfo.initialFilterFc);
@@ -587,10 +535,23 @@ class MidyGMLite {
587
535
  .exponentialRampToValueAtTime(adjustedPeekFreq, modAttack)
588
536
  .setValueAtTime(adjustedPeekFreq, modHold)
589
537
  .linearRampToValueAtTime(adjustedSustainFreq, modDecay);
538
+ let lfoGain;
539
+ if (channel.modulation > 0) {
540
+ const vibratoDelay = startTime + channel.vibratoDelay;
541
+ const vibratoAttack = vibratoDelay + 0.1;
542
+ lfoGain = new GainNode(this.audioContext, {
543
+ gain: 0,
544
+ });
545
+ lfoGain.gain
546
+ .setValueAtTime(1e-6, vibratoDelay) // exponentialRampToValueAtTime() requires a non-zero value
547
+ .exponentialRampToValueAtTime(channel.modulation, vibratoAttack);
548
+ channel.modulationEffect.lfo.connect(lfoGain);
549
+ lfoGain.connect(bufferSource.detune);
550
+ }
590
551
  bufferSource.connect(filterNode);
591
552
  filterNode.connect(gainNode);
592
553
  bufferSource.start(startTime, noteInfo.start / noteInfo.sampleRate);
593
- return { bufferSource, gainNode, filterNode };
554
+ return { bufferSource, gainNode, filterNode, lfoGain };
594
555
  }
595
556
  async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
596
557
  const channel = this.channels[channelNumber];
@@ -603,16 +564,17 @@ class MidyGMLite {
603
564
  const noteInfo = soundFont.getInstrumentKey(bankNumber, channel.program, noteNumber);
604
565
  if (!noteInfo)
605
566
  return;
606
- const { bufferSource, gainNode, filterNode } = await this
567
+ const { bufferSource, gainNode, filterNode, lfoGain } = await this
607
568
  .createNoteAudioChain(channel, noteInfo, noteNumber, velocity, startTime, isSF3);
608
569
  this.connectNoteEffects(channel, gainNode);
609
570
  const scheduledNotes = channel.scheduledNotes;
610
571
  const scheduledNote = {
611
- gainNode,
612
- filterNode,
613
572
  bufferSource,
614
- noteNumber,
573
+ filterNode,
574
+ gainNode,
575
+ lfoGain,
615
576
  noteInfo,
577
+ noteNumber,
616
578
  startTime,
617
579
  };
618
580
  if (scheduledNotes.has(noteNumber)) {
@@ -639,7 +601,7 @@ class MidyGMLite {
639
601
  continue;
640
602
  if (targetNote.ending)
641
603
  continue;
642
- const { bufferSource, filterNode, gainNode, noteInfo } = targetNote;
604
+ const { bufferSource, filterNode, gainNode, lfoGain, noteInfo } = targetNote;
643
605
  const velocityRate = (velocity + 127) / 127;
644
606
  const volEndTime = stopTime + noteInfo.volRelease * velocityRate;
645
607
  gainNode.gain.cancelScheduledValues(stopTime);
@@ -661,6 +623,8 @@ class MidyGMLite {
661
623
  bufferSource.disconnect(0);
662
624
  filterNode.disconnect(0);
663
625
  gainNode.disconnect(0);
626
+ if (lfoGain)
627
+ lfoGain.disconnect(0);
664
628
  resolve();
665
629
  };
666
630
  bufferSource.stop(volEndTime);
@@ -671,28 +635,21 @@ class MidyGMLite {
671
635
  const now = this.audioContext.currentTime;
672
636
  return this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now);
673
637
  }
674
- releaseSustainPedal(channelNumber) {
675
- const now = this.audioContext.currentTime;
638
+ releaseSustainPedal(channelNumber, halfVelocity) {
639
+ const velocity = halfVelocity * 2;
676
640
  const channel = this.channels[channelNumber];
641
+ const promises = [];
677
642
  channel.sustainPedal = false;
678
643
  channel.scheduledNotes.forEach((scheduledNotes) => {
679
644
  scheduledNotes.forEach((scheduledNote) => {
680
645
  if (scheduledNote) {
681
- const { bufferSource, gainNode, filterNode, noteInfo } = scheduledNote;
682
- const volEndTime = now + noteInfo.volRelease;
683
- gainNode.gain.cancelScheduledValues(now);
684
- gainNode.gain.linearRampToValueAtTime(0, volEndTime);
685
- const maxFreq = this.audioContext.sampleRate / 2;
686
- const baseFreq = this.centToHz(noteInfo.initialFilterFc);
687
- const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
688
- const modEndTime = now + noteInfo.modRelease;
689
- filterNode.frequency
690
- .cancelScheduledValues(stopTime)
691
- .linearRampToValueAtTime(adjustedBaseFreq, modEndTime);
692
- bufferSource.stop(volEndTime);
646
+ const { noteNumber } = scheduledNote;
647
+ const promise = this.releaseNote(channelNumber, noteNumber, velocity);
648
+ promises.push(promise);
693
649
  }
694
650
  });
695
651
  });
652
+ return promises;
696
653
  }
697
654
  handleMIDIMessage(statusByte, data1, data2) {
698
655
  const channelNumber = statusByte & 0x0F;
@@ -702,46 +659,37 @@ class MidyGMLite {
702
659
  return this.releaseNote(channelNumber, data1, data2);
703
660
  case 0x90:
704
661
  return this.noteOn(channelNumber, data1, data2);
705
- case 0xA0:
706
- return this.handlePolyphonicKeyPressure(channelNumber, data1, data2);
707
662
  case 0xB0:
708
663
  return this.handleControlChange(channelNumber, data1, data2);
709
664
  case 0xC0:
710
665
  return this.handleProgramChange(channelNumber, data1);
711
- case 0xD0:
712
- return this.handleChannelPressure(channelNumber, data1);
713
666
  case 0xE0:
714
- return this.handlePitchBend(channelNumber, data1, data2);
667
+ return this.handlePitchBendMessage(channelNumber, data1, data2);
715
668
  default:
716
669
  console.warn(`Unsupported MIDI message: ${messageType.toString(16)}`);
717
670
  }
718
671
  }
719
- handlePolyphonicKeyPressure(channelNumber, noteNumber, pressure) {
720
- const now = this.audioContext.currentTime;
721
- const channel = this.channels[channelNumber];
722
- const scheduledNotes = channel.scheduledNotes.get(noteNumber);
723
- pressure /= 127;
724
- if (scheduledNotes) {
725
- scheduledNotes.forEach((scheduledNote) => {
726
- if (scheduledNote) {
727
- const { initialAttenuation } = scheduledNote.noteInfo;
728
- const gain = this.cbToRatio(-initialAttenuation) * pressure;
729
- scheduledNote.gainNode.gain.cancelScheduledValues(now);
730
- scheduledNote.gainNode.gain.setValueAtTime(gain, now);
731
- }
732
- });
733
- }
734
- }
735
672
  handleProgramChange(channelNumber, program) {
736
673
  const channel = this.channels[channelNumber];
737
674
  channel.program = program;
738
675
  }
739
- handleChannelPressure(channelNumber, pressure) {
740
- this.channels[channelNumber].channelPressure = pressure;
676
+ handlePitchBendMessage(channelNumber, lsb, msb) {
677
+ const pitchBend = msb * 128 + lsb;
678
+ this.handlePitchBend(channelNumber, pitchBend);
741
679
  }
742
- handlePitchBend(channelNumber, lsb, msb) {
743
- const pitchBend = (msb * 128 + lsb - 8192) / 8192;
744
- this.channels[channelNumber].pitchBend = pitchBend;
680
+ handlePitchBend(channelNumber, pitchBend) {
681
+ const now = this.audioContext.currentTime;
682
+ const channel = this.channels[channelNumber];
683
+ channel.pitchBend = (pitchBend - 8192) / 8192;
684
+ const semitoneOffset = this.calcSemitoneOffset(channel);
685
+ const activeNotes = this.getActiveNotes(channel);
686
+ activeNotes.forEach((activeNote) => {
687
+ const { bufferSource, noteInfo, noteNumber } = activeNote;
688
+ const playbackRate = calcPlaybackRate(noteInfo, noteNumber, semitoneOffset);
689
+ bufferSource.playbackRate
690
+ .cancelScheduledValues(now)
691
+ .setValueAtTime(playbackRate * pressure, now);
692
+ });
745
693
  }
746
694
  handleControlChange(channelNumber, controller, value) {
747
695
  switch (controller) {
@@ -774,13 +722,9 @@ class MidyGMLite {
774
722
  }
775
723
  }
776
724
  setModulation(channelNumber, modulation) {
777
- const now = this.audioContext.currentTime;
778
725
  const channel = this.channels[channelNumber];
779
- channel.modulation = (modulation * 100 / 127) *
780
- channel.modulationDepthRange;
781
- const lfoGain = channel.modulationEffect.lfoGain;
782
- lfoGain.gain.cancelScheduledValues(now);
783
- lfoGain.gain.setValueAtTime(channel.modulation, now);
726
+ channel.modulation = (modulation / 127) *
727
+ (channel.modulationDepthRange * 100);
784
728
  }
785
729
  setVolume(channelNumber, volume) {
786
730
  const channel = this.channels[channelNumber];
@@ -809,7 +753,7 @@ class MidyGMLite {
809
753
  const isOn = value >= 64;
810
754
  this.channels[channelNumber].sustainPedal = isOn;
811
755
  if (!isOn) {
812
- this.releaseSustainPedal(channelNumber);
756
+ this.releaseSustainPedal(channelNumber, value);
813
757
  }
814
758
  }
815
759
  setRPNMSB(channelNumber, value) {
@@ -905,13 +849,18 @@ class MidyGMLite {
905
849
  }
906
850
  }
907
851
  handleMasterVolumeSysEx(data) {
908
- const volume = (data[5] * 128 + data[4] - 8192) / 8192;
852
+ const volume = (data[5] * 128 + data[4]) / 16383;
909
853
  this.handleMasterVolume(volume);
910
854
  }
911
855
  handleMasterVolume(volume) {
912
- const now = this.audioContext.currentTime;
913
- this.masterGain.gain.cancelScheduledValues(now);
914
- this.masterGain.gain.setValueAtTime(volume * volume, now);
856
+ if (volume < 0 && 1 < volume) {
857
+ console.error("Master Volume is out of range");
858
+ }
859
+ else {
860
+ const now = this.audioContext.currentTime;
861
+ this.masterGain.gain.cancelScheduledValues(now);
862
+ this.masterGain.gain.setValueAtTime(volume * volume, now);
863
+ }
915
864
  }
916
865
  handleExclusiveMessage(data) {
917
866
  console.warn(`Unsupported Exclusive Message ${data}`);
@@ -944,7 +893,7 @@ Object.defineProperty(MidyGMLite, "channelSettings", {
944
893
  configurable: true,
945
894
  writable: true,
946
895
  value: {
947
- volume: 1,
896
+ volume: 100 / 127,
948
897
  pan: 0,
949
898
  vibratoRate: 5,
950
899
  vibratoDepth: 0.5,
@@ -954,7 +903,7 @@ Object.defineProperty(MidyGMLite, "channelSettings", {
954
903
  dataLSB: 0,
955
904
  program: 0,
956
905
  pitchBend: 0,
957
- modulationDepthRange: 2,
906
+ modulationDepthRange: 0.5,
958
907
  }
959
908
  });
960
909
  Object.defineProperty(MidyGMLite, "effectSettings", {
package/script/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;
@@ -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"}