@marmooo/midy 0.2.3 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -612,19 +612,22 @@ class MidyGM1 {
612
612
  const pitch = pitchWheel * pitchWheelSensitivity;
613
613
  return tuning + pitch;
614
614
  }
615
- updateDetune(channel) {
616
- const now = this.audioContext.currentTime;
615
+ updateChannelDetune(channel) {
617
616
  channel.scheduledNotes.forEach((noteList) => {
618
617
  for (let i = 0; i < noteList.length; i++) {
619
618
  const note = noteList[i];
620
619
  if (!note)
621
620
  continue;
622
- note.bufferSource.detune
623
- .cancelScheduledValues(now)
624
- .setValueAtTime(channel.detune, now);
621
+ this.updateDetune(channel, note);
625
622
  }
626
623
  });
627
624
  }
625
+ updateDetune(channel, note) {
626
+ const now = this.audioContext.currentTime;
627
+ note.bufferSource.detune
628
+ .cancelScheduledValues(now)
629
+ .setValueAtTime(channel.detune, now);
630
+ }
628
631
  setVolumeEnvelope(note) {
629
632
  const now = this.audioContext.currentTime;
630
633
  const { voiceParams, startTime } = note;
@@ -877,7 +880,7 @@ class MidyGM1 {
877
880
  const next = (value - 8192) / 8192;
878
881
  state.pitchWheel = value / 16383;
879
882
  channel.detune += (next - prev) * state.pitchWheelSensitivity * 12800;
880
- this.updateDetune(channel);
883
+ this.updateChannelDetune(channel);
881
884
  this.applyVoiceParams(channel, 14);
882
885
  }
883
886
  setModLfoToPitch(channel, note) {
@@ -975,7 +978,7 @@ class MidyGM1 {
975
978
  const freqVibLFO = note.voiceParams.freqVibLFO;
976
979
  note.vibratoLFO.frequency
977
980
  .cancelScheduledValues(now)
978
- .setValueAtTime(freqVibLFO * channel.state.vibratoRate, now);
981
+ .setValueAtTime(freqVibLFO * channel.state.vibratoRate * 2, now);
979
982
  }
980
983
  },
981
984
  };
@@ -1015,7 +1018,7 @@ class MidyGM1 {
1015
1018
  if (key in voiceParams)
1016
1019
  noteVoiceParams[key] = voiceParams[key];
1017
1020
  }
1018
- this.setFilterEnvelope(channel, note);
1021
+ this.setFilterEnvelope(note);
1019
1022
  this.setPitchEnvelope(note);
1020
1023
  }
