@marmooo/midy 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.d.ts +153 -0
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.d.ts.map +1 -0
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/{soundfont-parser@0.0.2 → soundfont-parser@0.0.4}/+esm.js +73 -66
- package/esm/midy-GM1.d.ts +19 -13
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +171 -131
- package/esm/midy-GM2.d.ts +22 -14
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +186 -133
- package/esm/midy-GMLite.d.ts +17 -13
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +159 -131
- package/esm/midy.d.ts +30 -16
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +266 -166
- package/package.json +1 -1
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.d.ts +153 -0
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.d.ts.map +1 -0
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/{soundfont-parser@0.0.2 → soundfont-parser@0.0.4}/+esm.js +75 -68
- package/script/midy-GM1.d.ts +19 -13
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +171 -131
- package/script/midy-GM2.d.ts +22 -14
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +186 -133
- package/script/midy-GMLite.d.ts +17 -13
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +159 -131
- package/script/midy.d.ts +30 -16
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +266 -166
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.d.ts +0 -135
- package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.d.ts.map +0 -1
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.d.ts +0 -135
- package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.d.ts.map +0 -1
package/esm/midy-GM1.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseMidi } from "./deps/cdn.jsdelivr.net/npm/midi-file@1.2.4/+esm.js";
|
|
2
|
-
import { parse, SoundFont, } from "./deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.
|
|
2
|
+
import { parse, SoundFont, } from "./deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.4/+esm.js";
|
|
3
3
|
class Note {
|
|
4
4
|
constructor(noteNumber, velocity, startTime, instrumentKey) {
|
|
5
5
|
Object.defineProperty(this, "bufferSource", {
|
|
@@ -8,25 +8,43 @@ class Note {
|
|
|
8
8
|
writable: true,
|
|
9
9
|
value: void 0
|
|
10
10
|
});
|
|
11
|
-
Object.defineProperty(this, "
|
|
11
|
+
Object.defineProperty(this, "filterNode", {
|
|
12
12
|
enumerable: true,
|
|
13
13
|
configurable: true,
|
|
14
14
|
writable: true,
|
|
15
15
|
value: void 0
|
|
16
16
|
});
|
|
17
|
-
Object.defineProperty(this, "
|
|
17
|
+
Object.defineProperty(this, "volumeNode", {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
configurable: true,
|
|
20
|
+
writable: true,
|
|
21
|
+
value: void 0
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(this, "volumeDepth", {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
writable: true,
|
|
27
|
+
value: void 0
|
|
28
|
+
});
|
|
29
|
+
Object.defineProperty(this, "modulationLFO", {
|
|
18
30
|
enumerable: true,
|
|
19
31
|
configurable: true,
|
|
20
32
|
writable: true,
|
|
21
33
|
value: void 0
|
|
22
34
|
});
|
|
23
|
-
Object.defineProperty(this, "
|
|
35
|
+
Object.defineProperty(this, "modulationDepth", {
|
|
24
36
|
enumerable: true,
|
|
25
37
|
configurable: true,
|
|
26
38
|
writable: true,
|
|
27
39
|
value: void 0
|
|
28
40
|
});
|
|
29
|
-
Object.defineProperty(this, "
|
|
41
|
+
Object.defineProperty(this, "vibratoLFO", {
|
|
42
|
+
enumerable: true,
|
|
43
|
+
configurable: true,
|
|
44
|
+
writable: true,
|
|
45
|
+
value: void 0
|
|
46
|
+
});
|
|
47
|
+
Object.defineProperty(this, "vibratoDepth", {
|
|
30
48
|
enumerable: true,
|
|
31
49
|
configurable: true,
|
|
32
50
|
writable: true,
|
|
@@ -313,7 +331,7 @@ export class MidyGM1 {
|
|
|
313
331
|
const t = this.audioContext.currentTime + offset;
|
|
314
332
|
queueIndex = await this.scheduleTimelineEvents(t, offset, queueIndex);
|
|
315
333
|
if (this.isPausing) {
|
|
316
|
-
await this.stopNotes();
|
|
334
|
+
await this.stopNotes(0, true);
|
|
317
335
|
this.notePromises = [];
|
|
318
336
|
resolve();
|
|
319
337
|
this.isPausing = false;
|
|
@@ -321,7 +339,7 @@ export class MidyGM1 {
|
|
|
321
339
|
return;
|
|
322
340
|
}
|
|
323
341
|
else if (this.isStopping) {
|
|
324
|
-
await this.stopNotes();
|
|
342
|
+
await this.stopNotes(0, true);
|
|
325
343
|
this.notePromises = [];
|
|
326
344
|
resolve();
|
|
327
345
|
this.isStopping = false;
|
|
@@ -329,7 +347,7 @@ export class MidyGM1 {
|
|
|
329
347
|
return;
|
|
330
348
|
}
|
|
331
349
|
else if (this.isSeeking) {
|
|
332
|
-
this.stopNotes();
|
|
350
|
+
this.stopNotes(0, true);
|
|
333
351
|
this.startTime = this.audioContext.currentTime;
|
|
334
352
|
queueIndex = this.getQueueIndex(this.resumeTime);
|
|
335
353
|
offset = this.resumeTime - this.startTime;
|
|
@@ -410,21 +428,25 @@ export class MidyGM1 {
|
|
|
410
428
|
}
|
|
411
429
|
return { instruments, timeline };
|
|
412
430
|
}
|
|
413
|
-
|
|
431
|
+
async stopChannelNotes(channelNumber, velocity, stopPedal) {
|
|
414
432
|
const now = this.audioContext.currentTime;
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
});
|
|
425
|
-
});
|
|
426
|
-
channel.scheduledNotes.clear();
|
|
433
|
+
const channel = this.channels[channelNumber];
|
|
434
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
435
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
436
|
+
const note = noteList[i];
|
|
437
|
+
if (!note)
|
|
438
|
+
continue;
|
|
439
|
+
const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now, stopPedal);
|
|
440
|
+
this.notePromises.push(promise);
|
|
441
|
+
}
|
|
427
442
|
});
|
|
443
|
+
channel.scheduledNotes.clear();
|
|
444
|
+
await Promise.all(this.notePromises);
|
|
445
|
+
}
|
|
446
|
+
stopNotes(velocity, stopPedal) {
|
|
447
|
+
for (let i = 0; i < this.channels.length; i++) {
|
|
448
|
+
this.stopChannelNotes(i, velocity, stopPedal);
|
|
449
|
+
}
|
|
428
450
|
return Promise.all(this.notePromises);
|
|
429
451
|
}
|
|
430
452
|
async start() {
|
|
@@ -508,75 +530,111 @@ export class MidyGM1 {
|
|
|
508
530
|
}
|
|
509
531
|
setVolumeEnvelope(note) {
|
|
510
532
|
const { instrumentKey, startTime } = note;
|
|
511
|
-
note.gainNode = new GainNode(this.audioContext, { gain: 0 });
|
|
512
533
|
const attackVolume = this.cbToRatio(-instrumentKey.initialAttenuation);
|
|
513
534
|
const sustainVolume = attackVolume * (1 - instrumentKey.volSustain);
|
|
514
535
|
const volDelay = startTime + instrumentKey.volDelay;
|
|
515
536
|
const volAttack = volDelay + instrumentKey.volAttack;
|
|
516
537
|
const volHold = volAttack + instrumentKey.volHold;
|
|
517
538
|
const volDecay = volHold + instrumentKey.volDecay;
|
|
518
|
-
note.
|
|
539
|
+
note.volumeNode.gain
|
|
540
|
+
.cancelScheduledValues(startTime)
|
|
541
|
+
.setValueAtTime(0, startTime)
|
|
519
542
|
.setValueAtTime(1e-6, volDelay) // exponentialRampToValueAtTime() requires a non-zero value
|
|
520
543
|
.exponentialRampToValueAtTime(attackVolume, volAttack)
|
|
521
544
|
.setValueAtTime(attackVolume, volHold)
|
|
522
545
|
.linearRampToValueAtTime(sustainVolume, volDecay);
|
|
523
546
|
}
|
|
524
|
-
|
|
525
|
-
const { instrumentKey,
|
|
526
|
-
const
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
const
|
|
532
|
-
const
|
|
533
|
-
|
|
547
|
+
setPitch(note, semitoneOffset) {
|
|
548
|
+
const { instrumentKey, noteNumber, startTime } = note;
|
|
549
|
+
const modEnvToPitch = instrumentKey.modEnvToPitch / 100;
|
|
550
|
+
note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
|
|
551
|
+
if (modEnvToPitch === 0)
|
|
552
|
+
return;
|
|
553
|
+
const basePitch = note.bufferSource.playbackRate.value;
|
|
554
|
+
const peekPitch = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset + modEnvToPitch);
|
|
555
|
+
const modDelay = startTime + instrumentKey.modDelay;
|
|
556
|
+
const modAttack = modDelay + instrumentKey.modAttack;
|
|
557
|
+
const modHold = modAttack + instrumentKey.modHold;
|
|
558
|
+
const modDecay = modHold + instrumentKey.modDecay;
|
|
559
|
+
note.bufferSource.playbackRate.value
|
|
560
|
+
.setValueAtTime(basePitch, modDelay)
|
|
561
|
+
.exponentialRampToValueAtTime(peekPitch, modAttack)
|
|
562
|
+
.setValueAtTime(peekPitch, modHold)
|
|
563
|
+
.linearRampToValueAtTime(basePitch, modDecay);
|
|
564
|
+
}
|
|
565
|
+
clampCutoffFrequency(frequency) {
|
|
566
|
+
const minFrequency = 20; // min Hz of initialFilterFc
|
|
567
|
+
const maxFrequency = 20000; // max Hz of initialFilterFc
|
|
568
|
+
return Math.max(minFrequency, Math.min(frequency, maxFrequency));
|
|
569
|
+
}
|
|
570
|
+
setFilterEnvelope(note) {
|
|
571
|
+
const { instrumentKey, startTime } = note;
|
|
572
|
+
const baseFreq = this.centToHz(instrumentKey.initialFilterFc);
|
|
573
|
+
const peekFreq = this.centToHz(instrumentKey.initialFilterFc + instrumentKey.modEnvToFilterFc);
|
|
574
|
+
const sustainFreq = baseFreq +
|
|
575
|
+
(peekFreq - baseFreq) * (1 - instrumentKey.modSustain);
|
|
576
|
+
const adjustedBaseFreq = this.clampCutoffFrequency(baseFreq);
|
|
577
|
+
const adjustedPeekFreq = this.clampCutoffFrequency(peekFreq);
|
|
578
|
+
const adjustedSustainFreq = this.clampCutoffFrequency(sustainFreq);
|
|
534
579
|
const modDelay = startTime + instrumentKey.modDelay;
|
|
535
580
|
const modAttack = modDelay + instrumentKey.modAttack;
|
|
536
581
|
const modHold = modAttack + instrumentKey.modHold;
|
|
537
582
|
const modDecay = modHold + instrumentKey.modDecay;
|
|
538
|
-
const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
|
|
539
|
-
const adjustedPeekFreq = Math.min(maxFreq, peekFreq);
|
|
540
|
-
const adjustedSustainFreq = Math.min(maxFreq, sustainFreq);
|
|
541
|
-
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
542
|
-
type: "lowpass",
|
|
543
|
-
Q: instrumentKey.initialFilterQ / 10, // dB
|
|
544
|
-
frequency: adjustedBaseFreq,
|
|
545
|
-
});
|
|
546
583
|
note.filterNode.frequency
|
|
584
|
+
.cancelScheduledValues(startTime)
|
|
585
|
+
.setValueAtTime(adjustedBaseFreq, startTime)
|
|
547
586
|
.setValueAtTime(adjustedBaseFreq, modDelay)
|
|
548
587
|
.exponentialRampToValueAtTime(adjustedPeekFreq, modAttack)
|
|
549
588
|
.setValueAtTime(adjustedPeekFreq, modHold)
|
|
550
589
|
.linearRampToValueAtTime(adjustedSustainFreq, modDecay);
|
|
551
|
-
note.bufferSource.detune.setValueAtTime(note.bufferSource.detune.value + instrumentKey.modEnvToPitch, modDelay);
|
|
552
590
|
}
|
|
553
|
-
startModulation(channel, note,
|
|
591
|
+
startModulation(channel, note, startTime) {
|
|
554
592
|
const { instrumentKey } = note;
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
});
|
|
558
|
-
note.modLFO = new OscillatorNode(this.audioContext, {
|
|
593
|
+
const { modLfoToPitch, modLfoToVolume } = instrumentKey;
|
|
594
|
+
note.modulationLFO = new OscillatorNode(this.audioContext, {
|
|
559
595
|
frequency: this.centToHz(instrumentKey.freqModLFO),
|
|
560
596
|
});
|
|
561
|
-
note.
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
597
|
+
note.filterDepth = new GainNode(this.audioContext, {
|
|
598
|
+
gain: instrumentKey.modLfoToFilterFc,
|
|
599
|
+
});
|
|
600
|
+
const modulationDepth = Math.abs(modLfoToPitch) + channel.modulationDepth;
|
|
601
|
+
const modulationDepthSign = (0 < modLfoToPitch) ? 1 : -1;
|
|
602
|
+
note.modulationDepth = new GainNode(this.audioContext, {
|
|
603
|
+
gain: modulationDepth * modulationDepthSign,
|
|
604
|
+
});
|
|
605
|
+
const volumeDepth = this.cbToRatio(Math.abs(modLfoToVolume)) - 1;
|
|
606
|
+
const volumeDepthSign = (0 < modLfoToVolume) ? 1 : -1;
|
|
607
|
+
note.volumeDepth = new GainNode(this.audioContext, {
|
|
608
|
+
gain: volumeDepth * volumeDepthSign,
|
|
609
|
+
});
|
|
610
|
+
note.modulationLFO.start(startTime + instrumentKey.delayModLFO);
|
|
611
|
+
note.modulationLFO.connect(note.filterDepth);
|
|
612
|
+
note.filterDepth.connect(note.filterNode.frequency);
|
|
613
|
+
note.modulationLFO.connect(note.modulationDepth);
|
|
614
|
+
note.modulationDepth.connect(note.bufferSource.detune);
|
|
615
|
+
note.modulationLFO.connect(note.volumeDepth);
|
|
616
|
+
note.volumeDepth.connect(note.volumeNode.gain);
|
|
566
617
|
}
|
|
567
618
|
async createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3) {
|
|
568
619
|
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
569
620
|
const note = new Note(noteNumber, velocity, startTime, instrumentKey);
|
|
570
621
|
note.bufferSource = await this.createNoteBufferNode(instrumentKey, isSF3);
|
|
571
|
-
note.
|
|
622
|
+
note.volumeNode = new GainNode(this.audioContext);
|
|
623
|
+
note.filterNode = new BiquadFilterNode(this.audioContext, {
|
|
624
|
+
type: "lowpass",
|
|
625
|
+
Q: instrumentKey.initialFilterQ / 10 * channel.filterResonance, // dB
|
|
626
|
+
});
|
|
572
627
|
this.setVolumeEnvelope(note);
|
|
573
|
-
this.setFilterEnvelope(
|
|
574
|
-
if (channel.
|
|
575
|
-
|
|
576
|
-
this.startModulation(channel, note,
|
|
628
|
+
this.setFilterEnvelope(note);
|
|
629
|
+
if (0 < channel.modulationDepth) {
|
|
630
|
+
this.setPitch(note, semitoneOffset);
|
|
631
|
+
this.startModulation(channel, note, startTime);
|
|
632
|
+
}
|
|
633
|
+
else {
|
|
634
|
+
note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
|
|
577
635
|
}
|
|
578
636
|
note.bufferSource.connect(note.filterNode);
|
|
579
|
-
note.filterNode.connect(note.
|
|
637
|
+
note.filterNode.connect(note.volumeNode);
|
|
580
638
|
note.bufferSource.start(startTime, instrumentKey.start / instrumentKey.sampleRate);
|
|
581
639
|
return note;
|
|
582
640
|
}
|
|
@@ -592,8 +650,8 @@ export class MidyGM1 {
|
|
|
592
650
|
if (!instrumentKey)
|
|
593
651
|
return;
|
|
594
652
|
const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
|
|
595
|
-
note.
|
|
596
|
-
note.
|
|
653
|
+
note.volumeNode.connect(channel.gainL);
|
|
654
|
+
note.volumeNode.connect(channel.gainR);
|
|
597
655
|
const scheduledNotes = channel.scheduledNotes;
|
|
598
656
|
if (scheduledNotes.has(noteNumber)) {
|
|
599
657
|
scheduledNotes.get(noteNumber).push(note);
|
|
@@ -606,7 +664,7 @@ export class MidyGM1 {
|
|
|
606
664
|
const now = this.audioContext.currentTime;
|
|
607
665
|
return this.scheduleNoteOn(channelNumber, noteNumber, velocity, now);
|
|
608
666
|
}
|
|
609
|
-
scheduleNoteRelease(channelNumber, noteNumber,
|
|
667
|
+
scheduleNoteRelease(channelNumber, noteNumber, _velocity, stopTime, stopPedal = false) {
|
|
610
668
|
const channel = this.channels[channelNumber];
|
|
611
669
|
if (stopPedal && channel.sustainPedal)
|
|
612
670
|
return;
|
|
@@ -619,20 +677,14 @@ export class MidyGM1 {
|
|
|
619
677
|
continue;
|
|
620
678
|
if (note.ending)
|
|
621
679
|
continue;
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
note.instrumentKey.volRelease * velocityRate;
|
|
625
|
-
note.gainNode.gain
|
|
680
|
+
const volEndTime = stopTime + note.instrumentKey.volRelease;
|
|
681
|
+
note.volumeNode.gain
|
|
626
682
|
.cancelScheduledValues(stopTime)
|
|
627
683
|
.linearRampToValueAtTime(0, volEndTime);
|
|
628
|
-
const
|
|
629
|
-
const baseFreq = this.centToHz(note.instrumentKey.initialFilterFc);
|
|
630
|
-
const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
|
|
631
|
-
const modEndTime = stopTime +
|
|
632
|
-
note.instrumentKey.modRelease * velocityRate;
|
|
684
|
+
const modRelease = stopTime + note.instrumentKey.modRelease;
|
|
633
685
|
note.filterNode.frequency
|
|
634
686
|
.cancelScheduledValues(stopTime)
|
|
635
|
-
.linearRampToValueAtTime(
|
|
687
|
+
.linearRampToValueAtTime(0, modRelease);
|
|
636
688
|
note.ending = true;
|
|
637
689
|
this.scheduleTask(() => {
|
|
638
690
|
note.bufferSource.loop = false;
|
|
@@ -641,15 +693,17 @@ export class MidyGM1 {
|
|
|
641
693
|
note.bufferSource.onended = () => {
|
|
642
694
|
scheduledNotes[i] = null;
|
|
643
695
|
note.bufferSource.disconnect();
|
|
696
|
+
note.volumeNode.disconnect();
|
|
644
697
|
note.filterNode.disconnect();
|
|
645
|
-
note.
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
698
|
+
if (note.volumeDepth)
|
|
699
|
+
note.volumeDepth.disconnect();
|
|
700
|
+
if (note.modulationDepth)
|
|
701
|
+
note.modulationDepth.disconnect();
|
|
702
|
+
if (note.modulationLFO)
|
|
703
|
+
note.modulationLFO.stop();
|
|
650
704
|
resolve();
|
|
651
705
|
};
|
|
652
|
-
bufferSource.stop(volEndTime);
|
|
706
|
+
note.bufferSource.stop(volEndTime);
|
|
653
707
|
});
|
|
654
708
|
}
|
|
655
709
|
}
|
|
@@ -662,14 +716,15 @@ export class MidyGM1 {
|
|
|
662
716
|
const channel = this.channels[channelNumber];
|
|
663
717
|
const promises = [];
|
|
664
718
|
channel.sustainPedal = false;
|
|
665
|
-
channel.scheduledNotes.forEach((
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
719
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
720
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
721
|
+
const note = noteList[i];
|
|
722
|
+
if (!note)
|
|
723
|
+
continue;
|
|
724
|
+
const { noteNumber } = note;
|
|
725
|
+
const promise = this.releaseNote(channelNumber, noteNumber, velocity);
|
|
726
|
+
promises.push(promise);
|
|
727
|
+
}
|
|
673
728
|
});
|
|
674
729
|
return promises;
|
|
675
730
|
}
|
|
@@ -710,7 +765,7 @@ export class MidyGM1 {
|
|
|
710
765
|
handleControlChange(channelNumber, controller, value) {
|
|
711
766
|
switch (controller) {
|
|
712
767
|
case 1:
|
|
713
|
-
return this.
|
|
768
|
+
return this.setModulationDepth(channelNumber, value);
|
|
714
769
|
case 6:
|
|
715
770
|
return this.dataEntryMSB(channelNumber, value);
|
|
716
771
|
case 7:
|
|
@@ -739,20 +794,25 @@ export class MidyGM1 {
|
|
|
739
794
|
}
|
|
740
795
|
updateModulation(channel) {
|
|
741
796
|
const now = this.audioContext.currentTime;
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
797
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
798
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
799
|
+
const note = noteList[i];
|
|
800
|
+
if (!note)
|
|
801
|
+
continue;
|
|
802
|
+
if (note.modulationDepth) {
|
|
803
|
+
note.modulationDepth.gain.setValueAtTime(channel.modulationDepth, now);
|
|
804
|
+
}
|
|
805
|
+
else {
|
|
806
|
+
const semitoneOffset = this.calcSemitoneOffset(channel);
|
|
807
|
+
this.setPitch(note, semitoneOffset);
|
|
808
|
+
this.startModulation(channel, note, now);
|
|
809
|
+
}
|
|
750
810
|
}
|
|
751
811
|
});
|
|
752
812
|
}
|
|
753
|
-
|
|
813
|
+
setModulationDepth(channelNumber, modulation) {
|
|
754
814
|
const channel = this.channels[channelNumber];
|
|
755
|
-
channel.
|
|
815
|
+
channel.modulationDepth = (modulation / 127) * channel.modulationDepthRange;
|
|
756
816
|
this.updateModulation(channel);
|
|
757
817
|
}
|
|
758
818
|
setVolume(channelNumber, volume) {
|
|
@@ -854,13 +914,17 @@ export class MidyGM1 {
|
|
|
854
914
|
}
|
|
855
915
|
updateDetune(channel, detuneChange) {
|
|
856
916
|
const now = this.audioContext.currentTime;
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
.
|
|
917
|
+
channel.scheduledNotes.forEach((noteList) => {
|
|
918
|
+
for (let i = 0; i < noteList.length; i++) {
|
|
919
|
+
const note = noteList[i];
|
|
920
|
+
if (!note)
|
|
921
|
+
continue;
|
|
922
|
+
const { bufferSource } = note;
|
|
923
|
+
const detune = bufferSource.detune.value + detuneChange;
|
|
924
|
+
bufferSource.detune
|
|
925
|
+
.cancelScheduledValues(now)
|
|
926
|
+
.setValueAtTime(detune, now);
|
|
927
|
+
}
|
|
864
928
|
});
|
|
865
929
|
}
|
|
866
930
|
handlePitchBendRangeRPN(channelNumber) {
|
|
@@ -904,37 +968,13 @@ export class MidyGM1 {
|
|
|
904
968
|
this.updateDetune(channel, detuneChange);
|
|
905
969
|
}
|
|
906
970
|
allSoundOff(channelNumber) {
|
|
907
|
-
|
|
908
|
-
const channel = this.channels[channelNumber];
|
|
909
|
-
const velocity = 0;
|
|
910
|
-
const stopPedal = true;
|
|
911
|
-
const promises = [];
|
|
912
|
-
channel.scheduledNotes.forEach((noteList) => {
|
|
913
|
-
const activeNote = this.getActiveNote(noteList, now);
|
|
914
|
-
if (activeNote) {
|
|
915
|
-
const notePromise = this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now, stopPedal);
|
|
916
|
-
promises.push(notePromise);
|
|
917
|
-
}
|
|
918
|
-
});
|
|
919
|
-
return promises;
|
|
971
|
+
return this.stopChannelNotes(channelNumber, 0, true);
|
|
920
972
|
}
|
|
921
973
|
resetAllControllers(channelNumber) {
|
|
922
974
|
Object.assign(this.channels[channelNumber], this.effectSettings);
|
|
923
975
|
}
|
|
924
976
|
allNotesOff(channelNumber) {
|
|
925
|
-
|
|
926
|
-
const channel = this.channels[channelNumber];
|
|
927
|
-
const velocity = 0;
|
|
928
|
-
const stopPedal = false;
|
|
929
|
-
const promises = [];
|
|
930
|
-
channel.scheduledNotes.forEach((noteList) => {
|
|
931
|
-
const activeNote = this.getActiveNote(noteList, now);
|
|
932
|
-
if (activeNote) {
|
|
933
|
-
const notePromise = this.scheduleNoteRelease(channelNumber, activeNote.noteNumber, velocity, now, stopPedal);
|
|
934
|
-
promises.push(notePromise);
|
|
935
|
-
}
|
|
936
|
-
});
|
|
937
|
-
return promises;
|
|
977
|
+
return this.stopChannelNotes(channelNumber, 0, false);
|
|
938
978
|
}
|
|
939
979
|
handleUniversalNonRealTimeExclusiveMessage(data) {
|
|
940
980
|
switch (data[2]) {
|
|
@@ -1029,7 +1069,7 @@ Object.defineProperty(MidyGM1, "channelSettings", {
|
|
|
1029
1069
|
pitchBend: 0,
|
|
1030
1070
|
fineTuning: 0, // cb
|
|
1031
1071
|
coarseTuning: 0, // cb
|
|
1032
|
-
modulationDepthRange:
|
|
1072
|
+
modulationDepthRange: 50, // cent
|
|
1033
1073
|
}
|
|
1034
1074
|
});
|
|
1035
1075
|
Object.defineProperty(MidyGM1, "effectSettings", {
|
|
@@ -1038,7 +1078,7 @@ Object.defineProperty(MidyGM1, "effectSettings", {
|
|
|
1038
1078
|
writable: true,
|
|
1039
1079
|
value: {
|
|
1040
1080
|
expression: 1,
|
|
1041
|
-
|
|
1081
|
+
modulationDepth: 0,
|
|
1042
1082
|
sustainPedal: false,
|
|
1043
1083
|
rpnMSB: 127,
|
|
1044
1084
|
rpnLSB: 127,
|
package/esm/midy-GM2.d.ts
CHANGED
|
@@ -6,6 +6,9 @@ export class MidyGM2 {
|
|
|
6
6
|
portamentoTime: number;
|
|
7
7
|
reverbSendLevel: number;
|
|
8
8
|
chorusSendLevel: number;
|
|
9
|
+
vibratoRate: number;
|
|
10
|
+
vibratoDepth: number;
|
|
11
|
+
vibratoDelay: number;
|
|
9
12
|
bank: number;
|
|
10
13
|
bankMSB: number;
|
|
11
14
|
bankLSB: number;
|
|
@@ -19,7 +22,7 @@ export class MidyGM2 {
|
|
|
19
22
|
};
|
|
20
23
|
static effectSettings: {
|
|
21
24
|
expression: number;
|
|
22
|
-
|
|
25
|
+
modulationDepth: number;
|
|
23
26
|
sustainPedal: boolean;
|
|
24
27
|
portamento: boolean;
|
|
25
28
|
sostenutoPedal: boolean;
|
|
@@ -125,7 +128,8 @@ export class MidyGM2 {
|
|
|
125
128
|
instruments: Set<any>;
|
|
126
129
|
timeline: any[];
|
|
127
130
|
};
|
|
128
|
-
|
|
131
|
+
stopChannelNotes(channelNumber: any, velocity: any, stopPedal: any): Promise<void>;
|
|
132
|
+
stopNotes(velocity: any, stopPedal: any): Promise<any[]>;
|
|
129
133
|
start(): Promise<void>;
|
|
130
134
|
stop(): void;
|
|
131
135
|
pause(): void;
|
|
@@ -162,25 +166,28 @@ export class MidyGM2 {
|
|
|
162
166
|
calcSemitoneOffset(channel: any): any;
|
|
163
167
|
calcPlaybackRate(instrumentKey: any, noteNumber: any, semitoneOffset: any): number;
|
|
164
168
|
setVolumeEnvelope(note: any): void;
|
|
169
|
+
setPitch(note: any, semitoneOffset: any): void;
|
|
170
|
+
clampCutoffFrequency(frequency: any): number;
|
|
165
171
|
setFilterEnvelope(channel: any, note: any): void;
|
|
166
|
-
startModulation(channel: any, note: any,
|
|
172
|
+
startModulation(channel: any, note: any, startTime: any): void;
|
|
173
|
+
startVibrato(channel: any, note: any, startTime: any): void;
|
|
167
174
|
createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
|
|
168
175
|
calcBank(channel: any, channelNumber: any): any;
|
|
169
176
|
scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
|
|
170
177
|
noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
|
|
171
|
-
scheduleNoteRelease(channelNumber: any, noteNumber: any,
|
|
178
|
+
scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, stopTime: any, stopPedal?: boolean): Promise<any> | undefined;
|
|
172
179
|
releaseNote(channelNumber: any, noteNumber: any, velocity: any): Promise<any> | undefined;
|
|
173
180
|
releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
|
|
174
181
|
releaseSostenutoPedal(channelNumber: any, halfVelocity: any): any[];
|
|
175
|
-
handleMIDIMessage(statusByte: any, data1: any, data2: any): void |
|
|
182
|
+
handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
|
|
176
183
|
handleProgramChange(channelNumber: any, program: any): void;
|
|
177
184
|
handleChannelPressure(channelNumber: any, pressure: any): void;
|
|
178
185
|
handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
|
|
179
186
|
setPitchBend(channelNumber: any, pitchBend: any): void;
|
|
180
|
-
handleControlChange(channelNumber: any, controller: any, value: any): void |
|
|
187
|
+
handleControlChange(channelNumber: any, controller: any, value: any): void | Promise<void>;
|
|
181
188
|
setBankMSB(channelNumber: any, msb: any): void;
|
|
182
189
|
updateModulation(channel: any): void;
|
|
183
|
-
|
|
190
|
+
setModulationDepth(channelNumber: any, modulation: any): void;
|
|
184
191
|
setPortamentoTime(channelNumber: any, portamentoTime: any): void;
|
|
185
192
|
setVolume(channelNumber: any, volume: any): void;
|
|
186
193
|
panToGain(pan: any): {
|
|
@@ -213,9 +220,9 @@ export class MidyGM2 {
|
|
|
213
220
|
setCoarseTuning(channelNumber: any, coarseTuning: any): void;
|
|
214
221
|
handleModulationDepthRangeRPN(channelNumber: any): void;
|
|
215
222
|
setModulationDepthRange(channelNumber: any, modulationDepthRange: any): void;
|
|
216
|
-
allSoundOff(channelNumber: any):
|
|
223
|
+
allSoundOff(channelNumber: any): Promise<void>;
|
|
217
224
|
resetAllControllers(channelNumber: any): void;
|
|
218
|
-
allNotesOff(channelNumber: any):
|
|
225
|
+
allNotesOff(channelNumber: any): Promise<void>;
|
|
219
226
|
omniOff(): void;
|
|
220
227
|
omniOn(): void;
|
|
221
228
|
monoOn(): void;
|
|
@@ -255,12 +262,13 @@ export class MidyGM2 {
|
|
|
255
262
|
declare class Note {
|
|
256
263
|
constructor(noteNumber: any, velocity: any, startTime: any, instrumentKey: any);
|
|
257
264
|
bufferSource: any;
|
|
258
|
-
gainNode: any;
|
|
259
265
|
filterNode: any;
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
266
|
+
volumeNode: any;
|
|
267
|
+
volumeDepth: any;
|
|
268
|
+
modulationLFO: any;
|
|
269
|
+
modulationDepth: any;
|
|
270
|
+
vibratoLFO: any;
|
|
271
|
+
vibratoDepth: any;
|
|
264
272
|
noteNumber: any;
|
|
265
273
|
velocity: any;
|
|
266
274
|
startTime: any;
|
package/esm/midy-GM2.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"AAwBA;IAkCE;;;;;;;;;;;;;;;;;;;;MAoBE;IAEF;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAgCF;;;;;OAWC;IAtHD,qBAAmB;IACnB,kBAAc;IACd,yBAAqB;IACrB,2BAAuB;IACvB;;;MAGE;IACF;;;;;;MAME;IACF,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;IA8ClB;;;;;MA4BE;IAGA,kBAAgC;IAChC;;;;;MAAqD;IACrD,gBAA4C;IAC5C,gBAAiD;IACjD;;;MAA8D;IAC9D;;;;;;;;MAAyD;IAO3D,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAcC;IAED,+DAyBC;IAED,mEAWC;IAED,qDAOC;IAED,2EAkDC;IAED,mCAOC;IAED,0BA+CC;IAED,uDAEC;IAED,wDAEC;IAED;;;MAgGC;IAED,mFAmBC;IAED,yDAKC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED,kFAuBC;IAED;;;;MAWC;IAED,gFAUC;IAED,mFAYC;IAED,sGAcC;IAID;;;MA+BC;IAED;;;;;;;;MA0CC;IAED,2BAEC;IAED,4BAEC;IAED,sCAKC;IAED,mFAGC;IAED,mCAeC;IAED,+CAwBC;IAED,6CAIC;IAED,iDAyBC;IAED,+DA0BC;IAED,4DAiBC;IAED,wHA0CC;IAED,gDAQC;IAED,kGAgCC;IAED,0EAGC;IAED,uIA4CC;IAED,0FAGC;IAED,kEAeC;IAED,oEAYC;IAED,gFAmBC;IAED,4DAIC;IAED,+DAcC;IAED,qEAGC;IAED,uDAOC;IAED,2FAuDC;IAED,+CAEC;IAED,qCAkBC;IAED,8DAIC;IAED,iEAEC;IAED,iDAIC;IAED;;;MAMC;IAED,2CAIC;IAED,yDAIC;IAED,+CAEC;IAED,mDAGC;IAED,sCAUC;IAED,sDAMC;IAGD,oDAEC;IAED,mEAWC;IAED,mEAWC;IAED,wDAWC;IAED,uDAGC;IAED,kFAeC;IAED,2DAMC;IAED,oCAqBC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,oDAaC;IAED,kDAKC;IAED,iEAOC;IAED,8CAKC;IAED,yDAMC;IAED,gDAKC;IAED,6DAMC;IAED,wDAKC;IAED,6EAKC;IAED,+CAEC;IAED,8CAEC;IAED,+CAEC;IAED,gBAEC;IAED,eAEC;IAED,eAEC;IAED,eAEC;IAED,4DAmBC;IAED,oBAQC;IAED,oBAQC;IAED,yDAiDC;IAED,yCAGC;IAED,mCAQC;IAED,6CAGC;IAED,2CAMC;IAED,+CAGC;IAED,+CAMC;IAED,mDAeC;IAED,4CAOC;IAED,+BAKC;IAED,qDAiBC;IAED,gCAMC;IAED,kCAEC;IA6BD,4CAEC;IAED,4CAaC;IAED,+BAiBC;IAED,wFAKC;IAED,mCAQC;IAED,qCAEC;IAED,oCAUC;IAED,sCAEC;IAED,oCAaC;IAED,sCAEC;IAED,wCAWC;IAED,0CAEC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAhyDD;IAUE,gFAKC;IAdD,kBAAa;IACb,gBAAW;IACX,gBAAW;IACX,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAChB,gBAAW;IACX,kBAAa;IAGX,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
|