@marmooo/midy 0.0.4 → 0.0.5

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.
Files changed (33) hide show
  1. package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/{soundfont-parser@0.0.1 → soundfont-parser@0.0.2}/+esm.d.ts +13 -6
  2. package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.d.ts.map +1 -0
  3. package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/{soundfont-parser@0.0.1 → soundfont-parser@0.0.2}/+esm.js +5 -5
  4. package/esm/midy-GM1.d.ts +24 -34
  5. package/esm/midy-GM1.d.ts.map +1 -1
  6. package/esm/midy-GM1.js +167 -106
  7. package/esm/midy-GM2.d.ts +123 -21
  8. package/esm/midy-GM2.d.ts.map +1 -1
  9. package/esm/midy-GM2.js +170 -116
  10. package/esm/midy-GMLite.d.ts +23 -35
  11. package/esm/midy-GMLite.d.ts.map +1 -1
  12. package/esm/midy-GMLite.js +156 -107
  13. package/esm/midy.d.ts +25 -23
  14. package/esm/midy.d.ts.map +1 -1
  15. package/esm/midy.js +191 -120
  16. package/package.json +1 -1
  17. package/script/deps/cdn.jsdelivr.net/npm/@marmooo/{soundfont-parser@0.0.1 → soundfont-parser@0.0.2}/+esm.d.ts +13 -6
  18. package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.d.ts.map +1 -0
  19. package/script/deps/cdn.jsdelivr.net/npm/@marmooo/{soundfont-parser@0.0.1 → soundfont-parser@0.0.2}/+esm.js +5 -5
  20. package/script/midy-GM1.d.ts +24 -34
  21. package/script/midy-GM1.d.ts.map +1 -1
  22. package/script/midy-GM1.js +167 -106
  23. package/script/midy-GM2.d.ts +123 -21
  24. package/script/midy-GM2.d.ts.map +1 -1
  25. package/script/midy-GM2.js +170 -116
  26. package/script/midy-GMLite.d.ts +23 -35
  27. package/script/midy-GMLite.d.ts.map +1 -1
  28. package/script/midy-GMLite.js +156 -107
  29. package/script/midy.d.ts +25 -23
  30. package/script/midy.d.ts.map +1 -1
  31. package/script/midy.js +191 -120
  32. package/esm/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.1/+esm.d.ts.map +0 -1
  33. package/script/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.1/+esm.d.ts.map +0 -1
@@ -12,7 +12,14 @@ declare class F {
12
12
  sampleName: any;
13
13
  sampleModes: number;
14
14
  playbackRate: (e: any) => number;
15
+ modLfoToPitch: number;
16
+ vibLfoToPitch: number;
15
17
  modEnvToPitch: number;
18
+ initialFilterFc: number;
19
+ initialFilterQ: number;
20
+ modLfoToFilterFc: number;
21
+ modEnvToFilterFc: number;
22
+ modLfoToVolume: number;
16
23
  scaleTuning: number;
17
24
  start: number;
18
25
  end: number;
@@ -32,12 +39,12 @@ declare class F {
32
39
  modRelease: number;
33
40
  keyRange: d;
34
41
  velRange: d;
35
- initialFilterFc: number;
36
- modEnvToFilterFc: number;
37
- initialFilterQ: number;
42
+ delayModLFO: number;
43
+ freqModLFO: number;
44
+ delayVibLFO: number;
45
+ freqVibLFO: number;
38
46
  initialAttenuation: number;
39
- freqVibLFO: number | undefined;
40
- pan: undefined;
47
+ pan: number;
41
48
  } | null;
42
49
  getPresetNames(): {};
43
50
  }
@@ -95,7 +102,7 @@ declare namespace T {
95
102
  let initialFilterQ: number;
96
103
  let initialFilterFc: number;
97
104
  let sampleModes: number;
98
- let pan: undefined;
105
+ let pan: number;
99
106
  }
