@marmooo/midy 0.1.5 → 0.1.6

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.
@@ -180,12 +180,14 @@ class MidyGM1 {
180
180
  addSoundFont(soundFont) {
181
181
  const index = this.soundFonts.length;
182
182
  this.soundFonts.push(soundFont);
183
- soundFont.parsed.presetHeaders.forEach((presetHeader) => {
183
+ const presetHeaders = soundFont.parsed.presetHeaders;
184
+ for (let i = 0; i < presetHeaders.length; i++) {
185
+ const presetHeader = presetHeaders[i];
184
186
  if (!presetHeader.presetName.startsWith("\u0000")) { // TODO: Only SF3 generated by PolyPone?
185
187
  const banks = this.soundFontTable[presetHeader.preset];
186
188
  banks.set(presetHeader.bank, index);
187
189
  }
188
- });
190
+ }
189
191
  }
190
192
  async loadSoundFont(soundFontUrl) {
191
193
  const response = await fetch(soundFontUrl);
@@ -230,27 +232,25 @@ class MidyGM1 {
230
232
  return channels;
231
233
  }
232
234
  async createNoteBuffer(instrumentKey, isSF3) {
235
+ const sampleStart = instrumentKey.start;
233
236
  const sampleEnd = instrumentKey.sample.length + instrumentKey.end;
234
237
  if (isSF3) {
235
- const sample = new Uint8Array(instrumentKey.sample.length);
236
- sample.set(instrumentKey.sample);
238
+ const sample = instrumentKey.sample.slice(sampleStart, sampleEnd);
237
239
  const audioBuffer = await this.audioContext.decodeAudioData(sample.buffer);
238
- for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) {
239
- const channelData = audioBuffer.getChannelData(channel);
240
- channelData.set(channelData.subarray(0, sampleEnd));
241
- }
242
240
  return audioBuffer;
243
241
  }
244
242
  else {
245
- const sample = instrumentKey.sample.subarray(0, sampleEnd);
246
- const floatSample = this.convertToFloat32Array(sample);
243
+ const sample = instrumentKey.sample.subarray(sampleStart, sampleEnd);
247
244
  const audioBuffer = new AudioBuffer({
248
245
  numberOfChannels: 1,
249
246
  length: sample.length,
250
247
  sampleRate: instrumentKey.sampleRate,
251
248
  });
252
249
  const channelData = audioBuffer.getChannelData(0);
253
- channelData.set(floatSample);
250
+ const int16Array = new Int16Array(sample.buffer);
251
+ for (let i = 0; i < int16Array.length; i++) {
252
+ channelData[i] = int16Array[i] / 32768;
253
+ }
254
254
  return audioBuffer;
255
255
  }
256
256
  }
@@ -266,14 +266,6 @@ class MidyGM1 {
266
266
  }
267
267
  return bufferSource;
268
268
  }