1021
1024
  else if (volumeEnvelopeKeySet.has(key)) {
@@ -1055,7 +1058,7 @@ class MidyGM1 {
1055
1058
  if (handler) {
1056
1059
  handler.call(this, channelNumber, value);
1057
1060
  const channel = this.channels[channelNumber];
1058
- this.applyVoiceParams(channel, controller + 128);
1061
+ this.applyVoiceParams(channel, controllerType + 128);
1059
1062
  }
1060
1063
  else {
1061
1064
  console.warn(`Unsupported Control change: controllerType=${controllerType} value=${value}`);
@@ -1194,7 +1197,7 @@ class MidyGM1 {
1194
1197
  const next = value / 128;
1195
1198
  state.pitchWheelSensitivity = next;
1196
1199
  channel.detune += (state.pitchWheel * 2 - 1) * (next - prev) * 12800;
1197
- this.updateDetune(channel);
1200
+ this.updateChannelDetune(channel);
1198
1201
  this.applyVoiceParams(channel, 16);
1199
1202
  }
1200
1203
  handleFineTuningRPN(channelNumber) {
@@ -1209,7 +1212,7 @@ class MidyGM1 {
1209
1212
  const next = (value - 8192) / 8.192; // cent
1210
1213
  channel.fineTuning = next;
1211
1214
  channel.detune += next - prev;
1212
- this.updateDetune(channel);
1215
+ this.updateChannelDetune(channel);
1213
1216
  }
1214
1217
  handleCoarseTuningRPN(channelNumber) {
1215
1218
  const channel = this.channels[channelNumber];
@@ -1223,7 +1226,7 @@ class MidyGM1 {
1223
1226
  const next = (value - 64) * 100; // cent
1224
1227
  channel.coarseTuning = next;
1225
1228
  channel.detune += next - prev;
1226
- this.updateDetune(channel);
1229
+ this.updateChannelDetune(channel);
1227
1230
  }
1228
1231
  allSoundOff(channelNumber) {
1229
1232
  return this.stopChannelNotes(channelNumber, 0, true);
@@ -1239,7 +1242,7 @@ class MidyGM1 {
1239
1242
  const state = channel.state;
1240
1243
  for (let i = 0; i < stateTypes.length; i++) {
1241
1244
  const type = stateTypes[i];
1242
- state[type] = defaultControllerState[type];
1245
+ state[type] = defaultControllerState[type].defaultValue;
1243
1246
  }
1244
1247
  const settingTypes = [
1245
1248
  "rpnMSB",
@@ -3,7 +3,7 @@ export class MidyGM2 {
3
3
  currentBufferSource: null;
4
4
  detune: number;
5
5
  scaleOctaveTuningTable: any[];
6
- pressureTable: Uint8Array<ArrayBuffer>;
6
+ channelPressureTable: Uint8Array<ArrayBuffer>;
7
7
  keyBasedInstrumentControlTable: Int8Array<ArrayBuffer>;
8
8
  program: number;
9
9
  bank: number;
@@ -17,14 +17,6 @@ export class MidyGM2 {
17
17
  coarseTuning: number;
18
18
  modulationDepthRange: number;
19
19
  };
20
- static controllerDestinationSettings: {
21
- pitchControl: number;
22
- filterCutoffControl: number;
23
- amplitudeControl: number;
24
- lfoPitchDepth: number;
25
- lfoFilterDepth: number;
26
- lfoAmplitudeDepth: number;
27
- };
28
20
  constructor(audioContext: any, options?: {
29
21
  reverbAlgorithm: (audioContext: any) => {
30
22
  input: any;
@@ -191,14 +183,15 @@ export class MidyGM2 {
191
183
  centToHz(cent: any): number;
192
184
  calcChannelDetune(channel: any): any;
193
185
  calcNoteDetune(channel: any, note: any): any;
194
- updateDetune(channel: any): void;
186
+ updateChannelDetune(channel: any): void;
187
+ updateDetune(channel: any, note: any, pressure: any): void;
195
188
  getPortamentoTime(channel: any): number;
196
189
  setPortamentoStartVolumeEnvelope(channel: any, note: any): void;
197
- setVolumeEnvelope(channel: any, note: any): void;
190
+ setVolumeEnvelope(note: any, pressure: any): void;
198
191
  setPitchEnvelope(note: any): void;
199
192
  clampCutoffFrequency(frequency: any): number;
200
193
  setPortamentoStartFilterEnvelope(channel: any, note: any): void;
201
- setFilterEnvelope(channel: any, note: any): void;
194
+ setFilterEnvelope(channel: any, note: any, pressure: any): void;
202
195
  startModulation(channel: any, note: any, startTime: any): void;
203
196
  startVibrato(channel: any, note: any, startTime: any): void;
204
197
  createNote(channel: any, voice: any, noteNumber: any, velocity: any, startTime: any, portamento: any, isSF3: any): Promise<Note>;
@@ -213,17 +206,17 @@ export class MidyGM2 {
213
206
  handleMIDIMessage(statusByte: any, data1: any, data2: any): void | Promise<any>;
214
207
  handleProgramChange(channelNumber: any, program: any): void;
215
208
  handleChannelPressure(channelNumber: any, value: any): void;
216
- setChannelPressure(channel: any, note: any): void;
217
209
  handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
218
210
  setPitchBend(channelNumber: any, value: any): void;
219
- setModLfoToPitch(channel: any, note: any): void;
211
+ setModLfoToPitch(channel: any, note: any, pressure: any): void;
220
212
  setVibLfoToPitch(channel: any, note: any): void;
221
- setModLfoToFilterFc(channel: any, note: any): void;
222
- setModLfoToVolume(channel: any, note: any): void;
213
+ setModLfoToFilterFc(note: any, pressure: any): void;
214
+ setModLfoToVolume(note: any, pressure: any): void;
223
215
  setReverbEffectsSend(channel: any, note: any, prevValue: any): void;
224
216
  setChorusEffectsSend(channel: any, note: any, prevValue: any): void;
225
217
  setDelayModLFO(note: any): void;
226
218
  setFreqModLFO(note: any): void;
219
+ setFreqVibLFO(channel: any, note: any): void;
227
220
  createVoiceParamsHandlers(): {
228
221
  modLfoToPitch: (channel: any, note: any, _prevValue: any) => void;
229
222
  vibLfoToPitch: (channel: any, note: any, _prevValue: any) => void;
@@ -311,7 +304,7 @@ export class MidyGM2 {
311
304
  handleUniversalNonRealTimeExclusiveMessage(data: any): void;
312
305
  GM1SystemOn(): void;
313
306
  GM2SystemOn(): void;
314
- handleUniversalRealTimeExclusiveMessage(data: any): void;
307
+ handleUniversalRealTimeExclusiveMessage(data: any): any;
315
308
  handleMasterVolumeSysEx(data: any): void;
316
309
  setMasterVolume(volume: any): void;
317
310
  handleMasterFineTuningSysEx(data: any): void;
@@ -339,14 +332,14 @@ export class MidyGM2 {
339
332
  getChannelBitmap(data: any): any[];
340
333
  handleScaleOctaveTuning1ByteFormatSysEx(data: any): void;
341
334
  applyDestinationSettings(channel: any, note: any, table: any): void;
342
- handleChannelPressureSysEx(data: any): void;
335
+ handleChannelPressureSysEx(data: any, tableName: any): void;
343
336
  initControlTable(): Uint8Array<ArrayBuffer>;
344
337
  applyControlTable(channel: any, controllerType: any): void;
345
338
  handleControlChangeSysEx(data: any): void;
346
339
  getKeyBasedInstrumentControlValue(channel: any, keyNumber: any, controllerType: any): number;
347
340
  handleKeyBasedInstrumentControlSysEx(data: any): void;
348
341
  handleExclusiveMessage(data: any): void;
349
- handleSysEx(data: any): void;
342
+ handleSysEx(data: any): any;
350
343
  scheduleTask(callback: any, startTime: any): Promise<any>;
351
344
  }
352
345
  declare class Note {
@@ -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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"}
@@ -100,7 +100,6 @@ class Note {
100
100
  const defaultControllerState = {
101
101
  noteOnVelocity: { type: 2, defaultValue: 0 },
102
102
  noteOnKeyNumber: { type: 3, defaultValue: 0 },
103
- polyPressure: { type: 10, defaultValue: 0 },
104
103
  channelPressure: { type: 13, defaultValue: 0 },
105
104
  pitchWheel: { type: 14, defaultValue: 8192 / 16383 },
106
105
  pitchWheelSensitivity: { type: 16, defaultValue: 2 / 128 },
@@ -432,9 +431,6 @@ class MidyGM2 {
432
431
  ...this.setChannelAudioNodes(audioContext),
433
432
  scheduledNotes: new Map(),
434
433
  sostenutoNotes: new Map(),
435
- channelPressure: {
436
- ...this.constructor.controllerDestinationSettings,
437
- },
438
434
  };
439
435
  });
440
436
  return channels;
@@ -936,28 +932,31 @@ class MidyGM2 {
936
932
  const pitchWheel = channel.state.pitchWheel * 2 - 1;
937
933
  const pitchWheelSensitivity = channel.state.pitchWheelSensitivity * 12800;
938
934
  const pitch = pitchWheel * pitchWheelSensitivity;
939
- const pressureDepth = (channel.pressureTable[0] - 64) / 37.5; // 2400 / 64;
935
+ const pressureDepth = (channel.channelPressureTable[0] - 64) / 37.5; // 2400 / 64;
940
936
  const pressure = pressureDepth * channel.state.channelPressure;
941
937
  return tuning + pitch + pressure;
942
938
  }
943
939
  calcNoteDetune(channel, note) {
944
940
  return channel.scaleOctaveTuningTable[note.noteNumber % 12];
945
941
  }
946
- updateDetune(channel) {
947
- const now = this.audioContext.currentTime;
942
+ updateChannelDetune(channel) {
948
943
  channel.scheduledNotes.forEach((noteList) => {
949
944
  for (let i = 0; i < noteList.length; i++) {
950
945
  const note = noteList[i];
951
946
  if (!note)
952
947
  continue;
953
- const noteDetune = this.calcNoteDetune(channel, note);
954
- const detune = channel.detune + noteDetune;
955
- note.bufferSource.detune
956
- .cancelScheduledValues(now)
957
- .setValueAtTime(detune, now);
948
+ this.updateDetune(channel, note, 0);
958
949
  }
959
950
  });
960
951
  }
952
+ updateDetune(channel, note, pressure) {
953
+ const now = this.audioContext.currentTime;
954
+ const noteDetune = this.calcNoteDetune(channel, note);
955
+ const detune = channel.detune + noteDetune + pressure;
956
+ note.bufferSource.detune
957
+ .cancelScheduledValues(now)
958
+ .setValueAtTime(detune, now);
959
+ }
961
960
  getPortamentoTime(channel) {
962
961
  const factor = 5 * Math.log(10) / 127;
963
962
  const time = channel.state.portamentoTime;
@@ -975,14 +974,11 @@ class MidyGM2 {
975
974
  .setValueAtTime(0, volDelay)
976
975
  .linearRampToValueAtTime(sustainVolume, portamentoTime);
977
976
  }
978
- setVolumeEnvelope(channel, note) {
977
+ setVolumeEnvelope(note, pressure) {
979
978
  const now = this.audioContext.currentTime;
980
- const state = channel.state;
981
979
  const { voiceParams, startTime } = note;
982
- const pressureDepth = channel.pressureTable[2] / 64;
983
- const pressure = 1 + pressureDepth * channel.state.channelPressure;
984
980
  const attackVolume = this.cbToRatio(-voiceParams.initialAttenuation) *
985
- pressure;
981
+ (1 + pressure);
986
982
  const sustainVolume = attackVolume * (1 - voiceParams.volSustain);
987
983
  const volDelay = startTime + voiceParams.volDelay;
988
984
  const volAttack = volDelay + voiceParams.volAttack;
@@ -1030,10 +1026,8 @@ class MidyGM2 {
1030
1026
  const { voiceParams, noteNumber, startTime } = note;
1031
1027
  const softPedalFactor = 1 -
1032
1028
  (0.1 + (noteNumber / 127) * 0.2) * state.softPedal;
1033
- const pressureDepth = (channel.pressureTable[1] - 64) * 15;
1034
- const pressure = pressureDepth * channel.state.channelPressure;
1035
- const baseCent = voiceParams.initialFilterFc + pressure;
1036
- const baseFreq = this.centToHz(baseCent) * softPedalFactor;
1029
+ const baseFreq = this.centToHz(voiceParams.initialFilterFc) *
1030
+ softPedalFactor;
1037
1031
  const peekFreq = this.centToHz(voiceParams.initialFilterFc + voiceParams.modEnvToFilterFc) * softPedalFactor;
1038
1032
  const sustainFreq = baseFreq +
1039
1033
  (peekFreq - baseFreq) * (1 - voiceParams.modSustain);
@@ -1047,15 +1041,16 @@ class MidyGM2 {
1047
1041
  .setValueAtTime(adjustedBaseFreq, modDelay)
1048
1042
  .linearRampToValueAtTime(adjustedSustainFreq, portamentoTime);
1049
1043
  }
1050
- setFilterEnvelope(channel, note) {
1044
+ setFilterEnvelope(channel, note, pressure) {
1051
1045
  const now = this.audioContext.currentTime;
1052
1046
  const state = channel.state;
1053
1047
  const { voiceParams, noteNumber, startTime } = note;
1054
1048
  const softPedalFactor = 1 -
1055
1049
  (0.1 + (noteNumber / 127) * 0.2) * state.softPedal;
1056
- const baseFreq = this.centToHz(voiceParams.initialFilterFc) *
1050
+ const baseCent = voiceParams.initialFilterFc + pressure;
1051
+ const baseFreq = this.centToHz(baseCent) * softPedalFactor;
1052
+ const peekFreq = this.centToHz(baseCent + voiceParams.modEnvToFilterFc) *
1057
1053
  softPedalFactor;
1058
- const peekFreq = this.centToHz(voiceParams.initialFilterFc + voiceParams.modEnvToFilterFc) * softPedalFactor;
1059
1054
  const sustainFreq = baseFreq +
1060
1055
  (peekFreq - baseFreq) * (1 - voiceParams.modSustain);
1061
1056
  const adjustedBaseFreq = this.clampCutoffFrequency(baseFreq);
@@ -1082,9 +1077,9 @@ class MidyGM2 {
1082
1077
  gain: voiceParams.modLfoToFilterFc,
1083
1078
  });
1084
1079
  note.modulationDepth = new GainNode(this.audioContext);
1085
- this.setModLfoToPitch(channel, note);
1080
+ this.setModLfoToPitch(channel, note, 0);
1086
1081
  note.volumeDepth = new GainNode(this.audioContext);
1087
- this.setModLfoToVolume(channel, note);
1082
+ this.setModLfoToVolume(note, 0);
1088
1083
  note.modulationLFO.start(startTime + voiceParams.delayModLFO);
1089
1084
  note.modulationLFO.connect(note.filterDepth);
1090
1085
  note.filterDepth.connect(note.filterNode.frequency);
@@ -1097,8 +1092,7 @@ class MidyGM2 {
1097
1092
  const { voiceParams } = note;
1098
1093
  const state = channel.state;
1099
1094
  note.vibratoLFO = new OscillatorNode(this.audioContext, {
1100
- frequency: this.centToHz(voiceParams.freqVibLFO) *
1101
- state.vibratoRate,
1095
+ frequency: this.centToHz(voiceParams.freqVibLFO) * state.vibratoRate * 2,
1102
1096
  });
1103
1097
  note.vibratoLFO.start(startTime + voiceParams.delayVibLFO * state.vibratoDelay * 2);
1104
1098
  note.vibratoDepth = new GainNode(this.audioContext);
@@ -1127,8 +1121,8 @@ class MidyGM2 {
1127
1121
  }
1128
1122
  else {
1129
1123
  note.portamento = false;
1130
- this.setVolumeEnvelope(channel, note);
1131
- this.setFilterEnvelope(channel, note);
1124
+ this.setVolumeEnvelope(note, 0);
1125
+ this.setFilterEnvelope(channel, note, 0);
1132
1126
  }
1133
1127
  if (0 < state.vibratoDepth) {
1134
1128
  this.startVibrato(channel, note, startTime);
@@ -1347,11 +1341,11 @@ class MidyGM2 {
1347
1341
  const prev = channel.state.channelPressure;
1348
1342
  const next = value / 127;
1349
1343
  channel.state.channelPressure = next;
1350
- if (channel.pressureTable[0] !== 64) {
1351
- const pressureDepth = (channel.pressureTable[0] - 64) / 37.5; // 2400 / 64;
1344
+ if (channel.channelPressureTable[0] !== 64) {
1345
+ const pressureDepth = (channel.channelPressureTable[0] - 64) / 37.5; // 2400 / 64;
1352
1346
  channel.detune += pressureDepth * (next - prev);
1353
1347
  }
1354
- const table = channel.pressureTable;
1348
+ const table = channel.channelPressureTable;
1355
1349
  channel.scheduledNotes.forEach((noteList) => {
1356
1350
  for (let i = 0; i < noteList.length; i++) {
1357
1351
  const note = noteList[i];
@@ -1362,28 +1356,6 @@ class MidyGM2 {
1362
1356
  });
1363
1357
  // this.applyVoiceParams(channel, 13);
1364
1358
  }
1365
- setChannelPressure(channel, note) {
1366
- if (channel.pressureTable[0] !== 64) {
1367
- this.updateDetune(channel);
1368
- }
1369
- if (!note.portamento) {
1370
- if (channel.pressureTable[1] !== 64) {
1371
- this.setFilterEnvelope(channel, note);
1372
- }
1373
- if (channel.pressureTable[2] !== 64) {
1374
- this.setVolumeEnvelope(channel, note);
1375
- }
1376
- }
1377
- if (channel.pressureTable[3] !== 0) {
1378
- this.setModLfoToPitch(channel, note);
1379
- }
1380
- if (channel.pressureTable[4] !== 0) {
1381
- this.setModLfoToFilterFc(channel, note);
1382
- }
1383
- if (channel.pressureTable[5] !== 0) {
1384
- this.setModLfoToVolume(channel, note);
1385
- }
1386
- }
1387
1359
  handlePitchBendMessage(channelNumber, lsb, msb) {
1388
1360
  const pitchBend = msb * 128 + lsb;
1389
1361
  this.setPitchBend(channelNumber, pitchBend);
@@ -1395,16 +1367,13 @@ class MidyGM2 {
1395
1367
  const next = (value - 8192) / 8192;
1396
1368
  state.pitchWheel = value / 16383;
1397
1369
  channel.detune += (next - prev) * state.pitchWheelSensitivity * 12800;
1398
- this.updateDetune(channel);
1370
+ this.updateChannelDetune(channel);
1399
1371
  this.applyVoiceParams(channel, 14);
1400
1372
  }
1401
- setModLfoToPitch(channel, note) {
1373
+ setModLfoToPitch(channel, note, pressure) {
1402
1374
  const now = this.audioContext.currentTime;
1403
- const pressureDepth = channel.pressureTable[3] / 127 * 600;
1404
- const pressure = pressureDepth * channel.state.channelPressure;
1405
1375
  const modLfoToPitch = note.voiceParams.modLfoToPitch + pressure;
1406
- const baseDepth = Math.abs(modLfoToPitch) +
1407
- channel.state.modulationDepth;
1376
+ const baseDepth = Math.abs(modLfoToPitch) + channel.state.modulationDepth;
1408
1377
  const modulationDepth = baseDepth * Math.sign(modLfoToPitch);
1409
1378
  note.modulationDepth.gain
1410
1379
  .cancelScheduledValues(now)
@@ -1420,22 +1389,18 @@ class MidyGM2 {
1420
1389
  .cancelScheduledValues(now)
1421
1390
  .setValueAtTime(vibratoDepth * vibratoDepthSign, now);
1422
1391
  }
1423
- setModLfoToFilterFc(channel, note) {
1392
+ setModLfoToFilterFc(note, pressure) {
1424
1393
  const now = this.audioContext.currentTime;
1425
- const pressureDepth = channel.pressureTable[4] / 127 * 2400;
1426
- const pressure = pressureDepth * channel.state.channelPressure;
1427
1394
  const modLfoToFilterFc = note.voiceParams.modLfoToFilterFc + pressure;
1428
1395
  note.filterDepth.gain
1429
1396
  .cancelScheduledValues(now)
1430
1397
  .setValueAtTime(modLfoToFilterFc, now);
1431
1398
  }
1432
- setModLfoToVolume(channel, note) {
1399
+ setModLfoToVolume(note, pressure) {
1433
1400
  const now = this.audioContext.currentTime;
1434
1401
  const modLfoToVolume = note.voiceParams.modLfoToVolume;
1435
1402
  const baseDepth = this.cbToRatio(Math.abs(modLfoToVolume)) - 1;
1436
- const pressureDepth = channel.pressureTable[5] / 127;
1437
- const pressure = 1 + pressureDepth * channel.state.channelPressure;
1438
- const volumeDepth = baseDepth * Math.sign(modLfoToVolume) * pressure;
1403
+ const volumeDepth = baseDepth * Math.sign(modLfoToVolume) * (1 + pressure);
1439
1404
  note.volumeDepth.gain
1440
1405
  .cancelScheduledValues(now)
1441
1406
  .setValueAtTime(volumeDepth, now);
@@ -1508,11 +1473,18 @@ class MidyGM2 {
1508
1473
  .cancelScheduledValues(now)
1509
1474
  .setValueAtTime(freqModLFO, now);
1510
1475
  }
1476
+ setFreqVibLFO(channel, note) {
1477
+ const now = this.audioContext.currentTime;
1478
+ const freqVibLFO = note.voiceParams.freqVibLFO;
1479
+ note.vibratoLFO.frequency
1480
+ .cancelScheduledValues(now)
1481
+ .setValueAtTime(freqVibLFO * channel.state.vibratoRate * 2, now);
1482
+ }
1511
1483
  createVoiceParamsHandlers() {
1512
1484
  return {
1513
1485
  modLfoToPitch: (channel, note, _prevValue) => {
1514
1486
  if (0 < channel.state.modulationDepth) {
1515
- this.setModLfoToPitch(channel, note);
1487
+ this.setModLfoToPitch(channel, note, 0);
1516
1488
  }
1517
1489
  },
1518
1490
  vibLfoToPitch: (channel, note, _prevValue) => {
@@ -1522,12 +1494,12 @@ class MidyGM2 {
1522
1494
  },
1523
1495
  modLfoToFilterFc: (channel, note, _prevValue) => {
1524
1496
  if (0 < channel.state.modulationDepth) {
1525
- this.setModLfoToFilterFc(channel, note);
1497
+ this.setModLfoToFilterFc(note, 0);
1526
1498
  }
1527
1499
  },
1528
1500
  modLfoToVolume: (channel, note, _prevValue) => {
1529
1501
  if (0 < channel.state.modulationDepth) {
1530
- this.setModLfoToVolume(channel, note);
1502
+ this.setModLfoToVolume(note, 0);
1531
1503
  }
1532
1504
  },
1533
1505
  chorusEffectsSend: (channel, note, prevValue) => {
@@ -1553,11 +1525,7 @@ class MidyGM2 {
1553
1525
  },
1554
1526
  freqVibLFO: (channel, note, _prevValue) => {
1555
1527
  if (0 < channel.state.vibratoDepth) {
1556
- const now = this.audioContext.currentTime;
1557
- const freqVibLFO = note.voiceParams.freqVibLFO;
1558
- note.vibratoLFO.frequency
1559
- .cancelScheduledValues(now)
1560
- .setValueAtTime(freqVibLFO * channel.state.vibratoRate, now);
1528
+ this.setFreqVibLFO(channel, note);
1561
1529
  }
1562
1530
  },
1563
1531
  };
@@ -1601,7 +1569,7 @@ class MidyGM2 {
1601
1569
  this.setPortamentoStartFilterEnvelope(channel, note);
1602
1570
  }
1603
1571
  else {
1604
- this.setFilterEnvelope(channel, note);
1572
+ this.setFilterEnvelope(channel, note, 0);
1605
1573
  }
1606
1574
  this.setPitchEnvelope(note);
1607
1575
  }
@@ -1615,7 +1583,7 @@ class MidyGM2 {
1615
1583
  if (key in voiceParams)
1616
1584
  noteVoiceParams[key] = voiceParams[key];
1617
1585
  }
1618
- this.setVolumeEnvelope(channel, note);
1586
+ this.setVolumeEnvelope(note, 0);
1619
1587
  }
1620
1588
  }
1621
1589
  }
@@ -1654,7 +1622,7 @@ class MidyGM2 {
1654
1622
  if (handler) {
1655
1623
  handler.call(this, channelNumber, value);
1656
1624
  const channel = this.channels[channelNumber];
1657
- this.applyVoiceParams(channel, controller + 128);
1625
+ this.applyVoiceParams(channel, controllerType + 128);
1658
1626
  this.applyControlTable(channel, controllerType);
1659
1627
  }
1660
1628
  else {
@@ -1947,7 +1915,7 @@ class MidyGM2 {
1947
1915
  const next = value / 128;
1948
1916
  state.pitchWheelSensitivity = next;
1949
1917
  channel.detune += (state.pitchWheel * 2 - 1) * (next - prev) * 12800;
1950
- this.updateDetune(channel);
1918
+ this.updateChannelDetune(channel);
1951
1919
  this.applyVoiceParams(channel, 16);
1952
1920
  }
1953
1921
  handleFineTuningRPN(channelNumber) {
@@ -1962,7 +1930,7 @@ class MidyGM2 {
1962
1930
  const next = (value - 8192) / 8.192; // cent
1963
1931
  channel.fineTuning = next;
1964
1932
  channel.detune += next - prev;
1965
- this.updateDetune(channel);
1933
+ this.updateChannelDetune(channel);
1966
1934
  }
1967
1935
  handleCoarseTuningRPN(channelNumber) {
1968
1936
  const channel = this.channels[channelNumber];
@@ -1976,7 +1944,7 @@ class MidyGM2 {
1976
1944
  const next = (value - 64) * 100; // cent
1977
1945
  channel.coarseTuning = next;
1978
1946
  channel.detune += next - prev;
1979
- this.updateDetune(channel);
1947
+ this.updateChannelDetune(channel);
1980
1948
  }
1981
1949
  handleModulationDepthRangeRPN(channelNumber) {
1982
1950
  const channel = this.channels[channelNumber];
@@ -2007,7 +1975,7 @@ class MidyGM2 {
2007
1975
  const state = channel.state;
2008
1976
  for (let i = 0; i < stateTypes.length; i++) {
2009
1977
  const type = stateTypes[i];
2010
- state[type] = defaultControllerState[type];
1978
+ state[type] = defaultControllerState[type].defaultValue;
2011
1979
  }
2012
1980
  const settingTypes = [
2013
1981
  "rpnMSB",
@@ -2101,7 +2069,7 @@ class MidyGM2 {
2101
2069
  case 9:
2102
2070
  switch (data[3]) {
2103
2071
  case 1: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca22.pdf
2104
- return this.handleChannelPressureSysEx(data);
2072
+ return this.handlePressureSysEx(data, "channelPressureTable");
2105
2073
  case 3: // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca22.pdf
2106
2074
  return this.handleControlChangeSysEx(data);
2107
2075
  default:
@@ -2143,7 +2111,7 @@ class MidyGM2 {
2143
2111
  const next = (value - 8192) / 8.192; // cent
2144
2112
  this.masterFineTuning = next;
2145
2113
  channel.detune += next - prev;
2146
- this.updateDetune(channel);
2114
+ this.updateChannelDetune(channel);
2147
2115
  }
2148
2116
  handleMasterCoarseTuningSysEx(data) {
2149
2117
  const coarseTuning = data[4];
@@ -2154,7 +2122,7 @@ class MidyGM2 {
2154
2122
  const next = (value - 64) * 100; // cent
2155
2123
  this.masterCoarseTuning = next;
2156
2124
  channel.detune += next - prev;
2157
- this.updateDetune(channel);
2125
+ this.updateChannelDetune(channel);
2158
2126
  }
2159
2127
  handleGlobalParameterControlSysEx(data) {
2160
2128
  if (data[7] === 1) {
@@ -2378,29 +2346,44 @@ class MidyGM2 {
2378
2346
  }
2379
2347
  applyDestinationSettings(channel, note, table) {
2380
2348
  if (table[0] !== 64) {
2381
- this.updateDetune(channel);
2349
+ this.updateDetune(channel, note, 0);
2382
2350
  }
2383
2351
  if (!note.portamento) {
2384
2352
  if (table[1] !== 64) {
2385
- this.setFilterEnvelope(channel, note);
2353
+ const channelPressure = channel.channelPressureTable[1] *
2354
+ channel.state.channelPressure;
2355
+ const pressure = (channelPressure - 64) * 15;
2356
+ this.setFilterEnvelope(channel, note, pressure);
2386
2357
  }
2387
2358
  if (table[2] !== 64) {
2388
- this.setVolumeEnvelope(channel, note);
2359
+ const channelPressure = channel.channelPressureTable[2] *
2360
+ channel.state.channelPressure;
2361
+ const pressure = channelPressure / 64;
2362
+ this.setVolumeEnvelope(note, pressure);
2389
2363
  }
2390
2364
  }
2391
2365
  if (table[3] !== 0) {
2392
- this.setModLfoToPitch(channel, note);
2366
+ const channelPressure = channel.channelPressureTable[3] *
2367
+ channel.state.channelPressure;
2368
+ const pressure = channelPressure / 127 * 600;
2369
+ this.setModLfoToPitch(channel, note, pressure);
2393
2370
  }
2394
2371
  if (table[4] !== 0) {
2395
- this.setModLfoToFilterFc(channel, note);
2372
+ const channelPressure = channel.channelPressureTable[4] *
2373
+ channel.state.channelPressure;
2374
+ const pressure = channelPressure / 127 * 2400;
2375
+ this.setModLfoToFilterFc(note, pressure);
2396
2376
  }
2397
2377
  if (table[5] !== 0) {
2398
- this.setModLfoToVolume(channel, note);
2378
+ const channelPressure = channel.channelPressureTable[5] *
2379
+ channel.state.channelPressure;
2380
+ const pressure = channelPressure / 127;
2381
+ this.setModLfoToVolume(note, pressure);
2399
2382
  }
2400
2383
  }
2401
- handleChannelPressureSysEx(data) {
2384
+ handleChannelPressureSysEx(data, tableName) {
2402
2385
  const channelNumber = data[4];
2403
- const table = this.channels[channelNumber].pressureTable;
2386
+ const table = this.channels[channelNumber][tableName];
2404
2387
  for (let i = 5; i < data.length - 1; i += 2) {
2405
2388
  const pp = data[i];
2406
2389
  const rr = data[i + 1];
@@ -2492,7 +2475,7 @@ Object.defineProperty(MidyGM2, "channelSettings", {
2492
2475
  currentBufferSource: null,
2493
2476
  detune: 0,
2494
2477
  scaleOctaveTuningTable: new Array(12).fill(0), // cent
2495
- pressureTable: new Uint8Array([64, 64, 64, 0, 0, 0]),
2478
+ channelPressureTable: new Uint8Array([64, 64, 64, 0, 0, 0]),
2496
2479
  keyBasedInstrumentControlTable: new Int8Array(128 * 128), // [-64, 63]
2497
2480
  program: 0,
2498
2481
  bank: 121 * 128,
@@ -2507,16 +2490,3 @@ Object.defineProperty(MidyGM2, "channelSettings", {
2507
2490
  modulationDepthRange: 50, // cent
2508
2491
  }
2509
2492
  });
2510
- Object.defineProperty(MidyGM2, "controllerDestinationSettings", {
2511
- enumerable: true,
2512
- configurable: true,
2513
- writable: true,
2514
- value: {
2515
- pitchControl: 0,
2516
- filterCutoffControl: 0,
2517
- amplitudeControl: 1,
2518
- lfoPitchDepth: 0,
2519
- lfoFilterDepth: 0,
2520
- lfoAmplitudeDepth: 0,
2521
- }
2522
- });
@@ -94,7 +94,8 @@ export class MidyGMLite {
94
94
  centToRate(cent: any): number;
95
95
  centToHz(cent: any): number;
96
96
  calcChannelDetune(channel: any): number;
97
- updateDetune(channel: any): void;
97
+ updateChannelDetune(channel: any): void;
98
+ updateDetune(channel: any, note: any): void;
98
99
  setVolumeEnvelope(note: any): void;
99
100
  setPitchEnvelope(note: any): void;
100
101
  clampCutoffFrequency(frequency: any): number;
@@ -163,7 +164,7 @@ export class MidyGMLite {
163
164
  setRPNLSB(channelNumber: any, value: any): void;
164
165
  dataEntryMSB(channelNumber: any, value: any): void;
165
166
  handlePitchBendRangeRPN(channelNumber: any): void;
166
- setPitchBendRange(channelNumber: any, pitchWheelSensitivity: any): void;
167
+ setPitchBendRange(channelNumber: any, value: any): void;
167
168
  allSoundOff(channelNumber: any): Promise<void>;
168
169
  resetAllControllers(channelNumber: any): void;
169
170
  allNotesOff(channelNumber: any): Promise<void>;