100
107
  declare function b(e: any, n?: {}): {
101
108
  samples: any;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"+esm.d.ts","sourceRoot":"","sources":["../../../../../../src/deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.js"],"names":[],"mappings":";;AAMizX;IAAQ,oBAA2H;IAAd,YAAa;IAAC,qDAAoJ;IAAA,mCAAoP;IAAA,uCAAwQ;IAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAAkqE;IAAA,qBAA0I;CAAC;AAAA,mCAAwC;AAA9oI,+BAA8F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAA98D;;;;;;;;;;;;;;;;EAA27B;AAAr4I;IAAqQ,wBAAwD;IAArT,4BAAyN;IAApB,QAAS;IAAC,QAAS;IAAC,oBAAoC;CAAyD;AAAllG;IAAwjC,gCAA8d;CAAC"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Bundled by jsDelivr using Rollup v2.79.2 and Terser v5.37.0.
3
- * Original file: /npm/@marmooo/soundfont-parser@0.0.1/esm/mod.js
3
+ * Original file: /npm/@marmooo/soundfont-parser@0.0.2/esm/mod.js
4
4
  *
5
5
  * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
6
6
  */
@@ -108,7 +108,7 @@ function I(e) { const t = {}; for (const r of e) {
108
108
  const e = r.type;
109
109
  void 0 !== e && (t[e] = r.value);
110
110
  } return t; }
111
- const T = { keynum: void 0, instrument: void 0, velocity: void 0, exclusiveClass: void 0, keyRange: new d(0, 127), velRange: new d(0, 127), sampleID: void 0, delayVolEnv: -12e3, attackVolEnv: -12e3, decayVolEnv: -12e3, holdVolEnv: -12e3, sustainVolEnv: 0, releaseVolEnv: -12e3, delayModEnv: -12e3, attackModEnv: -12e3, decayModEnv: -12e3, holdModEnv: -12e3, sustainModEnv: 0, releaseModEnv: -12e3, modEnvToPitch: 0, modEnvToFilterFc: 0, modLfoToFilterFc: 0, modLfoToPitch: 0, modLfoToVolume: 0, vibLfoToPitch: 0, chorusEffectsSend: 0, reverbEffectsSend: 0, delayModLFO: 0, freqModLFO: 0, delayVibLFO: 0, keynumToModEnvDecay: 0, keynumToModEnvHold: 0, keynumToVolEnvDecay: 0, keynumToVolEnvHold: 0, coarseTune: 0, fineTune: 0, scaleTuning: 100, freqVibLFO: 0, startAddrsOffset: 0, startAddrsCoarseOffset: 0, endAddrsOffset: 0, endAddrsCoarseOffset: 0, startloopAddrsOffset: 0, startloopAddrsCoarseOffset: 0, initialAttenuation: 0, endloopAddrsOffset: 0, endloopAddrsCoarseOffset: 0, overridingRootKey: void 0, initialFilterQ: 1, initialFilterFc: 13500, sampleModes: 0, pan: void 0 };
111
+ const T = { keynum: void 0, instrument: void 0, velocity: void 0, exclusiveClass: void 0, keyRange: new d(0, 127), velRange: new d(0, 127), sampleID: void 0, delayVolEnv: -12e3, attackVolEnv: -12e3, decayVolEnv: -12e3, holdVolEnv: -12e3, sustainVolEnv: 0, releaseVolEnv: -12e3, delayModEnv: -12e3, attackModEnv: -12e3, decayModEnv: -12e3, holdModEnv: -12e3, sustainModEnv: 0, releaseModEnv: -12e3, modEnvToPitch: 0, modEnvToFilterFc: 0, modLfoToFilterFc: 0, modLfoToPitch: 0, modLfoToVolume: 0, vibLfoToPitch: 0, chorusEffectsSend: 0, reverbEffectsSend: 0, delayModLFO: 0, freqModLFO: 0, delayVibLFO: 0, keynumToModEnvDecay: 0, keynumToModEnvHold: 0, keynumToVolEnvDecay: 0, keynumToVolEnvHold: 0, coarseTune: 0, fineTune: 0, scaleTuning: 100, freqVibLFO: 0, startAddrsOffset: 0, startAddrsCoarseOffset: 0, endAddrsOffset: 0, endAddrsCoarseOffset: 0, startloopAddrsOffset: 0, startloopAddrsCoarseOffset: 0, initialAttenuation: 0, endloopAddrsOffset: 0, endloopAddrsCoarseOffset: 0, overridingRootKey: void 0, initialFilterQ: 1, initialFilterFc: 13500, sampleModes: 0, pan: 0 };
112
112
  class F {
113
113
  constructor(e) { Object.defineProperty(this, "parsed", { enumerable: !0, configurable: !0, writable: !0, value: void 0 }), this.parsed = e; }
114
114
  getGenerators(e, t, r, n) { const a = new Array(n - r); for (let i = r; i < n; i++) {
@@ -144,12 +144,12 @@ class F {
144
144
  break;
145
145
  } if (!l)
146
146
  return console.warn("instrument not found: bank=%s instrument=%s", e, t), null; if (void 0 === l.sampleID)
147
- throw new Error("Invalid SoundFont: sampleID not found"); const d = { ...T, ...A(o || {}), ...A(s || {}), ...A(l) }, u = this.parsed.samples[d.sampleID], c = this.parsed.sampleHeaders[d.sampleID], f = d.coarseTune + d.fineTune / 100 + c.pitchCorrection / 100 - (d.overridingRootKey || c.originalPitch), p = d.scaleTuning / 100; return { sample: u, sampleRate: c.sampleRate, sampleName: c.sampleName, sampleModes: d.sampleModes, playbackRate: e => Math.pow(Math.pow(2, 1 / 12), (e + f) * p), modEnvToPitch: d.modEnvToPitch / 100, scaleTuning: p, start: 32768 * d.startAddrsCoarseOffset + d.startAddrsOffset, end: 32768 * d.endAddrsCoarseOffset + d.endAddrsOffset, loopStart: c.loopStart + 32768 * d.startloopAddrsCoarseOffset + d.startloopAddrsOffset, loopEnd: c.loopEnd + 32768 * d.endloopAddrsCoarseOffset + d.endloopAddrsOffset, volDelay: M(d.delayVolEnv), volAttack: M(d.attackVolEnv), volHold: M(d.holdVolEnv), volDecay: M(d.decayVolEnv), volSustain: d.sustainVolEnv / 1e3, volRelease: M(d.releaseVolEnv), modDelay: M(d.delayModEnv), modAttack: M(d.attackModEnv), modHold: M(d.holdModEnv), modDecay: M(d.decayModEnv), modSustain: d.sustainModEnv / 1e3, modRelease: M(d.releaseModEnv), keyRange: d.keyRange, velRange: d.velRange, initialFilterFc: d.initialFilterFc, modEnvToFilterFc: d.modEnvToFilterFc, initialFilterQ: d.initialFilterQ, initialAttenuation: d.initialAttenuation, freqVibLFO: d.freqVibLFO ? 8.176 * M(d.freqVibLFO) : void 0, pan: d.pan }; }
147
+ throw new Error("Invalid SoundFont: sampleID not found"); const d = { ...T, ...L(o || {}), ...L(s || {}), ...L(l) }, u = this.parsed.samples[d.sampleID], c = this.parsed.sampleHeaders[d.sampleID], f = d.coarseTune + d.fineTune / 100 + c.pitchCorrection / 100 - (d.overridingRootKey || c.originalPitch), p = d.scaleTuning / 100; return { sample: u, sampleRate: c.sampleRate, sampleName: c.sampleName, sampleModes: d.sampleModes, playbackRate: e => Math.pow(Math.pow(2, 1 / 12), (e + f) * p), modLfoToPitch: d.modLfoToPitch, vibLfoToPitch: d.vibLfoToPitch, modEnvToPitch: d.modEnvToPitch, initialFilterFc: d.initialFilterFc, initialFilterQ: d.initialFilterQ, modLfoToFilterFc: d.modLfoToFilterFc, modEnvToFilterFc: d.modEnvToFilterFc, modLfoToVolume: d.modLfoToVolume, scaleTuning: p, start: 32768 * d.startAddrsCoarseOffset + d.startAddrsOffset, end: 32768 * d.endAddrsCoarseOffset + d.endAddrsOffset, loopStart: c.loopStart + 32768 * d.startloopAddrsCoarseOffset + d.startloopAddrsOffset, loopEnd: c.loopEnd + 32768 * d.endloopAddrsCoarseOffset + d.endloopAddrsOffset, volDelay: M(d.delayVolEnv), volAttack: M(d.attackVolEnv), volHold: M(d.holdVolEnv), volDecay: M(d.decayVolEnv), volSustain: d.sustainVolEnv / 1e3, volRelease: M(d.releaseVolEnv), modDelay: M(d.delayModEnv), modAttack: M(d.attackModEnv), modHold: M(d.holdModEnv), modDecay: M(d.decayModEnv), modSustain: d.sustainModEnv / 1e3, modRelease: M(d.releaseModEnv), keyRange: d.keyRange, velRange: d.velRange, delayModLFO: M(d.delayModLFO), freqModLFO: d.freqModLFO, delayVibLFO: M(d.delayVibLFO), freqVibLFO: d.freqVibLFO, initialAttenuation: d.initialAttenuation, pan: d.pan }; }
148
148
  getPresetNames() { const e = {}; return this.parsed.presetHeaders.forEach((t => { e[t.bank] || (e[t.bank] = {}), e[t.bank][t.preset] = t.presetName; })), e; }
149
149
  }
150
150
  function M(e) { return Math.pow(2, e / 1200); }
151
- function A(e) { const t = {}; for (const r in e)
151
+ function L(e) { const t = {}; for (const r in e)
152
152
  void 0 !== e[r] && (t[r] = e[r]); return t; }
153
153
  export { F as SoundFont, M as convertTime, I as createGeneratorObject, T as defaultInstrumentZone, b as parse };
154
154
  export default null;
155
- //# sourceMappingURL=/sm/f81f37edef0ee7c3c75f39a74df8b8e54ea144490d686e35430b76b426f1559d.map
155
+ //# sourceMappingURL=/sm/22d03ff23e99217677631c656a57eea14149d50ae4425cf6cd850760c3e93c1e.map
package/esm/midy-GM1.d.ts CHANGED
@@ -2,9 +2,6 @@ export class MidyGM1 {
2
2
  static channelSettings: {
3
3
  volume: number;
4
4
  pan: number;
5
- vibratoRate: number;
6
- vibratoDepth: number;
7
- vibratoDelay: number;
8
5
  bank: number;
9
6
  dataMSB: number;
10
7
  dataLSB: number;
@@ -44,12 +41,8 @@ export class MidyGM1 {
44
41
  masterGain: any;
45
42
  channels: {
46
43
  scheduledNotes: Map<any, any>;
47
- sostenutoNotes: Map<any, any>;
48
44
  gainNode: any;
49
45
  pannerNode: any;
50
- modulationEffect: {
51
- lfo: any;
52
- };
53
46
  expression: number;
54
47
  modulation: number;
55
48
  sustainPedal: boolean;
@@ -58,9 +51,6 @@ export class MidyGM1 {
58
51
  pitchBendRange: number;
59
52
  volume: number;
60
53
  pan: number;
61
- vibratoRate: number;
62
- vibratoDepth: number;
63
- vibratoDelay: number;
64
54
  bank: number;
65
55
  dataMSB: number;
66
56
  dataLSB: number;
@@ -77,18 +67,11 @@ export class MidyGM1 {
77
67
  setChannelAudioNodes(audioContext: any): {
78
68
  gainNode: any;
79
69
  pannerNode: any;
80
- modulationEffect: {
81
- lfo: any;
82
- };
83
70
  };
84
71
  createChannels(audioContext: any): {
85
72
  scheduledNotes: Map<any, any>;
86
- sostenutoNotes: Map<any, any>;
87
73
  gainNode: any;
88
74
  pannerNode: any;
89
- modulationEffect: {
90
- lfo: any;
91
- };
92
75
  expression: number;
93
76
  modulation: number;
94
77
  sustainPedal: boolean;
@@ -97,9 +80,6 @@ export class MidyGM1 {
97
80
  pitchBendRange: number;
98
81
  volume: number;
99
82
  pan: number;
100
- vibratoRate: number;
101
- vibratoDepth: number;
102
- vibratoDelay: number;
103
83
  bank: number;
104
84
  dataMSB: number;
105
85
  dataLSB: number;
@@ -109,8 +89,8 @@ export class MidyGM1 {
109
89
  coarseTuning: number;
110
90
  modulationDepthRange: number;
111
91
  }[];
112
- createNoteBuffer(noteInfo: any, isSF3: any): Promise<any>;
113
- createNoteBufferNode(noteInfo: any, isSF3: any): Promise<any>;
92
+ createNoteBuffer(instrumentKey: any, isSF3: any): Promise<any>;
93
+ createNoteBufferNode(instrumentKey: any, isSF3: any): Promise<any>;
114
94
  convertToFloat32Array(uint8Array: any): Float32Array;
115
95
  scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
116
96
  getQueueIndex(second: any): number;
@@ -129,22 +109,17 @@ export class MidyGM1 {
129
109
  seekTo(second: any): void;
130
110
  calcTotalTime(): number;
131
111
  currentTime(): number;
132
- getActiveNotes(channel: any): Map<any, any>;
133
- getActiveChannelNotes(scheduledNotes: any): any;
134
- createModulationEffect(audioContext: any): {
135
- lfo: any;
136
- };
112
+ getActiveNotes(channel: any, time: any): Map<any, any>;
113
+ getActiveNote(noteList: any, time: any): any;
137
114
  connectNoteEffects(channel: any, gainNode: any): void;
138
115
  cbToRatio(cb: any): number;
139
116
  centToHz(cent: any): number;
140
117
  calcSemitoneOffset(channel: any): any;
141
- calcPlaybackRate(noteInfo: any, noteNumber: any, semitoneOffset: any): number;
142
- createNoteAudioChain(channel: any, noteInfo: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<{
143
- bufferSource: any;
144
- gainNode: any;
145
- filterNode: any;
146
- lfoGain: any;
147
- }>;
118
+ calcPlaybackRate(instrumentKey: any, noteNumber: any, semitoneOffset: any): number;
119
+ setVolumeEnvelope(channel: any, note: any): void;
120
+ setFilterEnvelope(channel: any, note: any): void;
121
+ startModulation(channel: any, note: any, time: any): void;
122
+ createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
148
123
  scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
149
124
  noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
150
125
  scheduleNoteRelease(channelNumber: any, noteNumber: any, velocity: any, stopTime: any, stopPedal?: boolean): Promise<any> | undefined;
@@ -176,4 +151,19 @@ export class MidyGM1 {
176
151
  handleSysEx(data: any): void;
177
152
  scheduleTask(callback: any, startTime: any): Promise<any>;
178
153
  }
154
+ declare class Note {
155
+ constructor(noteNumber: any, velocity: any, startTime: any, instrumentKey: any);
156
+ bufferSource: any;
157
+ gainNode: any;
158
+ filterNode: any;
159
+ modLFO: any;
160
+ modLFOGain: any;
161
+ vibLFO: any;
162
+ vibLFOGain: any;
163
+ noteNumber: any;
164
+ velocity: any;
165
+ startTime: any;
166
+ instrumentKey: any;
167
+ }
168
+ export {};
179
169
  //# sourceMappingURL=midy-GM1.d.ts.map
@@ -1 +1 @@
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,2EA+CC;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,sCAGC;IAED,8EAEC;IAED;;;;;OA8EC;IAED,kGAuCC;IAED,0EAGC;IAED,sIA4CC;IAED,0FAGC;IAED,kEAeC;IAED,wFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,0DAiBC;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,sCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF"}
1
+ {"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"AAuBA;IAmBE;;;;;;;;;;;MAWE;IAEF;;;;;;;MAOE;IAEF,+BAMC;IA9CD,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;IAyBhB,kBAAgC;IAChC,gBAA4C;IAE5C;;;;;;;;;;;;;;;;;;;;QAAiD;IAInD,4BAMC;IAED,mCASC;IAED,gDAMC;IAED,sCASC;IAED;;;MAaC;IAED;;;;;;;;;;;;;;;;;;;;QAUC;IAED,+DAyBC;IAED,mEAWC;IAED,qDAOC;IAED,2EA+CC;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,uDASC;IAED,6CAQC;IAED,sDAEC;IAED,2BAEC;IAED,4BAEC;IAED,sCAGC;IAED,mFAGC;IAED,iDAmBC;IAED,iDAiCC;IAED,0DAmBC;IAED,wHA6BC;IAED,kGA6BC;IAED,0EAGC;IAED,sIAmDC;IAED,0FAGC;IAED,kEAeC;IAED,wFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,0DAiBC;IAED,mFA+BC;IAED,yDAiBC;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,sCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAv+BD;IASE,gFAKC;IAbD,kBAAa;IACb,cAAS;IACT,gBAAW;IACX,YAAO;IACP,gBAAW;IACX,YAAO;IACP,gBAAW;IAGT,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,mBAAkC;CAErC"}
package/esm/midy-GM1.js CHANGED
@@ -1,5 +1,55 @@
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.1/+esm.js";
2
+ import { parse, SoundFont, } from "./deps/cdn.jsdelivr.net/npm/@marmooo/soundfont-parser@0.0.2/+esm.js";
3
+ class Note {
4
+ constructor(noteNumber, velocity, startTime, instrumentKey) {
5
+ Object.defineProperty(this, "bufferSource", {
6
+ enumerable: true,
7
+ configurable: true,
8
+ writable: true,
9
+ value: void 0
10
+ });
11
+ Object.defineProperty(this, "gainNode", {
12
+ enumerable: true,
13
+ configurable: true,
14
+ writable: true,
15
+ value: void 0
16
+ });
17
+ Object.defineProperty(this, "filterNode", {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value: void 0
22
+ });
23
+ Object.defineProperty(this, "modLFO", {
24
+ enumerable: true,
25
+ configurable: true,
26
+ writable: true,
27
+ value: void 0
28
+ });
29
+ Object.defineProperty(this, "modLFOGain", {
30
+ enumerable: true,
31
+ configurable: true,
32
+ writable: true,
33
+ value: void 0
34
+ });
35
+ Object.defineProperty(this, "vibLFO", {
36
+ enumerable: true,
37
+ configurable: true,
38
+ writable: true,
39
+ value: void 0
40
+ });
41
+ Object.defineProperty(this, "vibLFOGain", {
42
+ enumerable: true,
43
+ configurable: true,
44
+ writable: true,
45
+ value: void 0
46
+ });
47
+ this.noteNumber = noteNumber;
48
+ this.velocity = velocity;
49
+ this.startTime = startTime;
50
+ this.instrumentKey = instrumentKey;
51
+ }
52
+ }
3
53
  export class MidyGM1 {
4
54
  constructor(audioContext) {
5
55
  Object.defineProperty(this, "ticksPerBeat", {
@@ -151,14 +201,11 @@ export class MidyGM1 {
151
201
  const pannerNode = new StereoPannerNode(audioContext, {
152
202
  pan: MidyGM1.channelSettings.pan,
153
203
  });
154
- const modulationEffect = this.createModulationEffect(audioContext);
155
- modulationEffect.lfo.start();
156
204
  pannerNode.connect(gainNode);
157
205
  gainNode.connect(this.masterGain);
158
206
  return {
159
207
  gainNode,
160
208
  pannerNode,
161
- modulationEffect,
162
209
  };
163
210
  }
164
211
  createChannels(audioContext) {
@@ -168,16 +215,15 @@ export class MidyGM1 {
168
215
  ...MidyGM1.effectSettings,
169
216
  ...this.setChannelAudioNodes(audioContext),
170
217
  scheduledNotes: new Map(),
171
- sostenutoNotes: new Map(),
172
218
  };
173
219
  });
174
220
  return channels;
175
221
  }
176
- async createNoteBuffer(noteInfo, isSF3) {
177
- const sampleEnd = noteInfo.sample.length + noteInfo.end;
222
+ async createNoteBuffer(instrumentKey, isSF3) {
223
+ const sampleEnd = instrumentKey.sample.length + instrumentKey.end;
178
224
  if (isSF3) {
179
- const sample = new Uint8Array(noteInfo.sample.length);
180
- sample.set(noteInfo.sample);
225
+ const sample = new Uint8Array(instrumentKey.sample.length);
226
+ sample.set(instrumentKey.sample);
181
227
  const audioBuffer = await this.audioContext.decodeAudioData(sample.buffer);
182
228
  for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) {
183
229
  const channelData = audioBuffer.getChannelData(channel);
@@ -186,26 +232,27 @@ export class MidyGM1 {
186
232
  return audioBuffer;
187
233
  }
188
234
  else {
189
- const sample = noteInfo.sample.subarray(0, sampleEnd);
235
+ const sample = instrumentKey.sample.subarray(0, sampleEnd);
190
236
  const floatSample = this.convertToFloat32Array(sample);
191
237
  const audioBuffer = new AudioBuffer({
192
238
  numberOfChannels: 1,
193
239
  length: sample.length,
194
- sampleRate: noteInfo.sampleRate,
240
+ sampleRate: instrumentKey.sampleRate,
195
241
  });
196
242
  const channelData = audioBuffer.getChannelData(0);
197
243
  channelData.set(floatSample);
198
244
  return audioBuffer;
199
245
  }
200
246
  }
201
- async createNoteBufferNode(noteInfo, isSF3) {
247
+ async createNoteBufferNode(instrumentKey, isSF3) {
202
248
  const bufferSource = new AudioBufferSourceNode(this.audioContext);
203
- const audioBuffer = await this.createNoteBuffer(noteInfo, isSF3);
249
+ const audioBuffer = await this.createNoteBuffer(instrumentKey, isSF3);
204
250
  bufferSource.buffer = audioBuffer;
205
- bufferSource.loop = noteInfo.sampleModes % 2 !== 0;
251
+ bufferSource.loop = instrumentKey.sampleModes % 2 !== 0;
206
252
  if (bufferSource.loop) {
207
- bufferSource.loopStart = noteInfo.loopStart / noteInfo.sampleRate;
208
- bufferSource.loopEnd = noteInfo.loopEnd / noteInfo.sampleRate;
253
+ bufferSource.loopStart = instrumentKey.loopStart /
254
+ instrumentKey.sampleRate;
255
+ bufferSource.loopEnd = instrumentKey.loopEnd / instrumentKey.sampleRate;
209
256
  }
210
257
  return bufferSource;
211
258
  }
@@ -447,30 +494,26 @@ export class MidyGM1 {
447
494
  const now = this.audioContext.currentTime;
448
495
  return this.resumeTime + now - this.startTime - this.startDelay;
449
496
  }
450
- getActiveNotes(channel) {
497
+ getActiveNotes(channel, time) {
451
498
  const activeNotes = new Map();
452
- channel.scheduledNotes.forEach((scheduledNotes) => {
453
- const activeNote = this.getActiveChannelNotes(scheduledNotes);
499
+ channel.scheduledNotes.forEach((noteList) => {
500
+ const activeNote = this.getActiveNote(noteList, time);
454
501
  if (activeNote) {
455
502
  activeNotes.set(activeNote.noteNumber, activeNote);
456
503
  }
457
504
  });
458
505
  return activeNotes;
459
506
  }
460
- getActiveChannelNotes(scheduledNotes) {
461
- for (let i = 0; i < scheduledNotes; i++) {
462
- const scheduledNote = scheduledNotes[i];
463
- if (scheduledNote)
464
- return scheduledNote;
507
+ getActiveNote(noteList, time) {
508
+ for (let i = noteList.length - 1; i >= 0; i--) {
509
+ const note = noteList[i];
510
+ if (!note)
511
+ return;
512
+ if (time < note.startTime)
513
+ continue;
514
+ return (note.ending) ? null : note;
465
515
  }
466
- }
467
- createModulationEffect(audioContext) {
468
- const lfo = new OscillatorNode(audioContext, {
469
- frequency: 5,
470
- });
471
- return {
472
- lfo,
473
- };
516
+ return noteList[0];
474
517
  }
475
518
  connectNoteEffects(channel, gainNode) {
476
519
  gainNode.connect(channel.pannerNode);
@@ -485,71 +528,89 @@ export class MidyGM1 {
485
528
  const tuning = channel.coarseTuning + channel.fineTuning;
486
529
  return channel.pitchBend * channel.pitchBendRange + tuning;
487
530
  }
488
- calcPlaybackRate(noteInfo, noteNumber, semitoneOffset) {
489
- return noteInfo.playbackRate(noteNumber) * Math.pow(2, semitoneOffset / 12);
531
+ calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset) {
532
+ return instrumentKey.playbackRate(noteNumber) *
533
+ Math.pow(2, semitoneOffset / 12);
490
534
  }
491
- async createNoteAudioChain(channel, noteInfo, noteNumber, velocity, startTime, isSF3) {
492
- const bufferSource = await this.createNoteBufferNode(noteInfo, isSF3);
493
- const semitoneOffset = this.calcSemitoneOffset(channel);
494
- bufferSource.playbackRate.value = this.calcPlaybackRate(noteInfo, noteNumber, semitoneOffset);
495
- // volume envelope
496
- const gainNode = new GainNode(this.audioContext, {
535
+ setVolumeEnvelope(channel, note) {
536
+ const { instrumentKey, startTime, velocity } = note;
537
+ note.gainNode = new GainNode(this.audioContext, {
497
538
  gain: 0,
498
539
  });
499
540
  let volume = (velocity / 127) * channel.volume * channel.expression;
500
541
  if (volume === 0)
501
542
  volume = 1e-6; // exponentialRampToValueAtTime() requires a non-zero value
502
- const attackVolume = this.cbToRatio(-noteInfo.initialAttenuation) * volume;
503
- const sustainVolume = attackVolume * (1 - noteInfo.volSustain);
504
- const volDelay = startTime + noteInfo.volDelay;
505
- const volAttack = volDelay + noteInfo.volAttack;
506
- const volHold = volAttack + noteInfo.volHold;
507
- const volDecay = volHold + noteInfo.volDecay;
508
- gainNode.gain
543
+ const attackVolume = this.cbToRatio(-instrumentKey.initialAttenuation) *
544
+ volume;
545
+ const sustainVolume = attackVolume * (1 - instrumentKey.volSustain);
546
+ const volDelay = startTime + instrumentKey.volDelay;
547
+ const volAttack = volDelay + instrumentKey.volAttack;
548
+ const volHold = volAttack + instrumentKey.volHold;
549
+ const volDecay = volHold + instrumentKey.volDecay;
550
+ note.gainNode.gain
509
551
  .setValueAtTime(1e-6, volDelay) // exponentialRampToValueAtTime() requires a non-zero value
510
552
  .exponentialRampToValueAtTime(attackVolume, volAttack)
511
553
  .setValueAtTime(attackVolume, volHold)
512
554
  .linearRampToValueAtTime(sustainVolume, volDecay);
513
- // filter envelope
555
+ }
556
+ setFilterEnvelope(channel, note) {
557
+ const { instrumentKey, startTime, noteNumber } = note;
558
+ const softPedalFactor = 1 -
559
+ (0.1 + (noteNumber / 127) * 0.2) * channel.softPedal;
514
560
  const maxFreq = this.audioContext.sampleRate / 2;
515
- const baseFreq = this.centToHz(noteInfo.initialFilterFc);
516
- const peekFreq = this.centToHz(noteInfo.initialFilterFc + noteInfo.modEnvToFilterFc);
517
- const sustainFreq = baseFreq +
518
- (peekFreq - baseFreq) * (1 - noteInfo.modSustain);
561
+ const baseFreq = this.centToHz(instrumentKey.initialFilterFc) *
562
+ softPedalFactor;
563
+ const peekFreq = this.centToHz(instrumentKey.initialFilterFc + instrumentKey.modEnvToFilterFc) * softPedalFactor;
564
+ const sustainFreq = (baseFreq +
565
+ (peekFreq - baseFreq) * (1 - instrumentKey.modSustain)) * softPedalFactor;
566
+ const modDelay = startTime + instrumentKey.modDelay;
567
+ const modAttack = modDelay + instrumentKey.modAttack;
568
+ const modHold = modAttack + instrumentKey.modHold;
569
+ const modDecay = modHold + instrumentKey.modDecay;
519
570
  const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
520
571
  const adjustedPeekFreq = Math.min(maxFreq, peekFreq);
521
572
  const adjustedSustainFreq = Math.min(maxFreq, sustainFreq);
522
- const filterNode = new BiquadFilterNode(this.audioContext, {
573
+ note.filterNode = new BiquadFilterNode(this.audioContext, {
523
574
  type: "lowpass",
524
- Q: noteInfo.initialFilterQ / 10, // dB
575
+ Q: instrumentKey.initialFilterQ / 10, // dB
525
576
  frequency: adjustedBaseFreq,
526
577
  });
527
- const modDelay = startTime + noteInfo.modDelay;
528
- const modAttack = modDelay + noteInfo.modAttack;
529
- const modHold = modAttack + noteInfo.modHold;
530
- const modDecay = modHold + noteInfo.modDecay;
531
- filterNode.frequency
578
+ note.filterNode.frequency
532
579
  .setValueAtTime(adjustedBaseFreq, modDelay)
533
580
  .exponentialRampToValueAtTime(adjustedPeekFreq, modAttack)
534
581
  .setValueAtTime(adjustedPeekFreq, modHold)
535
582
  .linearRampToValueAtTime(adjustedSustainFreq, modDecay);
536
- let lfoGain;
583
+ note.bufferSource.detune.setValueAtTime(note.bufferSource.detune.value + instrumentKey.modEnvToPitch, modDelay);
584
+ }
585
+ startModulation(channel, note, time) {
586
+ const { instrumentKey } = note;
587
+ note.modLFOGain = new GainNode(this.audioContext, {
588
+ gain: this.cbToRatio(instrumentKey.modLfoToVolume) * channel.modulation,
589
+ });
590
+ note.modLFO = new OscillatorNode(this.audioContext, {
591
+ frequency: this.centToHz(instrumentKey.freqModLFO),
592
+ });
593
+ note.modLFO.start(time);
594
+ note.filterNode.frequency.setValueAtTime(note.filterNode.frequency.value + instrumentKey.modLfoToFilterFc, time);
595
+ note.bufferSource.detune.setValueAtTime(note.bufferSource.detune.value + instrumentKey.modLfoToPitch, time);
596
+ note.modLFO.connect(note.modLFOGain);
597
+ note.modLFOGain.connect(note.bufferSource.detune);
598
+ }
599
+ async createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3) {
600
+ const semitoneOffset = this.calcSemitoneOffset(channel);
601
+ const note = new Note(noteNumber, velocity, startTime, instrumentKey);
602
+ note.bufferSource = await this.createNoteBufferNode(instrumentKey, isSF3);
603
+ note.bufferSource.playbackRate.value = this.calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
604
+ this.setVolumeEnvelope(channel, note);
605
+ this.setFilterEnvelope(channel, note);
537
606
  if (channel.modulation > 0) {
538
- const vibratoDelay = startTime + channel.vibratoDelay;
539
- const vibratoAttack = vibratoDelay + 0.1;
540
- lfoGain = new GainNode(this.audioContext, {
541
- gain: 0,
542
- });
543
- lfoGain.gain
544
- .setValueAtTime(1e-6, vibratoDelay) // exponentialRampToValueAtTime() requires a non-zero value
545
- .exponentialRampToValueAtTime(channel.modulation, vibratoAttack);
546
- channel.modulationEffect.lfo.connect(lfoGain);
547
- lfoGain.connect(bufferSource.detune);
607
+ const delayModLFO = startTime + instrumentKey.delayModLFO;
608
+ this.startModulation(channel, note, delayModLFO);
548
609
  }
549
- bufferSource.connect(filterNode);
550
- filterNode.connect(gainNode);
551
- bufferSource.start(startTime, noteInfo.start / noteInfo.sampleRate);
552
- return { bufferSource, gainNode, filterNode, lfoGain };
610
+ note.bufferSource.connect(note.filterNode);
611
+ note.filterNode.connect(note.gainNode);
612
+ note.bufferSource.start(startTime, instrumentKey.start / instrumentKey.sampleRate);
613
+ return note;
553
614
  }
554
615
  async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
555
616
  const channel = this.channels[channelNumber];
@@ -559,27 +620,17 @@ export class MidyGM1 {
559
620
  return;
560
621
  const soundFont = this.soundFonts[soundFontIndex];
561
622
  const isSF3 = soundFont.parsed.info.version.major === 3;
562
- const noteInfo = soundFont.getInstrumentKey(bankNumber, channel.program, noteNumber);
563
- if (!noteInfo)
623
+ const instrumentKey = soundFont.getInstrumentKey(bankNumber, channel.program, noteNumber);
624
+ if (!instrumentKey)
564
625
  return;
565
- const { bufferSource, gainNode, filterNode, lfoGain } = await this
566
- .createNoteAudioChain(channel, noteInfo, noteNumber, velocity, startTime, isSF3);
567
- this.connectNoteEffects(channel, gainNode);
626
+ const note = await this.createNote(channel, instrumentKey, noteNumber, velocity, startTime, isSF3);
627
+ this.connectNoteEffects(channel, note.gainNode);
568
628
  const scheduledNotes = channel.scheduledNotes;
569
- const scheduledNote = {
570
- bufferSource,
571
- filterNode,
572
- gainNode,
573
- lfoGain,
574
- noteInfo,
575
- noteNumber,
576
- startTime,
577
- };
578
629
  if (scheduledNotes.has(noteNumber)) {
579
- scheduledNotes.get(noteNumber).push(scheduledNote);
630
+ scheduledNotes.get(noteNumber).push(note);
580
631
  }
581
632
  else {
582
- scheduledNotes.set(noteNumber, [scheduledNote]);
633
+ scheduledNotes.set(noteNumber, [note]);
583
634
  }
584
635
  }
585
636
  noteOn(channelNumber, noteNumber, velocity) {
@@ -599,15 +650,15 @@ export class MidyGM1 {
599
650
  continue;
600
651
  if (targetNote.ending)
601
652
  continue;
602
- const { bufferSource, filterNode, gainNode, lfoGain, noteInfo } = targetNote;
653
+ const { bufferSource, filterNode, gainNode, modLFO, modLFOGain, instrumentKey, } = targetNote;
603
654
  const velocityRate = (velocity + 127) / 127;
604
- const volEndTime = stopTime + noteInfo.volRelease * velocityRate;
655
+ const volEndTime = stopTime + instrumentKey.volRelease * velocityRate;
605
656
  gainNode.gain.cancelScheduledValues(stopTime);
606
657
  gainNode.gain.linearRampToValueAtTime(0, volEndTime);
607
658
  const maxFreq = this.audioContext.sampleRate / 2;
608
- const baseFreq = this.centToHz(noteInfo.initialFilterFc);
659
+ const baseFreq = this.centToHz(instrumentKey.initialFilterFc);
609
660
  const adjustedBaseFreq = Math.min(maxFreq, baseFreq);
610
- const modEndTime = stopTime + noteInfo.modRelease * velocityRate;
661
+ const modEndTime = stopTime + instrumentKey.modRelease * velocityRate;
611
662
  filterNode.frequency
612
663
  .cancelScheduledValues(stopTime)
613
664
  .linearRampToValueAtTime(adjustedBaseFreq, modEndTime);
@@ -621,8 +672,10 @@ export class MidyGM1 {
621
672
  bufferSource.disconnect(0);
622
673
  filterNode.disconnect(0);
623
674
  gainNode.disconnect(0);
624
- if (lfoGain)
625
- lfoGain.disconnect(0);
675
+ if (modLFOGain)
676
+ modLFOGain.disconnect(0);
677
+ if (modLFO)
678
+ modLFO.stop();
626
679
  resolve();
627
680
  };
628
681
  bufferSource.stop(volEndTime);
@@ -680,10 +733,10 @@ export class MidyGM1 {
680
733
  const channel = this.channels[channelNumber];
681
734
  channel.pitchBend = (pitchBend - 8192) / 8192;
682
735
  const semitoneOffset = this.calcSemitoneOffset(channel);
683
- const activeNotes = this.getActiveNotes(channel);
736
+ const activeNotes = this.getActiveNotes(channel, now);
684
737
  activeNotes.forEach((activeNote) => {
685
- const { bufferSource, noteInfo, noteNumber } = activeNote;
686
- const playbackRate = calcPlaybackRate(noteInfo, noteNumber, semitoneOffset);
738
+ const { bufferSource, instrumentKey, noteNumber } = activeNote;
739
+ const playbackRate = calcPlaybackRate(instrumentKey, noteNumber, semitoneOffset);
687
740
  bufferSource.playbackRate
688
741
  .cancelScheduledValues(now)
689
742
  .setValueAtTime(playbackRate * pressure, now);
@@ -720,9 +773,20 @@ export class MidyGM1 {
720
773
  }
721
774
  }
722
775
  setModulation(channelNumber, modulation) {
776
+ const now = this.audioContext.currentTime;
723
777
  const channel = this.channels[channelNumber];
724
778
  channel.modulation = (modulation / 127) *
725
779
  (channel.modulationDepthRange * 100);
780
+ const activeNotes = this.getActiveNotes(channel, now);
781
+ activeNotes.forEach((activeNote) => {
782
+ if (activeNote.modLFO) {
783
+ activeNote.gainNode.gain.setValueAtTime(this.cbToRatio(activeNote.instrumentKey.modLfoToVolume) *
784
+ channel.modulation, now);
785
+ }
786
+ else {
787
+ this.startModulation(channel, activeNote, now);
788
+ }
789
+ });
726
790
  }
727
791
  setVolume(channelNumber, volume) {
728
792
  const channel = this.channels[channelNumber];
@@ -785,8 +849,8 @@ export class MidyGM1 {
785
849
  const velocity = 0;
786
850
  const stopPedal = true;
787
851
  const promises = [];
788
- channel.scheduledNotes.forEach((scheduledNotes) => {
789
- const activeNote = this.getActiveChannelNotes(scheduledNotes);
852
+ channel.scheduledNotes.forEach((noteList) => {
853
+ const activeNote = this.getActiveNote(noteList, now);
790
854
  if (activeNote) {
791
855
  const notePromise = this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now, stopPedal);
792
856
  promises.push(notePromise);
@@ -803,8 +867,8 @@ export class MidyGM1 {
803
867
  const velocity = 0;
804
868
  const stopPedal = false;
805
869
  const promises = [];
806
- channel.scheduledNotes.forEach((scheduledNotes) => {
807
- const activeNote = this.getActiveChannelNotes(scheduledNotes);
870
+ channel.scheduledNotes.forEach((noteList) => {
871
+ const activeNote = this.getActiveNote(noteList, now);
808
872
  if (activeNote) {
809
873
  const notePromise = this.scheduleNoteRelease(channelNumber, noteNumber, velocity, now, stopPedal);
810
874
  promises.push(notePromise);
@@ -898,9 +962,6 @@ Object.defineProperty(MidyGM1, "channelSettings", {
898
962
  value: {
899
963
  volume: 100 / 127,
900
964
  pan: 0,
901
- vibratoRate: 5,
902
- vibratoDepth: 0.5,
903
- vibratoDelay: 2.5,
904
965
  bank: 0,
905
966
  dataMSB: 0,
906
967
  dataLSB: 0,