@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.
@@ -168,12 +168,14 @@ class MidyGMLite {
168
168
  addSoundFont(soundFont) {
169
169
  const index = this.soundFonts.length;
170
170
  this.soundFonts.push(soundFont);
171
- soundFont.parsed.presetHeaders.forEach((presetHeader) => {
171
+ const presetHeaders = soundFont.parsed.presetHeaders;
172
+ for (let i = 0; i < presetHeaders.length; i++) {
173
+ const presetHeader = presetHeaders[i];
172
174
  if (!presetHeader.presetName.startsWith("\u0000")) { // TODO: Only SF3 generated by PolyPone?
173
175
  const banks = this.soundFontTable[presetHeader.preset];
174
176
  banks.set(presetHeader.bank, index);
175
177
  }
176
- });
178
+ }
177
179
  }
178
180
  async loadSoundFont(soundFontUrl) {
179
181
  const response = await fetch(soundFontUrl);
@@ -218,27 +220,25 @@ class MidyGMLite {
218
220
  return channels;
219
221
  }
220
222
  async createNoteBuffer(instrumentKey, isSF3) {
223
+ const sampleStart = instrumentKey.start;
221
224
  const sampleEnd = instrumentKey.sample.length + instrumentKey.end;
222
225
  if (isSF3) {
223
- const sample = new Uint8Array(instrumentKey.sample.length);
224
- sample.set(instrumentKey.sample);
226
+ const sample = instrumentKey.sample.slice(sampleStart, sampleEnd);
225
227
  const audioBuffer = await this.audioContext.decodeAudioData(sample.buffer);
226
- for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) {
227
- const channelData = audioBuffer.getChannelData(channel);
228
- channelData.set(channelData.subarray(0, sampleEnd));
229
- }
230
228
  return audioBuffer;
231
229
  }
232
230
  else {
233
- const sample = instrumentKey.sample.subarray(0, sampleEnd);
234
- const floatSample = this.convertToFloat32Array(sample);
231
+ const sample = instrumentKey.sample.subarray(sampleStart, sampleEnd);
235
232
  const audioBuffer = new AudioBuffer({
236
233
  numberOfChannels: 1,
237
234
  length: sample.length,
238
235
  sampleRate: instrumentKey.sampleRate,
239
236
  });
240
237
  const channelData = audioBuffer.getChannelData(0);
241
- channelData.set(floatSample);
238
+ const int16Array = new Int16Array(sample.buffer);
239
+ for (let i = 0; i < int16Array.length; i++) {
240
+ channelData[i] = int16Array[i] / 32768;
241
+ }
242
242
  return audioBuffer;
243
243
  }
244
244
  }
@@ -254,14 +254,6 @@ class MidyGMLite {
254
254
  }
255
255
  return bufferSource;
256
256
  }
