@marmooo/midy 0.4.0 → 0.4.1

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.
@@ -99,11 +99,11 @@ const defaultControllerState = {
99
99
  pitchWheel: { type: 14, defaultValue: 8192 / 16383 },
100
100
  pitchWheelSensitivity: { type: 16, defaultValue: 2 / 128 },
101
101
  link: { type: 127, defaultValue: 0 },
102
- modulationDepth: { type: 128 + 1, defaultValue: 0 },
102
+ modulationDepthMSB: { type: 128 + 1, defaultValue: 0 },
103
103
  // dataMSB: { type: 128 + 6, defaultValue: 0, },
104
- volume: { type: 128 + 7, defaultValue: 100 / 127 },
105
- pan: { type: 128 + 10, defaultValue: 64 / 127 },
106
- expression: { type: 128 + 11, defaultValue: 1 },
104
+ volumeMSB: { type: 128 + 7, defaultValue: 100 / 127 },
105
+ panMSB: { type: 128 + 10, defaultValue: 64 / 127 },
106
+ expressionMSB: { type: 128 + 11, defaultValue: 1 },
107
107
  // dataLSB: { type: 128 + 38, defaultValue: 0, },
108
108
  sustainPedal: { type: 128 + 64, defaultValue: 0 },
109
109
  // rpnLSB: { type: 128 + 100, defaultValue: 127 },
@@ -429,7 +429,7 @@ export class MidyGMLite {
429
429
  return soundFontIndex * (2 ** 32) + (instrument << 16) + sampleID;
430
430
  }
431
431
  createChannelAudioNodes(audioContext) {
432
- const { gainLeft, gainRight } = this.panToGain(defaultControllerState.pan.defaultValue);
432
+ const { gainLeft, gainRight } = this.panToGain(defaultControllerState.panMSB.defaultValue);
433
433
  const gainL = new GainNode(audioContext, { gain: gainLeft });
434
434
  const gainR = new GainNode(audioContext, { gain: gainRight });
435
435
  const merger = new ChannelMergerNode(audioContext, { numberOfInputs: 2 });
@@ -457,10 +457,9 @@ export class MidyGMLite {
457
457
  return channels;
458
458
  }
459
459
  async createAudioBuffer(voiceParams) {
460
- const sample = voiceParams.sample;
461
- const sampleStart = voiceParams.start;
462
- const sampleEnd = sample.data.length + voiceParams.end;
463
- const audioBuffer = await sample.toAudioBuffer(this.audioContext, sampleStart, sampleEnd);
460
+ const { sample, start, end } = voiceParams;
461
+ const sampleEnd = sample.data.length + end;
462
+ const audioBuffer = await sample.toAudioBuffer(this.audioContext, start, sampleEnd);
464
463
  return audioBuffer;
465
464
  }
466
465
  createBufferSource(channel, voiceParams, audioBuffer) {
@@ -490,9 +489,7 @@ export class MidyGMLite {
490
489
  await this.noteOn(event.channel, event.noteNumber, event.velocity, startTime);
491
490
  break;
492
491
  case "noteOff": {
493
- const notePromise = this.noteOff(event.channel, event.noteNumber, event.velocity, startTime, false);
494
- if (notePromise)
495
- this.notePromises.push(notePromise);
492
+ this.noteOff(event.channel, event.noteNumber, event.velocity, startTime, false);
496
493
  break;
497
494
  }
498
495
  case "controller":
@@ -586,6 +583,12 @@ export class MidyGMLite {
586
583
  const waitTime = now + this.noteCheckInterval;
587
584
  await this.scheduleTask(() => { }, waitTime);
588
585
  }
586
+ if (this.timeline.length <= queueIndex) {
587
+ const now = this.audioContext.currentTime;
588
+ await this.stopNotes(0, true, now);
589
+ await this.audioContext.suspend();
590
+ finished = true;
591
+ }
589
592
  if (finished) {
590
593
  this.notePromises = [];
591
594
  this.resetAllStates();
@@ -918,12 +921,18 @@ export class MidyGMLite {
918
921
  this.setFilterEnvelope(note, now);
919
922
  this.setPitchEnvelope(note, now);
920
923
  this.updateDetune(channel, note, now);
921
- if (0 < state.modulationDepth) {
924
+ if (0 < state.modulationDepthMSB) {
922
925
  this.startModulation(channel, note, now);
923
926
  }
924
927
  note.bufferSource.connect(note.filterNode);
925
928
  note.filterNode.connect(note.volumeEnvelopeNode);
926
- note.bufferSource.start(startTime);
929
+ if (voiceParams.sample.type === "compressed") {
930
+ const offset = voiceParams.start / audioBuffer.sampleRate;
931
+ note.bufferSource.start(startTime, offset);
932
+ }
933
+ else {
934
+ note.bufferSource.start(startTime);
935
+ }
927
936
  return note;
928
937
  }
929
938
  handleExclusiveClass(note, channelNumber, startTime) {
@@ -1045,7 +1054,9 @@ export class MidyGMLite {
1045
1054
  }
1046
1055
  note.ending = true;
1047
1056
  this.setNoteIndex(channel, index);
1048
- this.releaseNote(channel, note, endTime);
1057
+ const promise = this.releaseNote(channel, note, endTime);
1058
+ this.notePromises.push(promise);
1059
+ return promise;
1049
1060
  }
1050
1061
  setNoteIndex(channel, index) {
1051
1062
  let allEnds = true;
@@ -1143,11 +1154,12 @@ export class MidyGMLite {
1143
1154
  setModLfoToPitch(channel, note, scheduleTime) {
1144
1155
  if (note.modulationDepth) {
1145
1156
  const modLfoToPitch = note.voiceParams.modLfoToPitch;
1146
- const baseDepth = Math.abs(modLfoToPitch) + channel.state.modulationDepth;
1147
- const modulationDepth = baseDepth * Math.sign(modLfoToPitch);
1157
+ const baseDepth = Math.abs(modLfoToPitch) +
1158
+ channel.state.modulationDepthMSB;
1159
+ const depth = baseDepth * Math.sign(modLfoToPitch);
1148
1160
  note.modulationDepth.gain
1149
1161
  .cancelScheduledValues(scheduleTime)
1150
- .setValueAtTime(modulationDepth, scheduleTime);
1162
+ .setValueAtTime(depth, scheduleTime);
1151
1163
  }
1152
1164
  else {
1153
1165
  this.startModulation(channel, note, scheduleTime);
@@ -1184,18 +1196,18 @@ export class MidyGMLite {
1184
1196
  createVoiceParamsHandlers() {
1185
1197
  return {
1186
1198
  modLfoToPitch: (channel, note, scheduleTime) => {
1187
- if (0 < channel.state.modulationDepth) {
1199
+ if (0 < channel.state.modulationDepthMSB) {
1188
1200
  this.setModLfoToPitch(channel, note, scheduleTime);
1189
1201
  }
1190
1202
  },
1191
1203
  vibLfoToPitch: (_channel, _note, _scheduleTime) => { },
1192
1204
  modLfoToFilterFc: (channel, note, scheduleTime) => {
1193
- if (0 < channel.state.modulationDepth) {
1205
+ if (0 < channel.state.modulationDepthMSB) {
1194
1206
  this.setModLfoToFilterFc(note, scheduleTime);
1195
1207
  }
1196
1208
  },
1197
1209
  modLfoToVolume: (channel, note, scheduleTime) => {
1198
- if (0 < channel.state.modulationDepth) {
1210
+ if (0 < channel.state.modulationDepthMSB) {
1199
1211
  this.setModLfoToVolume(note, scheduleTime);
1200
1212
  }
1201
1213
  },
@@ -1433,8 +1445,8 @@ export class MidyGMLite {
1433
1445
  resetAllControllers(channelNumber, _value, scheduleTime) {
1434
1446
  const keys = [
1435
1447
  "pitchWheel",
1436
- "expression",
1437
- "modulationDepth",
1448
+ "expressionMSB",
1449
+ "modulationDepthMSB",
1438
1450
  "sustainPedal",
1439
1451
  ];
1440
1452
  const channel = this.channels[channelNumber];
package/esm/midy.d.ts CHANGED
@@ -13,6 +13,7 @@ export class Midy {
13
13
  modulationDepthRange: number;
14
14
  fineTuning: number;
15
15
  coarseTuning: number;
16
+ portamentoControl: boolean;
16
17
  };
17
18
  constructor(audioContext: any);
18
19
  mode: string;
@@ -182,11 +183,11 @@ export class Midy {
182
183
  noteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
183
184
  disconnectNote(note: any): void;
184
185
  releaseNote(channel: any, note: any, endTime: any): Promise<any>;
185
- noteOff(channelNumber: any, noteNumber: any, velocity: any, endTime: any, force: any): void;
186
+ noteOff(channelNumber: any, noteNumber: any, velocity: any, endTime: any, force: any): Promise<any> | undefined;
186
187
  setNoteIndex(channel: any, index: any): void;
187
188
  findNoteOffIndex(channel: any, noteNumber: any): any;
188
- releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): void[];
189
- releaseSostenutoPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): void[];
189
+ releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
190
+ releaseSostenutoPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
190
191
  createMessageHandlers(): any[];
191
192
  handleMessage(data: any, scheduleTime: any): void;
192
193
  activeSensing(): void;
@@ -223,16 +224,16 @@ export class Midy {
223
224
  setControlChange(channelNumber: any, controllerType: any, value: any, scheduleTime: any): void;
224
225
  setBankMSB(channelNumber: any, msb: any): void;
225
226
  updateModulation(channel: any, scheduleTime: any): void;
226
- setModulationDepth(channelNumber: any, modulation: any, scheduleTime: any): void;
227
+ setModulationDepth(channelNumber: any, value: any, scheduleTime: any): void;
227
228
  updatePortamento(channel: any, scheduleTime: any): void;
228
- setPortamentoTime(channelNumber: any, portamentoTime: any, scheduleTime: any): void;
229
- setVolume(channelNumber: any, volume: any, scheduleTime: any): void;
229
+ setPortamentoTime(channelNumber: any, value: any, scheduleTime: any): void;
230
+ setVolume(channelNumber: any, value: any, scheduleTime: any): void;
230
231
  panToGain(pan: any): {
231
232
  gainLeft: number;
232
233
  gainRight: number;
233
234
  };
234
- setPan(channelNumber: any, pan: any, scheduleTime: any): void;
235
- setExpression(channelNumber: any, expression: any, scheduleTime: any): void;
235
+ setPan(channelNumber: any, value: any, scheduleTime: any): void;
236
+ setExpression(channelNumber: any, value: any, scheduleTime: any): void;
236
237
  setBankLSB(channelNumber: any, lsb: any): void;
237
238
  dataEntryLSB(channelNumber: any, value: any, scheduleTime: any): void;
238
239
  updateChannelVolume(channel: any, scheduleTime: any): void;
@@ -252,6 +253,7 @@ export class Midy {
252
253
  setVibratoRate(channelNumber: any, vibratoRate: any, scheduleTime: any): void;
253
254
  setVibratoDepth(channelNumber: any, vibratoDepth: any, scheduleTime: any): void;
254
255
  setVibratoDelay(channelNumber: any, vibratoDelay: any, scheduleTime: any): void;
256
+ setPortamentoNoteNumber(channelNumber: any, value: any, scheduleTime: any): void;
255
257
  setReverbSendLevel(channelNumber: any, reverbSendLevel: any, scheduleTime: any): void;
256
258
  setChorusSendLevel(channelNumber: any, chorusSendLevel: any, scheduleTime: any): void;
257
259
  limitData(channel: any, minMSB: any, maxMSB: any, minLSB: any, maxLSB: any): void;
package/esm/midy.d.ts.map CHANGED
@@ -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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"}
package/esm/midy.js CHANGED
@@ -158,14 +158,19 @@ const defaultControllerState = {
158
158
  pitchWheelSensitivity: { type: 16, defaultValue: 2 / 128 },
159
159
  link: { type: 127, defaultValue: 0 },
160
160
  // bankMSB: { type: 128 + 0, defaultValue: 121, },
161
- modulationDepth: { type: 128 + 1, defaultValue: 0 },
162
- portamentoTime: { type: 128 + 5, defaultValue: 0 },
161
+ modulationDepthMSB: { type: 128 + 1, defaultValue: 0 },
162
+ portamentoTimeMSB: { type: 128 + 5, defaultValue: 0 },
163
163
  // dataMSB: { type: 128 + 6, defaultValue: 0, },
164
- volume: { type: 128 + 7, defaultValue: 100 / 127 },
165
- pan: { type: 128 + 10, defaultValue: 64 / 127 },
166
- expression: { type: 128 + 11, defaultValue: 1 },
164
+ volumeMSB: { type: 128 + 7, defaultValue: 100 / 127 },
165
+ panMSB: { type: 128 + 10, defaultValue: 64 / 127 },
166
+ expressionMSB: { type: 128 + 11, defaultValue: 1 },
167
167
  // bankLSB: { type: 128 + 32, defaultValue: 0, },
168
+ modulationDepthLSB: { type: 128 + 33, defaultValue: 0 },
169
+ portamentoTimeLSB: { type: 128 + 37, defaultValue: 0 },
168
170
  // dataLSB: { type: 128 + 38, defaultValue: 0, },
171
+ volumeLSB: { type: 128 + 39, defaultValue: 0 },
172
+ panLSB: { type: 128 + 42, defaultValue: 0 },
173
+ expressionLSB: { type: 128 + 43, defaultValue: 0 },
169
174
  sustainPedal: { type: 128 + 64, defaultValue: 0 },
170
175
  portamento: { type: 128 + 65, defaultValue: 0 },
171
176
  sostenutoPedal: { type: 128 + 66, defaultValue: 0 },
@@ -178,6 +183,7 @@ const defaultControllerState = {
178
183
  vibratoRate: { type: 128 + 76, defaultValue: 64 / 127 },
179
184
  vibratoDepth: { type: 128 + 77, defaultValue: 64 / 127 },
180
185
  vibratoDelay: { type: 128 + 78, defaultValue: 64 / 127 },
186
+ portamentoNoteNumber: { type: 128 + 84, defaultValue: 0 },
181
187
  reverbSendLevel: { type: 128 + 91, defaultValue: 0 },
182
188
  chorusSendLevel: { type: 128 + 93, defaultValue: 0 },
183
189
  // dataIncrement: { type: 128 + 96, defaultValue: 0 },
@@ -561,7 +567,7 @@ export class Midy {
561
567
  return soundFontIndex * (2 ** 32) + (instrument << 16) + sampleID;
562
568
  }
563
569
  createChannelAudioNodes(audioContext) {
564
- const { gainLeft, gainRight } = this.panToGain(defaultControllerState.pan.defaultValue);
570
+ const { gainLeft, gainRight } = this.panToGain(defaultControllerState.panMSB.defaultValue);
565
571
  const gainL = new GainNode(audioContext, { gain: gainLeft });
566
572
  const gainR = new GainNode(audioContext, { gain: gainRight });
567
573
  const merger = new ChannelMergerNode(audioContext, { numberOfInputs: 2 });
@@ -604,10 +610,9 @@ export class Midy {
604
610
  return channels;
605
611
  }
606
612
  async createAudioBuffer(voiceParams) {
607
- const sample = voiceParams.sample;
608
- const sampleStart = voiceParams.start;
609
- const sampleEnd = sample.data.length + voiceParams.end;
610
- const audioBuffer = await sample.toAudioBuffer(this.audioContext, sampleStart, sampleEnd);
613
+ const { sample, start, end } = voiceParams;
614
+ const sampleEnd = sample.data.length + end;
615
+ const audioBuffer = await sample.toAudioBuffer(this.audioContext, start, sampleEnd);
611
616
  return audioBuffer;
612
617
  }
613
618
  isLoopDrum(channel, noteNumber) {
@@ -642,9 +647,7 @@ export class Midy {
642
647
  await this.noteOn(event.channel, event.noteNumber, event.velocity, startTime);
643
648
  break;
644
649
  case "noteOff": {
645
- const notePromise = this.noteOff(event.channel, event.noteNumber, event.velocity, startTime, false);
646
- if (notePromise)
647
- this.notePromises.push(notePromise);
650
+ this.noteOff(event.channel, event.noteNumber, event.velocity, startTime, false);
648
651
  break;
649
652
  }
650
653
  case "noteAftertouch":
@@ -751,6 +754,12 @@ export class Midy {
751
754
  const waitTime = now + this.noteCheckInterval;
752
755
  await this.scheduleTask(() => { }, waitTime);
753
756
  }
757
+ if (this.timeline.length <= queueIndex) {
758
+ const now = this.audioContext.currentTime;
759
+ await this.stopNotes(0, true, now);
760
+ await this.audioContext.suspend();
761
+ finished = true;
762
+ }
754
763
  if (finished) {
755
764
  this.notePromises = [];
756
765
  this.resetAllStates();
@@ -1143,6 +1152,13 @@ export class Midy {
1143
1152
  const noteDetune = this.calcNoteDetune(channel, note);
1144
1153
  const pitchControl = this.getPitchControl(channel, note);
1145
1154
  const detune = channel.detune + noteDetune + pitchControl;
1155
+ if (channel.portamentoControl) {
1156
+ const state = channel.state;
1157
+ const portamentoNoteNumber = Math.ceil(state.portamentoNoteNumber * 127);
1158
+ note.portamentoNoteNumber = portamentoNoteNumber;
1159
+ channel.portamentoControl = false;
1160
+ state.portamentoNoteNumber = 0;
1161
+ }
1146
1162
  if (this.isPortamento(channel, note)) {
1147
1163
  const startTime = note.startTime;
1148
1164
  const deltaCent = (note.noteNumber - note.portamentoNoteNumber) * 100;
@@ -1159,8 +1175,10 @@ export class Midy {
1159
1175
  }
1160
1176
  }
1161
1177
  getPortamentoTime(channel, note) {
1178
+ const { portamentoTimeMSB, portamentoTimeLSB } = channel.state;
1179
+ const portamentoTime = portamentoTimeMSB + portamentoTimeLSB / 128;
1162
1180
  const deltaSemitone = Math.abs(note.noteNumber - note.portamentoNoteNumber);
1163
- const value = Math.ceil(channel.state.portamentoTime * 127);
1181
+ const value = Math.ceil(portamentoTime * 128);
1164
1182
  return deltaSemitone / this.getPitchIncrementSpeed(value) / 10;
1165
1183
  }
1166
1184
  getPitchIncrementSpeed(value) {
@@ -1424,7 +1442,7 @@ export class Midy {
1424
1442
  if (0 < state.vibratoDepth) {
1425
1443
  this.startVibrato(channel, note, now);
1426
1444
  }
1427
- if (0 < state.modulationDepth) {
1445
+ if (0 < state.modulationDepthMSB + state.modulationDepthLSB) {
1428
1446
  this.startModulation(channel, note, now);
1429
1447
  }
1430
1448
  if (channel.mono && channel.currentBufferSource) {
@@ -1435,7 +1453,13 @@ export class Midy {
1435
1453
  note.filterNode.connect(note.volumeEnvelopeNode);
1436
1454
  this.setChorusSend(channel, note, now);
1437
1455
  this.setReverbSend(channel, note, now);
1438
- note.bufferSource.start(startTime);
1456
+ if (voiceParams.sample.type === "compressed") {
1457
+ const offset = voiceParams.start / audioBuffer.sampleRate;
1458
+ note.bufferSource.start(startTime, offset);
1459
+ }
1460
+ else {
1461
+ note.bufferSource.start(startTime);
1462
+ }
1439
1463
  return note;
1440
1464
  }
1441
1465
  handleExclusiveClass(note, channelNumber, startTime) {
@@ -1594,7 +1618,9 @@ export class Midy {
1594
1618
  }
1595
1619
  note.ending = true;
1596
1620
  this.setNoteIndex(channel, index);
1597
- this.releaseNote(channel, note, endTime);
1621
+ const promise = this.releaseNote(channel, note, endTime);
1622
+ this.notePromises.push(promise);
1623
+ return promise;
1598
1624
  }
1599
1625
  setNoteIndex(channel, index) {
1600
1626
  let allEnds = true;
@@ -1747,9 +1773,11 @@ export class Midy {
1747
1773
  }
1748
1774
  setModLfoToPitch(channel, note, scheduleTime) {
1749
1775
  if (note.modulationDepth) {
1776
+ const { modulationDepthMSB, modulationDepthLSB } = channel.state;
1777
+ const modulationDepth = modulationDepthMSB + modulationDepthLSB / 128;
1750
1778
  const modLfoToPitch = note.voiceParams.modLfoToPitch +
1751
1779
  this.getLFOPitchDepth(channel, note);
1752
- const baseDepth = Math.abs(modLfoToPitch) + channel.state.modulationDepth;
1780
+ const baseDepth = Math.abs(modLfoToPitch) + modulationDepth;
1753
1781
  const depth = baseDepth * Math.sign(modLfoToPitch);
1754
1782
  note.modulationDepth.gain
1755
1783
  .cancelScheduledValues(scheduleTime)
@@ -1882,7 +1910,8 @@ export class Midy {
1882
1910
  createVoiceParamsHandlers() {
1883
1911
  return {
1884
1912
  modLfoToPitch: (channel, note, scheduleTime) => {
1885
- if (0 < channel.state.modulationDepth) {
1913
+ const { modulationDepthMSB, modulationDepthLSB } = channel.state;
1914
+ if (0 < modulationDepthMSB + modulationDepthLSB) {
1886
1915
  this.setModLfoToPitch(channel, note, scheduleTime);
1887
1916
  }
1888
1917
  },
@@ -1892,12 +1921,14 @@ export class Midy {
1892
1921
  }
1893
1922
  },
1894
1923
  modLfoToFilterFc: (channel, note, scheduleTime) => {
1895
- if (0 < channel.state.modulationDepth) {
1924
+ const { modulationDepthMSB, modulationDepthLSB } = channel.state;
1925
+ if (0 < modulationDepthMSB + modulationDepthLSB) {
1896
1926
  this.setModLfoToFilterFc(channel, note, scheduleTime);
1897
1927
  }
1898
1928
  },
1899
1929
  modLfoToVolume: (channel, note, scheduleTime) => {
1900
- if (0 < channel.state.modulationDepth) {
1930
+ const { modulationDepthMSB, modulationDepthLSB } = channel.state;
1931
+ if (0 < modulationDepthMSB + modulationDepthLSB) {
1901
1932
  this.setModLfoToVolume(channel, note, scheduleTime);
1902
1933
  }
1903
1934
  },
@@ -1908,12 +1939,14 @@ export class Midy {
1908
1939
  this.setReverbSend(channel, note, scheduleTime);
1909
1940
  },
1910
1941
  delayModLFO: (_channel, note, _scheduleTime) => {
1911
- if (0 < channel.state.modulationDepth) {
1942
+ const { modulationDepthMSB, modulationDepthLSB } = channel.state;
1943
+ if (0 < modulationDepthMSB + modulationDepthLSB) {
1912
1944
  this.setDelayModLFO(note);
1913
1945
  }
1914
1946
  },
1915
1947
  freqModLFO: (_channel, note, scheduleTime) => {
1916
- if (0 < channel.state.modulationDepth) {
1948
+ const { modulationDepthMSB, modulationDepthLSB } = channel.state;
1949
+ if (0 < modulationDepthMSB + modulationDepthLSB) {
1917
1950
  this.setFreqModLFO(note, scheduleTime);
1918
1951
  }
1919
1952
  },
@@ -1982,7 +2015,12 @@ export class Midy {
1982
2015
  handlers[10] = this.setPan;
1983
2016
  handlers[11] = this.setExpression;
1984
2017
  handlers[32] = this.setBankLSB;
2018
+ handlers[33] = this.setModulationDepth;
2019
+ handlers[37] = this.setPortamentoTime;
1985
2020
  handlers[38] = this.dataEntryLSB;
2021
+ handlers[39] = this.setVolume;
2022
+ handlers[42] = this.setPan;
2023
+ handlers[43] = this.setExpression;
1986
2024
  handlers[64] = this.setSustainPedal;
1987
2025
  handlers[65] = this.setPortamento;
1988
2026
  handlers[66] = this.setSostenutoPedal;
@@ -1995,6 +2033,7 @@ export class Midy {
1995
2033
  handlers[76] = this.setVibratoRate;
1996
2034
  handlers[77] = this.setVibratoDepth;
1997
2035
  handlers[78] = this.setVibratoDelay;
2036
+ handlers[84] = this.setPortamentoNoteNumber;
1998
2037
  handlers[91] = this.setReverbSendLevel;
1999
2038
  handlers[93] = this.setChorusSendLevel;
2000
2039
  handlers[96] = this.dataIncrement;
@@ -2026,7 +2065,9 @@ export class Midy {
2026
2065
  this.channels[channelNumber].bankMSB = msb;
2027
2066
  }
2028
2067
  updateModulation(channel, scheduleTime) {
2029
- const depth = channel.state.modulationDepth * channel.modulationDepthRange;
2068
+ const { modulationDepthMSB, modulationDepthLSB } = channel.state;
2069
+ const modulationDepth = modulationDepthMSB + modulationDepthLSB / 128;
2070
+ const depth = modulationDepth * channel.modulationDepthRange;
2030
2071
  this.processScheduledNotes(channel, (note) => {
2031
2072
  if (note.modulationDepth) {
2032
2073
  note.modulationDepth.gain.setValueAtTime(depth, scheduleTime);
@@ -2036,12 +2077,15 @@ export class Midy {
2036
2077
  }
2037
2078
  });
2038
2079
  }
2039
- setModulationDepth(channelNumber, modulation, scheduleTime) {
2080
+ setModulationDepth(channelNumber, value, scheduleTime) {
2040
2081
  const channel = this.channels[channelNumber];
2041
2082
  if (channel.isDrum)
2042
2083
  return;
2043
2084
  scheduleTime ??= this.audioContext.currentTime;
2044
- channel.state.modulationDepth = modulation / 127;
2085
+ const state = channel.state;
2086
+ const intPart = Math.trunc(value);
2087
+ state.modulationDepthMSB = intPart / 127;
2088
+ state.modulationDepthLSB = value - intPart;
2045
2089
  this.updateModulation(channel, scheduleTime);
2046
2090
  }
2047
2091
  updatePortamento(channel, scheduleTime) {
@@ -2062,18 +2106,24 @@ export class Midy {
2062
2106
  }
2063
2107
  });
2064
2108
  }
2065
- setPortamentoTime(channelNumber, portamentoTime, scheduleTime) {
2066
- const channel = this.channels[channelNumber];
2109
+ setPortamentoTime(channelNumber, value, scheduleTime) {
2067
2110
  scheduleTime ??= this.audioContext.currentTime;
2068
- channel.state.portamentoTime = portamentoTime / 127;
2111
+ const channel = this.channels[channelNumber];
2112
+ const state = channel.state;
2113
+ const intPart = Math.trunc(value);
2114
+ state.portamentoTimeMSB = intPart / 127;
2115
+ state.portamentoTimeLSB = value - 127;
2069
2116
  if (channel.isDrum)
2070
2117
  return;
2071
2118
  this.updatePortamento(channel, scheduleTime);
2072
2119
  }
2073
- setVolume(channelNumber, volume, scheduleTime) {
2120
+ setVolume(channelNumber, value, scheduleTime) {
2074
2121
  scheduleTime ??= this.audioContext.currentTime;
2075
2122
  const channel = this.channels[channelNumber];
2076
- channel.state.volume = volume / 127;
2123
+ const state = channel.state;
2124
+ const intPart = Math.trunc(value);
2125
+ state.volumeMSB = intPart / 127;
2126
+ state.volumeLSB = value - intPart;
2077
2127
  if (channel.isDrum) {
2078
2128
  for (let i = 0; i < 128; i++) {
2079
2129
  this.updateKeyBasedVolume(channel, i, scheduleTime);
@@ -2084,16 +2134,19 @@ export class Midy {
2084
2134
  }
2085
2135
  }
2086
2136
  panToGain(pan) {
2087
- const theta = Math.PI / 2 * Math.max(0, pan * 127 - 1) / 126;
2137
+ const theta = Math.PI / 2 * Math.max(pan * 127 - 1) / 126;
2088
2138
  return {
2089
2139
  gainLeft: Math.cos(theta),
2090
2140
  gainRight: Math.sin(theta),
2091
2141
  };
2092
2142
  }
2093
- setPan(channelNumber, pan, scheduleTime) {
2143
+ setPan(channelNumber, value, scheduleTime) {
2094
2144
  scheduleTime ??= this.audioContext.currentTime;
2095
2145
  const channel = this.channels[channelNumber];
2096
- channel.state.pan = pan / 127;
2146
+ const state = channel.state;
2147
+ const intPart = Math.trunc(value);
2148
+ state.panMSB = intPart / 127;
2149
+ state.panLSB = value - intPart;
2097
2150
  if (channel.isDrum) {
2098
2151
  for (let i = 0; i < 128; i++) {
2099
2152
  this.updateKeyBasedVolume(channel, i, scheduleTime);
@@ -2103,10 +2156,13 @@ export class Midy {
2103
2156
  this.updateChannelVolume(channel, scheduleTime);
2104
2157
  }
2105
2158
  }
2106
- setExpression(channelNumber, expression, scheduleTime) {
2159
+ setExpression(channelNumber, value, scheduleTime) {
2107
2160
  scheduleTime ??= this.audioContext.currentTime;
2108
2161
  const channel = this.channels[channelNumber];
2109
- channel.state.expression = expression / 127;
2162
+ const state = channel.state;
2163
+ const intPart = Math.trunc(value);
2164
+ state.expressionMSB = intPart / 127;
2165
+ state.expressionLSB = value - intPart;
2110
2166
  this.updateChannelVolume(channel, scheduleTime);
2111
2167
  }
2112
2168
  setBankLSB(channelNumber, lsb) {
@@ -2117,37 +2173,42 @@ export class Midy {
2117
2173
  this.handleRPN(channelNumber, 0, scheduleTime);
2118
2174
  }
2119
2175
  updateChannelVolume(channel, scheduleTime) {
2120
- const state = channel.state;
2121
- const volume = state.volume * state.expression;
2122
- const { gainLeft, gainRight } = this.panToGain(state.pan);
2176
+ const { expressionMSB, expressionLSB, volumeMSB, volumeLSB, panMSB, panLSB, } = channel.state;
2177
+ const volume = volumeMSB + volumeLSB / 128;
2178
+ const expression = expressionMSB + expressionLSB / 128;
2179
+ const pan = panMSB + panLSB / 128;
2180
+ const gain = volume * expression;
2181
+ const { gainLeft, gainRight } = this.panToGain(pan);
2123
2182
  channel.gainL.gain
2124
2183
  .cancelScheduledValues(scheduleTime)
2125
- .setValueAtTime(volume * gainLeft, scheduleTime);
2184
+ .setValueAtTime(gain * gainLeft, scheduleTime);
2126
2185
  channel.gainR.gain
2127
2186
  .cancelScheduledValues(scheduleTime)
2128
- .setValueAtTime(volume * gainRight, scheduleTime);
2187
+ .setValueAtTime(gain * gainRight, scheduleTime);
2129
2188
  }
2130
2189
  updateKeyBasedVolume(channel, keyNumber, scheduleTime) {
2131
2190
  const gainL = channel.keyBasedGainLs[keyNumber];
2132
2191
  if (!gainL)
2133
2192
  return;
2134
2193
  const gainR = channel.keyBasedGainRs[keyNumber];
2135
- const state = channel.state;
2136
- const defaultVolume = state.volume * state.expression;
2137
- const defaultPan = state.pan;
2194
+ const { expressionMSB, expressionLSB, volumeMSB, volumeLSB, panMSB, panLSB, } = channel.state;
2195
+ const volume = volumeMSB + volumeLSB / 128;
2196
+ const expression = expressionMSB + expressionLSB / 128;
2197
+ const defaultGain = volume * expression;
2198
+ const defaultPan = panMSB + panLSB / 128;
2138
2199
  const keyBasedVolume = this.getKeyBasedValue(channel, keyNumber, 7);
2139
- const volume = (0 <= keyBasedVolume)
2140
- ? defaultVolume * keyBasedVolume / 64
2141
- : defaultVolume;
2200
+ const gain = (0 <= keyBasedVolume)
2201
+ ? defaultGain * keyBasedVolume / 64
2202
+ : defaultGain;
2142
2203
  const keyBasedPan = this.getKeyBasedValue(channel, keyNumber, 10);
2143
2204
  const pan = (0 <= keyBasedPan) ? keyBasedPan / 127 : defaultPan;
2144
2205
  const { gainLeft, gainRight } = this.panToGain(pan);
2145
2206
  gainL.gain
2146
2207
  .cancelScheduledValues(scheduleTime)
2147
- .setValueAtTime(volume * gainLeft, scheduleTime);
2208
+ .setValueAtTime(gain * gainLeft, scheduleTime);
2148
2209
  gainR.gain
2149
2210
  .cancelScheduledValues(scheduleTime)
2150
- .setValueAtTime(volume * gainRight, scheduleTime);
2211
+ .setValueAtTime(gain * gainRight, scheduleTime);
2151
2212
  }
2152
2213
  setSustainPedal(channelNumber, value, scheduleTime) {
2153
2214
  const channel = this.channels[channelNumber];
@@ -2220,8 +2281,8 @@ export class Midy {
2220
2281
  scheduleTime ??= this.audioContext.currentTime;
2221
2282
  const state = channel.state;
2222
2283
  state.filterResonance = ccValue / 127;
2223
- const filterResonance = this.getRelativeKeyBasedValue(channel, note, 71);
2224
2284
  this.processScheduledNotes(channel, (note) => {
2285
+ const filterResonance = this.getRelativeKeyBasedValue(channel, note, 71);
2225
2286
  const Q = note.voiceParams.initialFilterQ / 5 * filterResonance;
2226
2287
  note.filterNode.Q.setValueAtTime(Q, scheduleTime);
2227
2288
  });
@@ -2321,6 +2382,12 @@ export class Midy {
2321
2382
  });
2322
2383
  }
2323
2384
  }
2385
+ setPortamentoNoteNumber(channelNumber, value, scheduleTime) {
2386
+ scheduleTime ??= this.audioContext.currentTime;
2387
+ const channel = this.channels[channelNumber];
2388
+ channel.portamentoControl = true;
2389
+ channel.state.portamentoNoteNumber = value / 127;
2390
+ }
2324
2391
  setReverbSendLevel(channelNumber, reverbSendLevel, scheduleTime) {
2325
2392
  scheduleTime ??= this.audioContext.currentTime;
2326
2393
  const channel = this.channels[channelNumber];
@@ -2508,8 +2575,10 @@ export class Midy {
2508
2575
  "polyphonicKeyPressure",
2509
2576
  "channelPressure",
2510
2577
  "pitchWheel",
2511
- "expression",
2512
- "modulationDepth",
2578
+ "expressionMSB",
2579
+ "expressionLSB",
2580
+ "modulationDepthMSB",
2581
+ "modulationDepthLSB",
2513
2582
  "sustainPedal",
2514
2583
  "portamento",
2515
2584
  "sostenutoPedal",
@@ -3218,5 +3287,6 @@ Object.defineProperty(Midy, "channelSettings", {
3218
3287
  modulationDepthRange: 50, // cent
3219
3288
  fineTuning: 0, // cent
3220
3289
  coarseTuning: 0, // cent
3290
+ portamentoControl: false,
3221
3291
  }
3222
3292
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marmooo/midy",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "A MIDI player/synthesizer written in JavaScript that supports GM-Lite/GM1 and SF2/SF3.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -22,7 +22,7 @@
22
22
  "test": "node test_runner.js"
23
23
  },
24
24
  "dependencies": {
25
- "@marmooo/soundfont-parser": "^0.1.4",
25
+ "@marmooo/soundfont-parser": "^0.1.5",
26
26
  "midi-file": "^1.2.4"
27
27
  },
28
28
  "devDependencies": {
@@ -112,13 +112,13 @@ export class MidyGM1 {
112
112
  noteOn(channelNumber: any, noteNumber: any, velocity: any, startTime: any): Promise<void>;
113
113
  disconnectNote(note: any): void;
114
114
  releaseNote(channel: any, note: any, endTime: any): Promise<any>;
115
- noteOff(channelNumber: any, noteNumber: any, velocity: any, endTime: any, force: any): void;
115
+ noteOff(channelNumber: any, noteNumber: any, velocity: any, endTime: any, force: any): Promise<any> | undefined;
116
116
  setNoteIndex(channel: any, index: any): void;
117
117
  findNoteOffIndex(channel: any, noteNumber: any): any;
118
- releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): void[];
118
+ releaseSustainPedal(channelNumber: any, halfVelocity: any, scheduleTime: any): (Promise<any> | undefined)[];
119
119
  createMessageHandlers(): any[];
120
120
  handleMessage(data: any, scheduleTime: any): void;
121
- handleChannelMessage(statusByte: any, data1: any, data2: any, scheduleTime: any): void | Promise<void>;
121
+ handleChannelMessage(statusByte: any, data1: any, data2: any, scheduleTime: any): void | Promise<any>;
122
122
  setProgramChange(channelNumber: any, programNumber: any, _scheduleTime: any): void;
123
123
  handlePitchBendMessage(channelNumber: any, lsb: any, msb: any, scheduleTime: any): void;
124
124
  setPitchBend(channelNumber: any, value: any, scheduleTime: any): void;