@marmooo/midy 0.2.0 → 0.2.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.
package/esm/midy-GM2.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export class MidyGM2 {
2
2
  static channelSettings: {
3
3
  currentBufferSource: null;
4
+ detune: number;
5
+ scaleOctaveTuningTable: any[];
4
6
  program: number;
5
7
  bank: number;
6
8
  bankMSB: number;
@@ -182,12 +184,15 @@ export class MidyGM2 {
182
184
  feedbackGains: any[];
183
185
  };
184
186
  cbToRatio(cb: any): number;
187
+ rateToCent(rate: any): number;
188
+ centToRate(cent: any): number;
185
189
  centToHz(cent: any): number;
186
- calcSemitoneOffset(channel: any): any;
190
+ calcDetune(channel: any, note: any): any;
191
+ calcNoteDetune(channel: any, note: any): any;
192
+ updateDetune(channel: any): void;
187
193
  setPortamentoStartVolumeEnvelope(channel: any, note: any): void;
188
194
  setVolumeEnvelope(note: any): void;
189
- setPlaybackRate(note: any): void;
190
- setPitch(channel: any, note: any): void;
195
+ setPitchEnvelope(note: any): void;
191
196
  clampCutoffFrequency(frequency: any): number;
192
197
  setPortamentoStartFilterEnvelope(channel: any, note: any): void;
193
198
  setFilterEnvelope(channel: any, note: any): void;
@@ -208,11 +213,11 @@ export class MidyGM2 {
208
213
  handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
209
214
  setPitchBend(channelNumber: any, value: any): void;
210
215
  setModLfoToPitch(channel: any, note: any): void;
216
+ setVibLfoToPitch(channel: any, note: any): void;
217
+ setModLfoToFilterFc(note: any): void;
211
218
  setModLfoToVolume(note: any): void;
212
219
  setChorusEffectsSend(note: any, prevValue: any): void;
213
220
  setReverbEffectsSend(note: any, prevValue: any): void;
214
- setVibLfoToPitch(channel: any, note: any): void;
215
- setModLfoToFilterFc(note: any): void;
216
221
  setDelayModLFO(note: any): void;
217
222
  setFreqModLFO(note: any): void;
218
223
  createVoiceParamsHandlers(): {
@@ -282,13 +287,12 @@ export class MidyGM2 {
282
287
  setRPNMSB(channelNumber: any, value: any): void;
283
288
  setRPNLSB(channelNumber: any, value: any): void;
284
289
  dataEntryMSB(channelNumber: any, value: any): void;
285
- updateDetune(channel: any, detune: any): void;
286
290
  handlePitchBendRangeRPN(channelNumber: any): void;
287
- setPitchBendRange(channelNumber: any, pitchWheelSensitivity: any): void;
291
+ setPitchBendRange(channelNumber: any, value: any): void;
288
292
  handleFineTuningRPN(channelNumber: any): void;
289
- setFineTuning(channelNumber: any, fineTuning: any): void;
293
+ setFineTuning(channelNumber: any, value: any): void;
290
294
  handleCoarseTuningRPN(channelNumber: any): void;
291
- setCoarseTuning(channelNumber: any, coarseTuning: any): void;
295
+ setCoarseTuning(channelNumber: any, value: any): void;
292
296
  handleModulationDepthRangeRPN(channelNumber: any): void;
293
297
  setModulationDepthRange(channelNumber: any, modulationDepthRange: any): void;
294
298
  allSoundOff(channelNumber: any): Promise<void>;
@@ -305,9 +309,11 @@ export class MidyGM2 {
305
309
  handleMasterVolumeSysEx(data: any): void;
306
310
  setMasterVolume(volume: any): void;
307
311
  handleMasterFineTuningSysEx(data: any): void;
308
- setMasterFineTuning(fineTuning: any): void;
312
+ setMasterFineTuning(value: any): void;
309
313
  handleMasterCoarseTuningSysEx(data: any): void;
310
- setMasterCoarseTuning(coarseTuning: any): void;
314
+ setMasterCoarseTuning(value: any): void;
315
+ getChannelBitmap(data: any): any[];
316
+ handleScaleOctaveTuning1ByteFormat(data: any): void;
311
317
  handleGlobalParameterControlSysEx(data: any): void;
312
318
  handleReverbParameterSysEx(data: any): void;
313
319
  setReverbType(type: 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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"}
package/esm/midy-GM2.js CHANGED
@@ -898,16 +898,42 @@ export class MidyGM2 {
898
898
  cbToRatio(cb) {
899
899
  return Math.pow(10, cb / 200);
900
900
  }
901
+ rateToCent(rate) {
902
+ return 1200 * Math.log2(rate);
903
+ }
904
+ centToRate(cent) {
905
+ return Math.pow(2, cent / 1200);
906
+ }
901
907
  centToHz(cent) {
902
- return 8.176 * Math.pow(2, cent / 1200);
908
+ return 8.176 * this.centToRate(cent);
903
909
  }
904
- calcSemitoneOffset(channel) {
910
+ calcDetune(channel, note) {
905
911
  const masterTuning = this.masterCoarseTuning + this.masterFineTuning;
906
912
  const channelTuning = channel.coarseTuning + channel.fineTuning;
913
+ const scaleOctaveTuning = channel.scaleOctaveTuningTable[note.noteNumber % 12];
914
+ const tuning = masterTuning + channelTuning + scaleOctaveTuning;
907
915
  const pitchWheel = channel.state.pitchWheel * 2 - 1;
908
- const pitchWheelSensitivity = channel.state.pitchWheelSensitivity * 128;
916
+ const pitchWheelSensitivity = channel.state.pitchWheelSensitivity * 12800;
909
917
  const pitch = pitchWheel * pitchWheelSensitivity;
910
- return masterTuning + channelTuning + pitch;
918
+ return tuning + pitch;
919
+ }
920
+ calcNoteDetune(channel, note) {
921
+ return channel.scaleOctaveTuningTable[note.noteNumber % 12];
922
+ }
923
+ updateDetune(channel) {
924
+ const now = this.audioContext.currentTime;
925
+ channel.scheduledNotes.forEach((noteList) => {
926
+ for (let i = 0; i < noteList.length; i++) {
927
+ const note = noteList[i];
928
+ if (!note)
929
+ continue;
930
+ const noteDetune = this.calcNoteDetune(channel, note);
931
+ const detune = channel.detune + noteDetune;
932
+ note.bufferSource.detune
933
+ .cancelScheduledValues(now)
934
+ .setValueAtTime(detune, now);
935
+ }
936
+ });
911
937
  }
912
938
  setPortamentoStartVolumeEnvelope(channel, note) {
913
939
  const now = this.audioContext.currentTime;
@@ -938,32 +964,28 @@ export class MidyGM2 {
938
964
  .setValueAtTime(attackVolume, volHold)
939
965
  .linearRampToValueAtTime(sustainVolume, volDecay);
940
966
  }
941
- setPlaybackRate(note) {
967
+ setPitchEnvelope(note) {
942
968
  const now = this.audioContext.currentTime;
969
+ const { voiceParams } = note;
970
+ const baseRate = voiceParams.playbackRate;
943
971
  note.bufferSource.playbackRate
944
972
  .cancelScheduledValues(now)
945
- .setValueAtTime(note.voiceParams.playbackRate, now);
946
- }
947
- setPitch(channel, note) {
948
- const now = this.audioContext.currentTime;
949
- const { startTime } = note;
950
- const basePitch = this.calcSemitoneOffset(channel) * 100;
951
- note.bufferSource.detune
952
- .cancelScheduledValues(now)
953
- .setValueAtTime(basePitch, startTime);
954
- const modEnvToPitch = note.voiceParams.modEnvToPitch;
973
+ .setValueAtTime(baseRate, now);
974
+ const modEnvToPitch = voiceParams.modEnvToPitch;
955
975
  if (modEnvToPitch === 0)
956
976
  return;
977
+ const basePitch = this.rateToCent(baseRate);
957
978
  const peekPitch = basePitch + modEnvToPitch;
979
+ const peekRate = this.centToRate(peekPitch);
958
980
  const modDelay = startTime + voiceParams.modDelay;
959
981
  const modAttack = modDelay + voiceParams.modAttack;
960
982
  const modHold = modAttack + voiceParams.modHold;
961
983
  const modDecay = modHold + voiceParams.modDecay;
962
- note.bufferSource.detune
963
- .setValueAtTime(basePitch, modDelay)
964
- .exponentialRampToValueAtTime(peekPitch, modAttack)
965
- .setValueAtTime(peekPitch, modHold)
966
- .linearRampToValueAtTime(basePitch, modDecay);
984
+ note.bufferSource.playbackRate
985
+ .setValueAtTime(baseRate, modDelay)
986
+ .exponentialRampToValueAtTime(peekRate, modAttack)
987
+ .setValueAtTime(peekRate, modHold)
988
+ .linearRampToValueAtTime(baseRate, modDecay);
967
989
  }
968
990
  clampCutoffFrequency(frequency) {
969
991
  const minFrequency = 20; // min Hz of initialFilterFc
@@ -1074,9 +1096,8 @@ export class MidyGM2 {
1074
1096
  if (0 < state.vibratoDepth) {
1075
1097
  this.startVibrato(channel, note, startTime);
1076
1098
  }
1077
- this.setPlaybackRate(note);
1099
+ this.setPitchEnvelope(note);
1078
1100
  if (0 < state.modulationDepth) {
1079
- this.setPitch(channel, note);
1080
1101
  this.startModulation(channel, note, startTime);
1081
1102
  }
1082
1103
  if (this.mono && channel.currentBufferSource) {
@@ -1209,11 +1230,12 @@ export class MidyGM2 {
1209
1230
  }
1210
1231
  else {
1211
1232
  const portamentoTime = endTime + state.portamentoTime;
1212
- const detuneChange = (portamentoNoteNumber - noteNumber) * 100;
1213
- const detune = note.bufferSource.detune.value + detuneChange;
1214
- note.bufferSource.detune
1233
+ const deltaNote = portamentoNoteNumber - noteNumber;
1234
+ const baseRate = note.voiceParams.playbackRate;
1235
+ const targetRate = baseRate * Math.pow(2, deltaNote / 12);
1236
+ note.bufferSource.playbackRate
1215
1237
  .cancelScheduledValues(endTime)
1216
- .linearRampToValueAtTime(detune, portamentoTime);
1238
+ .linearRampToValueAtTime(targetRate, portamentoTime);
1217
1239
  return this.stopNote(endTime, portamentoTime, scheduledNotes, i);
1218
1240
  }
1219
1241
  }
@@ -1300,10 +1322,11 @@ export class MidyGM2 {
1300
1322
  setPitchBend(channelNumber, value) {
1301
1323
  const channel = this.channels[channelNumber];
1302
1324
  const state = channel.state;
1325
+ const prev = state.pitchWheel * 2 - 1;
1326
+ const next = (value - 8192) / 8192;
1303
1327
  state.pitchWheel = value / 16383;
1304
- const pitchWheel = (value - 8192) / 8192;
1305
- const detuneChange = pitchWheel * state.pitchWheelSensitivity * 12800;
1306
- this.updateDetune(channel, detuneChange);
1328
+ channel.detune += (next - prev) * state.pitchWheelSensitivity * 12800;
1329
+ this.updateDetune(channel);
1307
1330
  this.applyVoiceParams(channel, 14);
1308
1331
  }
1309
1332
  setModLfoToPitch(channel, note) {
@@ -1316,6 +1339,23 @@ export class MidyGM2 {
1316
1339
  .cancelScheduledValues(now)
1317
1340
  .setValueAtTime(modulationDepth * modulationDepthSign, now);
1318
1341
  }
1342
+ setVibLfoToPitch(channel, note) {
1343
+ const now = this.audioContext.currentTime;
1344
+ const vibLfoToPitch = note.voiceParams.vibLfoToPitch;
1345
+ const vibratoDepth = Math.abs(vibLfoToPitch) * channel.state.vibratoDepth *
1346
+ 2;
1347
+ const vibratoDepthSign = 0 < vibLfoToPitch;
1348
+ note.vibratoDepth.gain
1349
+ .cancelScheduledValues(now)
1350
+ .setValueAtTime(vibratoDepth * vibratoDepthSign, now);
1351
+ }
1352
+ setModLfoToFilterFc(note) {
1353
+ const now = this.audioContext.currentTime;
1354
+ const modLfoToFilterFc = note.voiceParams.modLfoToFilterFc;
1355
+ note.filterDepth.gain
1356
+ .cancelScheduledValues(now)
1357
+ .setValueAtTime(modLfoToFilterFc, now);
1358
+ }
1319
1359
  setModLfoToVolume(note) {
1320
1360
  const now = this.audioContext.currentTime;
1321
1361
  const modLfoToVolume = note.voiceParams.modLfoToVolume;
@@ -1375,23 +1415,6 @@ export class MidyGM2 {
1375
1415
  }
1376
1416
  }
1377
1417
  }
1378
- setVibLfoToPitch(channel, note) {
1379
- const now = this.audioContext.currentTime;
1380
- const vibLfoToPitch = note.voiceParams.vibLfoToPitch;
1381
- const vibratoDepth = Math.abs(vibLfoToPitch) * channel.state.vibratoDepth *
1382
- 2;
1383
- const vibratoDepthSign = 0 < vibLfoToPitch;
1384
- note.vibratoDepth.gain
1385
- .cancelScheduledValues(now)
1386
- .setValueAtTime(vibratoDepth * vibratoDepthSign, now);
1387
- }
1388
- setModLfoToFilterFc(note) {
1389
- const now = this.audioContext.currentTime;
1390
- const modLfoToFilterFc = note.voiceParams.modLfoToFilterFc;
1391
- note.filterDepth.gain
1392
- .cancelScheduledValues(now)
1393
- .setValueAtTime(modLfoToFilterFc, now);
1394
- }
1395
1418
  setDelayModLFO(note) {
1396
1419
  const now = this.audioContext.currentTime;
1397
1420
  const startTime = note.startTime;
@@ -1500,7 +1523,7 @@ export class MidyGM2 {
1500
1523
  else {
1501
1524
  this.setFilterEnvelope(channel, note);
1502
1525
  }
1503
- this.setPitch(channel, note);
1526
+ this.setPitchEnvelope(note);
1504
1527
  }
1505
1528
  else if (volumeEnvelopeKeySet.has(key)) {
1506
1529
  if (appliedVolumeEnvelope)
@@ -1572,7 +1595,7 @@ export class MidyGM2 {
1572
1595
  note.modulationDepth.gain.setValueAtTime(channel.state.modulationDepth, now);
1573
1596
  }
1574
1597
  else {
1575
- this.setPitch(channel, note);
1598
+ this.setPitchEnvelope(note);
1576
1599
  this.startModulation(channel, note, now);
1577
1600
  }
1578
1601
  }
@@ -1793,59 +1816,49 @@ export class MidyGM2 {
1793
1816
  this.channels[channelNumber].dataMSB = value;
1794
1817
  this.handleRPN(channelNumber);
1795
1818
  }
1796
- updateDetune(channel, detune) {
1797
- const now = this.audioContext.currentTime;
1798
- channel.scheduledNotes.forEach((noteList) => {
1799
- for (let i = 0; i < noteList.length; i++) {
1800
- const note = noteList[i];
1801
- if (!note)
1802
- continue;
1803
- const { bufferSource } = note;
1804
- bufferSource.detune
1805
- .cancelScheduledValues(now)
1806
- .setValueAtTime(detune, now);
1807
- }
1808
- });
1809
- }
1810
1819
  handlePitchBendRangeRPN(channelNumber) {
1811
1820
  const channel = this.channels[channelNumber];
1812
1821
  this.limitData(channel, 0, 127, 0, 99);
1813
1822
  const pitchBendRange = channel.dataMSB + channel.dataLSB / 100;
1814
1823
  this.setPitchBendRange(channelNumber, pitchBendRange);
1815
1824
  }
1816
- setPitchBendRange(channelNumber, pitchWheelSensitivity) {
1825
+ setPitchBendRange(channelNumber, value) {
1817
1826
  const channel = this.channels[channelNumber];
1818
1827
  const state = channel.state;
1819
- state.pitchWheelSensitivity = pitchWheelSensitivity / 128;
1820
- const detune = (state.pitchWheel * 2 - 1) * pitchWheelSensitivity * 100;
1821
- this.updateDetune(channel, detune);
1828
+ const prev = state.pitchWheelSensitivity;
1829
+ const next = value / 128;
1830
+ state.pitchWheelSensitivity = next;
1831
+ channel.detune += (state.pitchWheel * 2 - 1) * (next - prev) * 12800;
1832
+ this.updateDetune(channel);
1822
1833
  this.applyVoiceParams(channel, 16);
1823
1834
  }
1824
1835
  handleFineTuningRPN(channelNumber) {
1825
1836
  const channel = this.channels[channelNumber];
1826
1837
  this.limitData(channel, 0, 127, 0, 127);
1827
- const fineTuning = (channel.dataMSB * 128 + channel.dataLSB - 8192) / 8192;
1838
+ const fineTuning = channel.dataMSB * 128 + channel.dataLSB;
1828
1839
  this.setFineTuning(channelNumber, fineTuning);
1829
1840
  }
1830
- setFineTuning(channelNumber, fineTuning) {
1841
+ setFineTuning(channelNumber, value) {
1831
1842
  const channel = this.channels[channelNumber];
1832
- const prevFineTuning = channel.fineTuning;
1833
- channel.fineTuning = fineTuning;
1834
- const detuneChange = channel.fineTuning - prevFineTuning;
1835
- this.updateDetune(channel, detuneChange);
1843
+ const prev = channel.fineTuning;
1844
+ const next = (value - 8192) / 8.192; // cent
1845
+ channel.fineTuning = next;
1846
+ channel.detune += next - prev;
1847
+ this.updateDetune(channel);
1836
1848
  }
1837
1849
  handleCoarseTuningRPN(channelNumber) {
1838
1850
  const channel = this.channels[channelNumber];
1839
1851
  this.limitDataMSB(channel, 0, 127);
1840
- const coarseTuning = channel.dataMSB - 64;
1841
- this.setFineTuning(channelNumber, coarseTuning);
1852
+ const coarseTuning = channel.dataMSB;
1853
+ this.setCoarseTuning(channelNumber, coarseTuning);
1842
1854
  }
1843
- setCoarseTuning(channelNumber, coarseTuning) {
1855
+ setCoarseTuning(channelNumber, value) {
1844
1856
  const channel = this.channels[channelNumber];
1845
- const prevCoarseTuning = channel.coarseTuning;
1846
- channel.coarseTuning = coarseTuning;
1847
- const detuneChange = channel.coarseTuning - prevCoarseTuning;
1848
- this.updateDetune(channel, detuneChange);
1857
+ const prev = channel.coarseTuning;
1858
+ const next = (value - 64) * 100; // cent
1859
+ channel.coarseTuning = next;
1860
+ channel.detune += next - prev;
1861
+ this.updateDetune(channel);
1849
1862
  }
1850
1863
  handleModulationDepthRangeRPN(channelNumber) {
1851
1864
  const channel = this.channels[channelNumber];
@@ -1905,6 +1918,15 @@ export class MidyGM2 {
1905
1918
  }
1906
1919
  handleUniversalNonRealTimeExclusiveMessage(data) {
1907
1920
  switch (data[2]) {
1921
+ case 8:
1922
+ switch (data[3]) {
1923
+ case 8:
1924
+ // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/ca21.pdf
1925
+ return this.handleScaleOctaveTuning1ByteFormat(data);
1926
+ default:
1927
+ console.warn(`Unsupported Exclusive Message: ${data}`);
1928
+ }
1929
+ break;
1908
1930
  case 9:
1909
1931
  switch (data[3]) {
1910
1932
  case 1:
@@ -1959,15 +1981,6 @@ export class MidyGM2 {
1959
1981
  console.warn(`Unsupported Exclusive Message: ${data}`);
1960
1982
  }
1961
1983
  break;
1962
- case 8:
1963
- switch (data[3]) {
1964
- // case 8:
1965
- // // TODO
1966
- // return this.handleScaleOctaveTuning1ByteFormat();
1967
- default:
1968
- console.warn(`Unsupported Exclusive Message: ${data}`);
1969
- }
1970
- break;
1971
1984
  case 9:
1972
1985
  switch (data[3]) {
1973
1986
  // case 1:
@@ -2008,27 +2021,59 @@ export class MidyGM2 {
2008
2021
  }
2009
2022
  }
2010
2023
  handleMasterFineTuningSysEx(data) {
2011
- const fineTuning = (data[5] * 128 + data[4] - 8192) / 8192;
2024
+ const fineTuning = data[5] * 128 + data[4];
2012
2025
  this.setMasterFineTuning(fineTuning);
2013
2026
  }
2014
- setMasterFineTuning(fineTuning) {
2015
- if (fineTuning < -1 && 1 < fineTuning) {
2016
- console.error("Master Fine Tuning value is out of range");
2017
- }
2018
- else {
2019
- this.masterFineTuning = fineTuning;
2020
- }
2027
+ setMasterFineTuning(value) {
2028
+ const prev = this.masterFineTuning;
2029
+ const next = (value - 8192) / 8.192; // cent
2030
+ this.masterFineTuning = next;
2031
+ channel.detune += next - prev;
2032
+ this.updateDetune(channel);
2021
2033
  }
2022
2034
  handleMasterCoarseTuningSysEx(data) {
2023
2035
  const coarseTuning = data[4];
2024
2036
  this.setMasterCoarseTuning(coarseTuning);
2025
2037
  }
2026
- setMasterCoarseTuning(coarseTuning) {
2027
- if (coarseTuning < 0 && 127 < coarseTuning) {
2028
- console.error("Master Coarse Tuning value is out of range");
2038
+ setMasterCoarseTuning(value) {
2039
+ const prev = this.masterCoarseTuning;
2040
+ const next = (value - 64) * 100; // cent
2041
+ this.masterCoarseTuning = next;
2042
+ channel.detune += next - prev;
2043
+ this.updateDetune(channel);
2044
+ }
2045
+ getChannelBitmap(data) {
2046
+ const bitmap = new Array(16).fill(false);
2047
+ const ff = data[4] & 0b11;
2048
+ const gg = data[5] & 0x7F;
2049
+ const hh = data[6] & 0x7F;
2050
+ for (let bit = 0; bit < 7; bit++) {
2051
+ if (hh & (1 << bit))
2052
+ bitmap[bit] = true;
2053
+ }
2054
+ for (let bit = 0; bit < 7; bit++) {
2055
+ if (gg & (1 << bit))
2056
+ bitmap[bit + 7] = true;
2057
+ }
2058
+ for (let bit = 0; bit < 2; bit++) {
2059
+ if (ff & (1 << bit))
2060
+ bitmap[bit + 14] = true;
2061
+ }
2062
+ return bitmap;
2063
+ }
2064
+ handleScaleOctaveTuning1ByteFormat(data) {
2065
+ if (data.length < 18) {
2066
+ console.error("Data length is too short");
2067
+ return;
2029
2068
  }
2030
- else {
2031
- this.masterCoarseTuning = coarseTuning - 64;
2069
+ const channelBitmap = this.getChannelBitmap(data);
2070
+ for (let i = 0; i < channelBitmap.length; i++) {
2071
+ if (!channelBitmap[i])
2072
+ continue;
2073
+ for (let j = 0; j < 12; j++) {
2074
+ const value = data[j + 7] - 64; // cent
2075
+ this.channels[i].scaleOctaveTuningTable[j] = value;
2076
+ }
2032
2077
  }
2033
2078
  }
2034
2079
  handleGlobalParameterControlSysEx(data) {
@@ -2248,6 +2293,8 @@ Object.defineProperty(MidyGM2, "channelSettings", {
2248
2293
  writable: true,
2249
2294
  value: {
2250
2295
  currentBufferSource: null,
2296
+ detune: 0,
2297
+ scaleOctaveTuningTable: new Array(12).fill(0), // cent
2251
2298
  program: 0,
2252
2299
  bank: 121 * 128,
2253
2300
  bankMSB: 121,
@@ -1,6 +1,7 @@
1
1
  export class MidyGMLite {
2
2
  static channelSettings: {
3
3
  currentBufferSource: null;
4
+ detune: number;
4
5
  program: number;
5
6
  bank: number;
6
7
  dataMSB: number;
@@ -89,11 +90,13 @@ export class MidyGMLite {
89
90
  getActiveNotes(channel: any, time: any): Map<any, any>;
90
91
  getActiveNote(noteList: any, time: any): any;
91
92
  cbToRatio(cb: any): number;
93
+ rateToCent(rate: any): number;
94
+ centToRate(cent: any): number;
92
95
  centToHz(cent: any): number;
93
- calcSemitoneOffset(channel: any): number;
96
+ calcChannelDetune(channel: any): number;
97
+ updateDetune(channel: any): void;
94
98
  setVolumeEnvelope(note: any): void;
95
- setPlaybackRate(note: any): void;
96
- setPitch(channel: any, note: any): void;
99
+ setPitchEnvelope(note: any): void;
97
100
  clampCutoffFrequency(frequency: any): number;
98
101
  setFilterEnvelope(note: any): void;
99
102
  startModulation(channel: any, note: any, startTime: any): void;
@@ -109,8 +112,8 @@ export class MidyGMLite {
109
112
  handlePitchBendMessage(channelNumber: any, lsb: any, msb: any): void;
110
113
  setPitchBend(channelNumber: any, value: any): void;
111
114
  setModLfoToPitch(channel: any, note: any): void;
112
- setModLfoToVolume(note: any): void;
113
115
  setModLfoToFilterFc(note: any): void;
116
+ setModLfoToVolume(note: any): void;
114
117
  setDelayModLFO(note: any): void;
115
118
  setFreqModLFO(note: any): void;
116
119
  createVoiceParamsHandlers(): {
@@ -159,7 +162,6 @@ export class MidyGMLite {
159
162
  setRPNMSB(channelNumber: any, value: any): void;
160
163
  setRPNLSB(channelNumber: any, value: any): void;
161
164
  dataEntryMSB(channelNumber: any, value: any): void;
162
- updateDetune(channel: any, detune: any): void;
163
165
  handlePitchBendRangeRPN(channelNumber: any): void;
164
166
  setPitchBendRange(channelNumber: any, pitchWheelSensitivity: any): void;
165
167
  allSoundOff(channelNumber: any): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AAmFA;IAoBE;;;;;;;;MAQE;IAEF,+BAQC;IArCD,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;IAClB,iCAA8B;IAa5B,kBAAgC;IAChC,gBAA4C;IAC5C;;;;;;;;;;;MAA2D;IAC3D;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IAKnD,4BAMC;IAED,mCAWC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAUC;IAED,6DA2BC;IAED,iEAUC;IAED,2EA+CC;IAED,mCAOC;IAED,0BAkDC;IAED,uDAEC;IAED,wDAEC;IAED;;;MAgEC;IAED,+EAmBC;IAED,qDAKC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED,2BAEC;IAED,4BAEC;IAED,yCAIC;IAED,mCAgBC;IAED,iCAKC;IAED,wCAmBC;IAED,6CAIC;IAED,mCAuBC;IAED,+DAoBC;IAED,gHA4BC;IAED,kGAgDC;IAED,0EAGC;IAED,qFAwBC;IAED,6HAuBC;IAED,0FAGC;IAED,kEAeC;IAED,gFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,mDAOC;IAED,gDASC;IAED,mCAQC;IAED,qCAMC;IAED,gCAOC;IAED,+BAMC;IAED;;;;;;;;;;;MAqBC;IAED,+EAMC;IAED,0DA6CC;IAED;;;;;;;;;;;;;MAeC;IAED,+EASC;IAED,qCAiBC;IAED,8DAKC;IACD,iDAIC;IAED;;;MAMC;IAED,2CAIC;IAED,yDAIC;IAED,mDAGC;IAED,wCAWC;IAED,sDAKC;IAED,kFAeC;IAED,oCAYC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,8CAYC;IAED,kDAKC;IAED,wEAOC;IAED,+CAEC;IAED,8CAqBC;IAED,+CAEC;IAED,4DAgBC;IAED,oBAMC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AAjtCD;IAQE,0FAMC;IAbD,kBAAa;IACb,gBAAW;IACX,gBAAW;IACX,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAGd,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}
1
+ {"version":3,"file":"midy-GMLite.d.ts","sourceRoot":"","sources":["../src/midy-GMLite.js"],"names":[],"mappings":"AAmFA;IAoBE;;;;;;;;;MASE;IAEF,+BAQC;IAtCD,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;IAClB,iCAA8B;IAc5B,kBAAgC;IAChC,gBAA4C;IAC5C;;;;;;;;;;;MAA2D;IAC3D;;;;;;;;;;;;;MAA+D;IAC/D,gBAAiD;IAKnD,4BAMC;IAED,mCAWC;IAED,gDAMC;IAED,sCASC;IAED;;;;MAeC;IAED,yCAUC;IAED,6DA2BC;IAED,iEAUC;IAED,2EA+CC;IAED,mCAOC;IAED,0BAkDC;IAED,uDAEC;IAED,wDAEC;IAED;;;MAgEC;IAED,+EAmBC;IAED,qDAKC;IAED,uBAKC;IAED,aAGC;IAED,cAKC;IAED,wBAIC;IAED,0BAKC;IAED,wBAOC;IAED,sBAGC;IAED,uDASC;IAED,6CAQC;IAED,2BAEC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,wCAIC;IAED,iCAWC;IAED,mCAgBC;IAED,kCAqBC;IAED,6CAIC;IAED,mCAuBC;IAED,+DAoBC;IAED,gHA2BC;IAED,kGAgDC;IAED,0EAGC;IAED,qFAwBC;IAED,6HAuBC;IAED,0FAGC;IAED,kEAeC;IAED,gFAiBC;IAED,4DAGC;IAED,qEAGC;IAED,mDASC;IAED,gDASC;IAED,qCAMC;IAED,mCAQC;IAED,gCAOC;IAED,+BAMC;IAED;;;;;;;;;;;MAqBC;IAED,+EAMC;IAED,0DA6CC;IAED;;;;;;;;;;;;;MAeC;IAED,+EASC;IAED,qCAiBC;IAED,8DAKC;IACD,iDAIC;IAED;;;MAMC;IAED,2CAIC;IAED,yDAIC;IAED,mDAGC;IAED,wCAWC;IAED,sDAKC;IAED,kFAeC;IAED,oCAYC;IAED,gDAEC;IAED,gDAEC;IAED,mDAGC;IAED,kDAKC;IAED,wEAOC;IAED,+CAEC;IAED,8CAqBC;IAED,+CAEC;IAED,4DAgBC;IAED,oBAMC;IAED,yDAaC;IAED,yCAGC;IAED,mCAQC;IAED,wCAEC;IAED,6BASC;IAED,0DAUC;CACF;AArtCD;IAQE,0FAMC;IAbD,kBAAa;IACb,gBAAW;IACX,gBAAW;IACX,iBAAY;IACZ,mBAAc;IACd,qBAAgB;IAGd,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,WAAkB;IAClB,iBAA8B;CAEjC"}