257
- convertToFloat32Array(uint8Array) {
258
- const int16Array = new Int16Array(uint8Array.buffer);
259
- const float32Array = new Float32Array(int16Array.length);
260
- for (let i = 0; i < int16Array.length; i++) {
261
- float32Array[i] = int16Array[i] / 32768;
262
- }
263
- return float32Array;
264
- }
265
257
  async scheduleTimelineEvents(t, offset, queueIndex) {
266
258
  while (queueIndex < this.timeline.length) {
267
259
  const event = this.timeline[queueIndex];
@@ -372,9 +364,11 @@ class MidyGMLite {
372
364
  bank: this.channels[i].bank,
373
365
  };
374
366
  }
375
- midi.tracks.forEach((track) => {
367
+ for (let i = 0; i < midi.tracks.length; i++) {
368
+ const track = midi.tracks[i];
376
369
  let currentTicks = 0;
377
- track.forEach((event) => {
370
+ for (let j = 0; j < track.length; j++) {
371
+ const event = track[j];
378
372
  currentTicks += event.deltaTime;
379
373
  event.ticks = currentTicks;
380
374
  switch (event.type) {
@@ -394,8 +388,8 @@ class MidyGMLite {
394
388
  }
395
389
  delete event.deltaTime;
396
390
  timeline.push(event);
397
- });
398
- });
391
+ }
392
+ }
399
393
  const priority = {
400
394
  controller: 0,
401
395
  sysEx: 1,
@@ -420,7 +414,7 @@ class MidyGMLite {
420
414
  }
421
415
  return { instruments, timeline };
422
416
  }
423
- async stopChannelNotes(channelNumber, velocity, stopPedal) {
417
+ async stopChannelNotes(channelNumber, velocity, force) {
424
418
  const now = this.audioContext.currentTime;
425
419
  const channel = this.channels[channelNumber];
426
420
  channel.scheduledNotes.forEach((noteList) => {
@@ -428,16 +422,16 @@ class MidyGMLite {
428
422
  const note = noteList[i];
429
423
  if (!note)
430
424
  continue;
431
- const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now, stopPedal);
425
+ const promise = this.scheduleNoteRelease(channelNumber, note.noteNumber, velocity, now, force);
432
426
  this.notePromises.push(promise);
433
427
  }
434
428
  });
435
429
  channel.scheduledNotes.clear();
436
430
  await Promise.all(this.notePromises);
437
431
  }
438
- stopNotes(velocity, stopPedal) {
432
+ stopNotes(velocity, force) {
439
433
  for (let i = 0; i < this.channels.length; i++) {
440
- this.stopChannelNotes(i, velocity, stopPedal);
434
+ this.stopChannelNotes(i, velocity, force);
441
435
  }
442
436
  return Promise.all(this.notePromises);
443
437
  }
@@ -613,7 +607,7 @@ class MidyGMLite {
613
607
  note.volumeNode = new GainNode(this.audioContext);
614
608
  note.filterNode = new BiquadFilterNode(this.audioContext, {
615
609
  type: "lowpass",
616
- Q: instrumentKey.initialFilterQ / 10 * channel.filterResonance, // dB
610
+ Q: instrumentKey.initialFilterQ / 10, // dB
617
611
  });
618
612
  this.setVolumeEnvelope(note);
619
613
  this.setFilterEnvelope(note);
@@ -626,7 +620,7 @@ class MidyGMLite {
626
620
  }
627
621
  note.bufferSource.connect(note.filterNode);
628
622
  note.filterNode.connect(note.volumeNode);
629
- note.bufferSource.start(startTime, instrumentKey.start / instrumentKey.sampleRate);
623
+ note.bufferSource.start(startTime);
630
624
  return note;
631
625
  }
632
626
  async scheduleNoteOn(channelNumber, noteNumber, velocity, startTime) {
@@ -655,9 +649,38 @@ class MidyGMLite {
655
649
  const now = this.audioContext.currentTime;
656
650
  return this.scheduleNoteOn(channelNumber, noteNumber, velocity, now);
657
651
  }
658
- scheduleNoteRelease(channelNumber, noteNumber, _velocity, stopTime, stopPedal = false) {
652
+ stopNote(stopTime, endTime, scheduledNotes, index) {
653
+ const note = scheduledNotes[index];
654
+ note.volumeNode.gain
655
+ .cancelScheduledValues(stopTime)
656
+ .linearRampToValueAtTime(0, endTime);
657
+ note.ending = true;
658
+ this.scheduleTask(() => {
659
+ note.bufferSource.loop = false;
660
+ }, endTime);
661
+ return new Promise((resolve) => {
662
+ note.bufferSource.onended = () => {
663
+ scheduledNotes[index] = null;
664
+ note.bufferSource.disconnect();
665
+ note.volumeNode.disconnect();
666
+ note.filterNode.disconnect();
667
+ if (note.modulationDepth) {
668
+ note.volumeDepth.disconnect();
669
+ note.modulationDepth.disconnect();
670
+ note.modulationLFO.stop();
671
+ }
672
+ if (note.vibratoDepth) {
673
+ note.vibratoDepth.disconnect();
674
+ note.vibratoLFO.stop();
675
+ }
676
+ resolve();
677
+ };
678
+ note.bufferSource.stop(endTime);
679
+ });
680
+ }
681
+ scheduleNoteRelease(channelNumber, noteNumber, _velocity, stopTime, force) {
659
682
  const channel = this.channels[channelNumber];
660
- if (stopPedal && channel.sustainPedal)
683
+ if (!force && channel.sustainPedal)
661
684
  return;
662
685
  if (!channel.scheduledNotes.has(noteNumber))
663
686
  return;
@@ -669,32 +692,11 @@ class MidyGMLite {
669
692
  if (note.ending)
670
693
  continue;
671
694
  const volEndTime = stopTime + note.instrumentKey.volRelease;
672
- note.volumeNode.gain
673
- .cancelScheduledValues(stopTime)
674
- .linearRampToValueAtTime(0, volEndTime);
675
695
  const modRelease = stopTime + note.instrumentKey.modRelease;
676
696
  note.filterNode.frequency
677
697
  .cancelScheduledValues(stopTime)
678
698
  .linearRampToValueAtTime(0, modRelease);
679
- note.ending = true;
680
- this.scheduleTask(() => {
681
- note.bufferSource.loop = false;
682
- }, stopTime);
683
- return new Promise((resolve) => {
684
- note.bufferSource.onended = () => {
685
- scheduledNotes[i] = null;
686
- note.bufferSource.disconnect();
687
- note.volumeNode.disconnect();
688
- note.filterNode.disconnect();
689
- if (note.modulationDepth) {
690
- note.volumeDepth.disconnect();
691
- note.modulationDepth.disconnect();
692
- note.modulationLFO.stop();
693
- }
694
- resolve();
695
- };
696
- note.bufferSource.stop(volEndTime);
697
- });
699
+ this.stopNote(stopTime, volEndTime, scheduledNotes, i);
698
700
  }
699
701
  }
700
702
  releaseNote(channelNumber, noteNumber, velocity) {
@@ -803,7 +805,7 @@ class MidyGMLite {
803
805
  setVolume(channelNumber, volume) {
804
806
  const channel = this.channels[channelNumber];
805
807
  channel.volume = volume / 127;
806
- this.updateChannelGain(channel);
808
+ this.updateChannelVolume(channel);
807
809
  }
808
810
  panToGain(pan) {
809
811
  const theta = Math.PI / 2 * Math.max(0, pan - 1) / 126;
@@ -815,18 +817,18 @@ class MidyGMLite {
815
817
  setPan(channelNumber, pan) {
816
818
  const channel = this.channels[channelNumber];
817
819
  channel.pan = pan;
818
- this.updateChannelGain(channel);
820
+ this.updateChannelVolume(channel);
819
821
  }
820
822
  setExpression(channelNumber, expression) {
821
823
  const channel = this.channels[channelNumber];
822
824
  channel.expression = expression / 127;
823
- this.updateChannelGain(channel);
825
+ this.updateChannelVolume(channel);
824
826
  }
825
827
  dataEntryLSB(channelNumber, value) {
826
828
  this.channels[channelNumber].dataLSB = value;
827
829
  this.handleRPN(channelNumber);
828
830
  }
829
- updateChannelGain(channel) {
831
+ updateChannelVolume(channel) {
830
832
  const now = this.audioContext.currentTime;
831
833
  const volume = channel.volume * channel.expression;
832
834
  const { gainLeft, gainRight } = this.panToGain(channel.pan);
@@ -921,11 +923,12 @@ class MidyGMLite {
921
923
  }
922
924
  }
923
925
  GM1SystemOn() {
924
- this.channels.forEach((channel) => {
926
+ for (let i = 0; i < this.channels.length; i++) {
927
+ const channel = this.channels[i];
925
928
  channel.bankMSB = 0;
926
929
  channel.bankLSB = 0;
927
930
  channel.bank = 0;
928
- });
931
+ }
929
932
  this.channels[9].bankMSB = 1;
930
933
  this.channels[9].bank = 128;
931
934
  }
package/script/midy.d.ts CHANGED
@@ -159,7 +159,7 @@ export class Midy {
159
159
  createChannels(audioContext: any): any[];
160
160
  createNoteBuffer(instrumentKey: any, isSF3: any): Promise<any>;
161
161
  createNoteBufferNode(instrumentKey: any, isSF3: any): Promise<any>;
162
- convertToFloat32Array(uint8Array: any): Float32Array;
162
+ findPortamentoTarget(queueIndex: any): any;
163
163
  scheduleTimelineEvents(t: any, offset: any, queueIndex: any): Promise<any>;
164
164
  getQueueIndex(second: any): number;
165
165
  playNotes(): Promise<any>;
@@ -169,8 +169,8 @@ export class Midy {
169
169
  instruments: Set<any>;
170
170
  timeline: any[];
171
171
  };
172
- stopChannelNotes(channelNumber: any, velocity: any, stopPedal: any): Promise<void>;
173
- stopNotes(velocity: any, stopPedal: any): Promise<any[]>;
172
+ stopChannelNotes(channelNumber: any, velocity: any, force: any): Promise<void>;
173
+ stopNotes(velocity: any, force: any): Promise<any[]>;
174
174
  start(): Promise<void>;
175
175
  stop(): void;
176
176
  pause(): void;
@@ -206,18 +206,21 @@ export class Midy {
206
206
  centToHz(cent: any): number;
207
207
  calcSemitoneOffset(channel: any): any;
208
208
  calcPlaybackRate(instrumentKey: any, noteNumber: any, semitoneOffset: any): number;
209
+ setPortamentoStartVolumeEnvelope(channel: any, note: any): void;
209
210
  setVolumeEnvelope(channel: any, note: any): void;
210
211
  setPitch(note: any, semitoneOffset: any): void;
211
212
  clampCutoffFrequency(frequency: any): number;
213
+ setPortamentoStartFilterEnvelope(channel: any, note: any): void;
212
214
  setFilterEnvelope(channel: any, note: any): void;
213
215
  startModulation(channel: any, note: any, startTime: any): void;
214
216
  startVibrato(channel: any, note: any, startTime: any): void;
215
- createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, isSF3: any): Promise<Note>;
217
+ createNote(channel: any, instrumentKey: any, noteNumber: any, velocity: any, startTime: any, portamento: any, isSF3: any): Promise<Note>;
216
218
  calcBank(channel: any, channelNumber: any): any;
217
- scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
218
- noteOn(channelNumber: any, noteNumber: any, velocity: any): Promise<void>;
219
- scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, stopTime: any, stopPedal?: boolean): Promise<any> | undefined;
220
- releaseNote(channelNumber: any, noteNumber: any, velocity: any): Promise<any> | undefined;
219
+ scheduleNoteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any, portamento: any): Promise<void>;
220
+ noteOn(channelNumber: any, noteNumber: any, velocity: any, portamento: any): Promise<void>;
221
+ stopNote(stopTime: any, endTime: any, scheduledNotes: any, index: any): Promise<any>;
222
+ scheduleNoteRelease(channelNumber: any, noteNumber: any, _velocity: any, stopTime: any, portamentoNoteNumber: any, force: any): Promise<any> | undefined;
223
+ releaseNote(channelNumber: any, noteNumber: any, velocity: any, portamentoNoteNumber: any): Promise<any> | undefined;
221
224
  releaseSustainPedal(channelNumber: any, halfVelocity: any): any[];
222
225
  releaseSostenutoPedal(channelNumber: any, halfVelocity: any): any[];
223
226
  handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
@@ -276,7 +279,7 @@ export class Midy {
276
279
  setExpression(channelNumber: any, expression: any): void;
277
280
  setBankLSB(channelNumber: any, lsb: any): void;
278
281
  dataEntryLSB(channelNumber: any, value: any): void;
279
- updateChannelGain(channel: any): void;
282
+ updateChannelVolume(channel: any): void;
280
283
  setSustainPedal(channelNumber: any, value: any): void;
281
284
  setPortamento(channelNumber: any, value: any): void;
282
285
  setReverbSendLevel(channelNumber: any, reverbSendLevel: any): void;
@@ -1 +1 @@
1
- {"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"midy.d.ts","sourceRoot":"","sources":["../src/midy.js"],"names":[],"mappings":"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"}