269
- convertToFloat32Array(uint8Array) {
270
- const int16Array = new Int16Array(uint8Array.buffer);
271
- const float32Array = new Float32Array(int16Array.length);
272
- for (let i = 0; i < int16Array.length; i++) {
273
- float32Array[i] = int16Array[i] / 32768;
274
- }
275
- return float32Array;
276
- }
277
269
  async scheduleTimelineEvents(t, offset, queueIndex) {
278
270
  while (queueIndex < this.timeline.length) {
279
271
  const event = this.timeline[queueIndex];
@@ -384,9 +376,11 @@ class MidyGM1 {
384
376
  bank: this.channels[i].bank,
385
377
  };
386
378
  }
387
- midi.tracks.forEach((track) => {
379
+ for (let i = 0; i < midi.tracks.length; i++) {
380
+ const track = midi.tracks[i];
388
381
  let currentTicks = 0;
389
- track.forEach((event) => {
382
+ for (let j = 0; j < track.length; j++) {
383
+ const event = track[j];
390
384
  currentTicks += event.deltaTime;
391
385
  event.ticks = currentTicks;
392
386
  switch (event.type) {
@@ -406,8 +400,8 @@ class MidyGM1 {
406
400
  }
407
401
  delete event.deltaTime;
408
402
  timeline.push(event);
409
- });
410
- });
403
+ }
404
+ }
411
405
  const priority = {
412
406
  controller: 0,
413
407
  sysEx: 1,
@@ -432,7 +426,7 @@ class MidyGM1 {
432
426
  }
433
427
  return { instruments, timeline };
434
428
  }
435
- async stopChannelNotes(channelNumber, velocity, stopPedal) {
429
+ async stopChannelNotes(channelNumber, velocity, force) {
436
430
  const now = this.audioContext.currentTime;
437
431
  const channel = this.channels[channelNumber];
438
432
  channel.scheduledNotes.forEach((noteList) => {
@@ -440,16 +434,16 @@ class MidyGM1 {
440
434
  const note = noteList[i];
441
435
  if (!note)
442
436
  continue;
443
- const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now, stopPedal);
437
+ const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now, force);
444
438
  this.notePromises.push(promise);
445
439
  }
446
440
  });
447
441
  channel.scheduledNotes.clear();
448
442
  await Promise.all(this.notePromises);
449
443
  }
450
- stopNotes(velocity, stopPedal) {
444
+ stopNotes(velocity, force) {
451
445
  for (let i = 0; i < this.channels.length; i++) {
452
- this.stopChannelNotes(i, velocity, stopPedal);
446
+ this.stopChannelNotes(i, velocity, force);
453
447
  }
454
448
  return Promise.all(this.notePromises);
455
449
  }
@@ -626,7 +620,7 @@ class MidyGM1 {
626
620
  note.volumeNode = new GainNode(this.audioContext);
627
621
  note.filterNode = new BiquadFilterNode(this.audioContext, {
628
622
  type: "lowpass",
629
- Q: instrumentKey.initialFilterQ / 10 * channel.filterResonance, // dB
623
+ Q: instrumentKey.initialFilterQ / 10, // dB
630
624
  });
631
625
  this.setVolumeEnvelope(note);
632
626
  this.setFilterEnvelope(note);
@@ -639,7 +633,7 @@ class MidyGM1 {
639
633
  }
640
634
  note.bufferSource.connect(note.filterNode);
641
635
  note.filterNode.connect(note.volumeNode);
642
- note.bufferSource.start(startTime, instrumentKey.start / instrumentKey.sampleRate);
636
+ note.bufferSource.start(startTime);
643
637
  return note;
644
638
  }
645
639
  async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
@@ -668,9 +662,38 @@ class MidyGM1 {
668
662
  const now = this.audioContext.currentTime;
669
663
  return this.scheduleNoteOn(channelNumber, noteNumber, velocity, now);
670
664
  }
671
- scheduleNoteRelease(channelNumber, noteNumber, _velocity, stopTime, stopPedal = false) {
665
+ stopNote(stopTime, endTime, scheduledNotes, index) {
666
+ const note = scheduledNotes[index];
667
+ note.volumeNode.gain
668
+ .cancelScheduledValues(stopTime)
669
+ .linearRampToValueAtTime(0, endTime);
670
+ note.ending = true;
671
+ this.scheduleTask(() => {
672
+ note.bufferSource.loop = false;
673
+ }, endTime);
674
+ return new Promise((resolve) => {
675
+ note.bufferSource.onended = () => {
676
+ scheduledNotes[index] = null;
677
+ note.bufferSource.disconnect();
678
+ note.volumeNode.disconnect();
679
+ note.filterNode.disconnect();
680
+ if (note.modulationDepth) {
681
+ note.volumeDepth.disconnect();
682
+ note.modulationDepth.disconnect();
683
+ note.modulationLFO.stop();
684
+ }
685
+ if (note.vibratoDepth) {
686
+ note.vibratoDepth.disconnect();
687
+ note.vibratoLFO.stop();
688
+ }
689
+ resolve();
690
+ };
691
+ note.bufferSource.stop(endTime);
692
+ });
693
+ }
694
+ scheduleNoteRelease(channelNumber, noteNumber, _velocity, stopTime, force) {
672
695
  const channel = this.channels[channelNumber];
673
- if (stopPedal && channel.sustainPedal)
696
+ if (!force && channel.sustainPedal)
674
697
  return;
675
698
  if (!channel.scheduledNotes.has(noteNumber))
676
699
  return;
@@ -682,32 +705,11 @@ class MidyGM1 {
682
705
  if (note.ending)
683
706
  continue;
684
707
  const volEndTime = stopTime + note.instrumentKey.volRelease;
685
- note.volumeNode.gain
686
- .cancelScheduledValues(stopTime)
687
- .linearRampToValueAtTime(0, volEndTime);
688
708
  const modRelease = stopTime + note.instrumentKey.modRelease;
689
709
  note.filterNode.frequency
690
710
  .cancelScheduledValues(stopTime)
691
711
  .linearRampToValueAtTime(0, modRelease);
692
- note.ending = true;
693
- this.scheduleTask(() => {
694
- note.bufferSource.loop = false;
695
- }, stopTime);
696
- return new Promise((resolve) => {
697
- note.bufferSource.onended = () => {
698
- scheduledNotes[i] = null;
699
- note.bufferSource.disconnect();
700
- note.volumeNode.disconnect();
701
- note.filterNode.disconnect();
702
- if (note.modulationDepth) {
703
- note.volumeDepth.disconnect();
704
- note.modulationDepth.disconnect();
705
- note.modulationLFO.stop();
706
- }
707
- resolve();
708
- };
709
- note.bufferSource.stop(volEndTime);
710
- });
712
+ this.stopNote(stopTime, volEndTime, scheduledNotes, i);
711
713
  }
712
714
  }
713
715
  releaseNote(channelNumber, noteNumber, velocity) {
@@ -816,7 +818,7 @@ class MidyGM1 {
816
818
  setVolume(channelNumber, volume) {
817
819
  const channel = this.channels[channelNumber];
818
820
  channel.volume = volume / 127;
819
- this.updateChannelGain(channel);
821
+ this.updateChannelVolume(channel);
820
822
  }
821
823
  panToGain(pan) {
822
824
  const theta = Math.PI / 2 * Math.max(0, pan - 1) / 126;
@@ -828,18 +830,18 @@ class MidyGM1 {
828
830
  setPan(channelNumber, pan) {
829
831
  const channel = this.channels[channelNumber];
830
832
  channel.pan = pan;
831
- this.updateChannelGain(channel);
833
+ this.updateChannelVolume(channel);
832
834
  }
833
835
  setExpression(channelNumber, expression) {
834
836
  const channel = this.channels[channelNumber];
835
837
  channel.expression = expression / 127;
836
- this.updateChannelGain(channel);
838
+ this.updateChannelVolume(channel);
837
839
  }
838
840
  dataEntryLSB(channelNumber, value) {
839
841
  this.channels[channelNumber].dataLSB = value;
840
842
  this.handleRPN(channelNumber, 0);
841
843
  }
842
- updateChannelGain(channel) {
844
+ updateChannelVolume(channel) {
843
845
  const now = this.audioContext.currentTime;
844
846
  const volume = channel.volume * channel.expression;
845
847
  const { gainLeft, gainRight } = this.panToGain(channel.pan);
@@ -992,11 +994,12 @@ class MidyGM1 {
992
994
  }
993
995
  }
994
996
  GM1SystemOn() {
995
- this.channels.forEach((channel) => {
997
+ for (let i = 0; i < this.channels.length; i++) {
998
+ const channel = this.channels[i];
996
999
  channel.bankMSB = 0;
997
1000
  channel.bankLSB = 0;
998
1001
  channel.bank = 0;
999
- });
1002
+ }
1000
1003
  this.channels[9].bankMSB = 1;
1001
1004
  this.channels[9].bank = 128;
1002
1005
  }
@@ -144,7 +144,7 @@ export class MidyGM2 {
144
144
  createChannels(audioContext: any): any[];
145
145
  createNoteBuffer(instrumentKey: any, isSF3: any): Promise<any>;
146
146
  createNoteBufferNode(instrumentKey: any, isSF3: any): Promise<any>;
147
- convertToFloat32Array(uint8Array: any): Float32Array;
147
+ findPortamentoTarget(queueIndex: any): any;
148
148
  scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
149
149
  getQueueIndex(second: any): number;
150
150
  playNotes(): Promise<any>;
@@ -154,8 +154,8 @@ export class MidyGM2 {
154
154
  instruments: Set<any>;
155
155
  timeline: any[];
156
156
  };
157
- stopChannelNotes(channelNumber: any, velocity: any, stopPedal: any): Promise<void>;
158
- stopNotes(velocity: any, stopPedal: any): Promise<any[]>;
157
+ stopChannelNotes(channelNumber: any, velocity: any, force: any): Promise<void>;
158
+ stopNotes(velocity: any, force: any): Promise<any[]>;
159
159
  start(): Promise<void>;
160
160
  stop(): void;
161
161
  pause(): void;
@@ -191,18 +191,21 @@ export class MidyGM2 {
191
191
  centToHz(cent: any): number;
192
192
  calcSemitoneOffset(channel: any): any;
193
193
  calcPlaybackRate(instrumentKey: any, noteNumber: any, semitoneOffset: any): number;
194
+ setPortamentoStartVolumeEnvelope(channel: any, note: any): void;
194
195
  setVolumeEnvelope(note: any): void;
195
196
  setPitch(note: any, semitoneOffset: any): void;
196
197
  clampCutoffFrequency(frequency: any): number;
198
+ setPortamentoStartFilterEnvelope(channel: any, note: any): void;
197
199
  setFilterEnvelope(channel: any, note: any): void;
198
200
  startModulation(channel: any, note: any, startTime: any): void;
199
201
  startVibrato(channel: any, note: any, startTime: any): void;
200
- createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
202
+ createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, portamento: any, isSF3: any): Promise<Note>;
201
203
  calcBank(channel: any, channelNumber: any): any;
202
- scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
203
- noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
204
- scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, stopTime: any, stopPedal?: boolean): Promise<any> | undefined;
205
- releaseNote(channelNumber: any, noteNumber: any, velocity: any): Promise<any> | undefined;
204
+ scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any, portamento: any): Promise<void>;
205
+ noteOn(channelNumber: any, noteNumber: any, velocity: any, portamento: any): Promise<void>;
206
+ stopNote(stopTime: any, endTime: any, scheduledNotes: any, index: any): Promise<any>;
207
+ scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, stopTime: any, portamentoNoteNumber: any, force: any): Promise<any> | undefined;
208
+ releaseNote(channelNumber: any, noteNumber: any, velocity: any, portamentoNoteNumber: any): Promise<any> | undefined;
206
209
  releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
207
210
  releaseSostenutoPedal(channelNumber: any, halfVelocity: any): any[];
208
211
  handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
@@ -250,7 +253,7 @@ export class MidyGM2 {
250
253
  setExpression(channelNumber: any, expression: any): void;
251
254
  setBankLSB(channelNumber: any, lsb: any): void;
252
255
  dataEntryLSB(channelNumber: any, value: any): void;
253
- updateChannelGain(channel: any): void;
256
+ updateChannelVolume(channel: any): void;
254
257
  setSustainPedal(channelNumber: any, value: any): void;
255
258
  setPortamento(channelNumber: any, value: any): void;
256
259
  setReverbSendLevel(channelNumber: any, reverbSendLevel: any): void;
@@ -1 +1 @@
1
- {"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"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"}