spessasynth_core 3.26.17 → 3.26.19

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.
Files changed (62) hide show
  1. package/index.js +5 -3
  2. package/package.json +1 -1
  3. package/src/externals/README.md +6 -0
  4. package/src/sequencer/README.md +5 -1
  5. package/src/soundfont/README.md +6 -8
  6. package/src/soundfont/basic_soundfont/basic_global_zone.js +16 -0
  7. package/src/soundfont/basic_soundfont/basic_instrument.js +26 -22
  8. package/src/soundfont/basic_soundfont/basic_instrument_zone.js +35 -0
  9. package/src/soundfont/basic_soundfont/basic_preset.js +53 -42
  10. package/src/soundfont/basic_soundfont/basic_preset_zone.js +30 -0
  11. package/src/soundfont/basic_soundfont/{basic_soundfont.js → basic_soundbank.js} +96 -55
  12. package/src/soundfont/basic_soundfont/basic_zone.js +73 -5
  13. package/src/soundfont/basic_soundfont/generator.js +4 -163
  14. package/src/soundfont/basic_soundfont/generator_types.js +151 -0
  15. package/src/soundfont/basic_soundfont/modulator.js +217 -65
  16. package/src/soundfont/basic_soundfont/write_dls/art2.js +3 -2
  17. package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +28 -45
  18. package/src/soundfont/basic_soundfont/write_dls/ins.js +11 -27
  19. package/src/soundfont/basic_soundfont/write_dls/modulator_converter.js +2 -2
  20. package/src/soundfont/basic_soundfont/write_dls/rgn2.js +2 -2
  21. package/src/soundfont/basic_soundfont/write_sf2/ibag.js +22 -19
  22. package/src/soundfont/basic_soundfont/write_sf2/igen.js +33 -29
  23. package/src/soundfont/basic_soundfont/write_sf2/imod.js +26 -16
  24. package/src/soundfont/basic_soundfont/write_sf2/inst.js +4 -5
  25. package/src/soundfont/basic_soundfont/write_sf2/pbag.js +21 -18
  26. package/src/soundfont/basic_soundfont/write_sf2/pgen.js +32 -29
  27. package/src/soundfont/basic_soundfont/write_sf2/phdr.js +4 -2
  28. package/src/soundfont/basic_soundfont/write_sf2/pmod.js +26 -16
  29. package/src/soundfont/basic_soundfont/write_sf2/write.js +14 -8
  30. package/src/soundfont/dls/articulator_converter.js +9 -3
  31. package/src/soundfont/dls/dls_preset.js +2 -3
  32. package/src/soundfont/dls/dls_soundfont.js +2 -3
  33. package/src/soundfont/dls/dls_sources.js +7 -6
  34. package/src/soundfont/dls/dls_zone.js +13 -16
  35. package/src/soundfont/dls/read_articulation.js +2 -1
  36. package/src/soundfont/dls/read_instrument.js +7 -10
  37. package/src/soundfont/dls/read_lart.js +5 -5
  38. package/src/soundfont/dls/read_region.js +3 -3
  39. package/src/soundfont/read_sf2/instruments.js +10 -1
  40. package/src/soundfont/read_sf2/modulators.js +10 -23
  41. package/src/soundfont/read_sf2/presets.js +10 -1
  42. package/src/soundfont/read_sf2/soundfont.js +3 -5
  43. package/src/soundfont/read_sf2/zones.js +30 -70
  44. package/src/synthetizer/README.md +3 -3
  45. package/src/synthetizer/audio_engine/README.md +1 -1
  46. package/src/synthetizer/audio_engine/engine_components/compute_modulator.js +20 -19
  47. package/src/synthetizer/audio_engine/engine_components/dynamic_modulator_system.js +11 -3
  48. package/src/synthetizer/audio_engine/engine_components/lowpass_filter.js +1 -1
  49. package/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js +1 -1
  50. package/src/synthetizer/audio_engine/engine_components/modulation_envelope.js +1 -1
  51. package/src/synthetizer/audio_engine/engine_components/stereo_panner.js +1 -1
  52. package/src/synthetizer/audio_engine/engine_components/voice.js +7 -10
  53. package/src/synthetizer/audio_engine/engine_components/volume_envelope.js +2 -1
  54. package/src/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +0 -4
  55. package/src/synthetizer/audio_engine/engine_methods/data_entry/awe32.js +1 -1
  56. package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +7 -0
  57. package/src/synthetizer/audio_engine/engine_methods/note_on.js +1 -1
  58. package/src/synthetizer/audio_engine/engine_methods/render_voice.js +1 -1
  59. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +1 -1
  60. package/src/synthetizer/audio_engine/engine_methods/system_exclusive.js +2 -1
  61. package/src/utils/README.md +5 -2
  62. package/src/soundfont/basic_soundfont/basic_zones.js +0 -43
@@ -3,6 +3,8 @@
3
3
  * @property {number} min - the minimum midi note
4
4
  * @property {number} max - the maximum midi note
5
5
  */
6
+ import { generatorTypes } from "./generator_types.js";
7
+ import { Generator } from "./generator.js";
6
8
 
7
9
  export class BasicZone
8
10
  {
@@ -19,11 +21,7 @@ export class BasicZone
19
21
  * @type {SoundFontRange}
20
22
  */
21
23
  keyRange = { min: -1, max: 127 };
22
- /**
23
- * Indicates if the zone is global
24
- * @type {boolean}
25
- */
26
- isGlobal = false;
24
+
27
25
  /**
28
26
  * The zone's generators
29
27
  * @type {Generator[]}
@@ -51,6 +49,76 @@ export class BasicZone
51
49
  return this.velRange.min !== -1;
52
50
  }
53
51
 
52
+ /**
53
+ * Adds at the start
54
+ * @param generator {Generator}
55
+ */
56
+ prependGenerator(generator)
57
+ {
58
+ this.generators.unshift(generator);
59
+ }
60
+
61
+ /**
62
+ * @param type {generatorTypes}
63
+ * @param value {number}
64
+ */
65
+ setGenerator(type, value)
66
+ {
67
+ switch (type)
68
+ {
69
+ case generatorTypes.sampleID:
70
+ throw new Error("Use setSample()");
71
+ case generatorTypes.instrument:
72
+ throw new Error("Use setInstrument()");
73
+
74
+ case generatorTypes.velRange:
75
+ case generatorTypes.keyRange:
76
+ throw new Error("Set the range manually");
77
+ }
78
+ let generator = this.generators.find(g => g.generatorType === type);
79
+ if (generator)
80
+ {
81
+ generator.generatorValue = value;
82
+ }
83
+ else
84
+ {
85
+ this.addGenerators(new Generator(type, value));
86
+ }
87
+ }
88
+
89
+ /**
90
+ * @param generators {Generator}
91
+ */
92
+ addGenerators(...generators)
93
+ {
94
+ generators.forEach(g =>
95
+ {
96
+ switch (g.generatorType)
97
+ {
98
+ default:
99
+ this.generators.push(g);
100
+ break;
101
+
102
+ case generatorTypes.velRange:
103
+ this.velRange.min = g.generatorValue & 0x7F;
104
+ this.velRange.max = (g.generatorValue >> 8) & 0x7F;
105
+ break;
106
+
107
+ case generatorTypes.keyRange:
108
+ this.keyRange.min = g.generatorValue & 0x7F;
109
+ this.keyRange.max = (g.generatorValue >> 8) & 0x7F;
110
+ }
111
+ });
112
+ }
113
+
114
+ /**
115
+ * @param modulators {Modulator}
116
+ */
117
+ addModulators(...modulators)
118
+ {
119
+ this.modulators.push(...modulators);
120
+ }
121
+
54
122
  /**
55
123
  * @param generatorType {generatorTypes}
56
124
  * @param notFoundValue {number}
@@ -1,156 +1,6 @@
1
- /**
2
- * @enum {number}
3
- */
4
- export const generatorTypes = {
5
- INVALID: -1, // invalid generator
6
- startAddrsOffset: 0, // sample control - moves sample start point
7
- endAddrOffset: 1, // sample control - moves sample end point
8
- startloopAddrsOffset: 2, // loop control - moves loop start point
9
- endloopAddrsOffset: 3, // loop control - moves loop end point
10
- startAddrsCoarseOffset: 4, // sample control - moves sample start point in 32,768 increments
11
- modLfoToPitch: 5, // pitch modulation - modulation lfo pitch modulation in cents
12
- vibLfoToPitch: 6, // pitch modulation - vibrato lfo pitch modulation in cents
13
- modEnvToPitch: 7, // pitch modulation - modulation envelope pitch modulation in cents
14
- initialFilterFc: 8, // filter - lowpass filter cutoff in cents
15
- initialFilterQ: 9, // filter - lowpass filter resonance
16
- modLfoToFilterFc: 10, // filter modulation - modulation lfo lowpass filter cutoff in cents
17
- modEnvToFilterFc: 11, // filter modulation - modulation envelope lowpass filter cutoff in cents
18
- endAddrsCoarseOffset: 12, // ample control - move sample end point in 32,768 increments
19
- modLfoToVolume: 13, // modulation lfo - volume (tremolo), where 100 = 10dB
20
- unused1: 14, // unused
21
- chorusEffectsSend: 15, // effect send - how much is sent to chorus 0 - 1000
22
- reverbEffectsSend: 16, // effect send - how much is sent to reverb 0 - 1000
23
- pan: 17, // panning - where -500 = left, 0 = center, 500 = right
24
- unused2: 18, // unused
25
- unused3: 19, // unused
26
- unused4: 20, // unused
27
- delayModLFO: 21, // mod lfo - delay for mod lfo to start from zero
28
- freqModLFO: 22, // mod lfo - frequency of mod lfo, 0 = 8.176 Hz, units: f => 1200log2(f/8.176)
29
- delayVibLFO: 23, // vib lfo - delay for vibrato lfo to start from zero
30
- freqVibLFO: 24, // vib lfo - frequency of vibrato lfo, 0 = 8.176Hz, unit: f => 1200log2(f/8.176)
31
- delayModEnv: 25, // mod env - 0 = 1 s decay till mod env starts
32
- attackModEnv: 26, // mod env - attack of mod env
33
- holdModEnv: 27, // mod env - hold of mod env
34
- decayModEnv: 28, // mod env - decay of mod env
35
- sustainModEnv: 29, // mod env - sustain of mod env
36
- releaseModEnv: 30, // mod env - release of mod env
37
- keyNumToModEnvHold: 31, // mod env - also modulating mod envelope hold with key number
38
- keyNumToModEnvDecay: 32, // mod env - also modulating mod envelope decay with key number
39
- delayVolEnv: 33, // vol env - delay of envelope from zero (weird scale)
40
- attackVolEnv: 34, // vol env - attack of envelope
41
- holdVolEnv: 35, // vol env - hold of envelope
42
- decayVolEnv: 36, // vol env - decay of envelope
43
- sustainVolEnv: 37, // vol env - sustain of envelope
44
- releaseVolEnv: 38, // vol env - release of envelope
45
- keyNumToVolEnvHold: 39, // vol env - key number to volume envelope hold
46
- keyNumToVolEnvDecay: 40, // vol env - key number to volume envelope decay
47
- instrument: 41, // zone - instrument index to use for preset zone
48
- reserved1: 42, // reserved
49
- keyRange: 43, // zone - key range for which preset / instrument zone is active
50
- velRange: 44, // zone - velocity range for which preset / instrument zone is active
51
- startloopAddrsCoarseOffset: 45, // sample control - moves sample loop start point in 32,768 increments
52
- keyNum: 46, // zone - instrument only: always use this midi number (ignore what's pressed)
53
- velocity: 47, // zone - instrument only: always use this velocity (ignore what's pressed)
54
- initialAttenuation: 48, // zone - allows turning down the volume, 10 = -1dB
55
- reserved2: 49, // reserved
56
- endloopAddrsCoarseOffset: 50, // sample control - moves sample loop end point in 32,768 increments
57
- coarseTune: 51, // tune - pitch offset in semitones
58
- fineTune: 52, // tune - pitch offset in cents
59
- sampleID: 53, // sample - instrument zone only: which sample to use
60
- sampleModes: 54, // sample - 0 = no loop, 1 = loop, 2 = reserved, 3 = loop and play till the end in release phase
61
- reserved3: 55, // reserved
62
- scaleTuning: 56, // sample - the degree to which MIDI key number influences pitch, 100 = default
63
- exclusiveClass: 57, // sample - = cut = choke group
64
- overridingRootKey: 58, // sample - can override the sample's original pitch
65
- unused5: 59, // unused
66
- endOper: 60, // end marker
67
-
68
- // additional generators that are used in system exclusives and will not be saved
69
- vibLfoToVolume: 61,
70
- vibLfoToFilterFc: 62
71
- };
72
- export const GENERATORS_AMOUNT = Object.keys(generatorTypes).length;
73
- export const MAX_GENERATOR = Math.max(...Object.values(generatorTypes));
74
-
75
- /**
76
- * @type {{min: number, max: number, def: number, nrpn: number}[]}
77
- * min: minimum value, max: maximum value, def: default value, nrpn: nprn scale...
78
- */
79
- const generatorLimits = [];
80
- // offsets
81
- generatorLimits[generatorTypes.startAddrsOffset] = { min: 0, max: 32768, def: 0, nrpn: 1 };
82
- generatorLimits[generatorTypes.endAddrOffset] = { min: -32768, max: 32768, def: 0, nrpn: 1 };
83
- generatorLimits[generatorTypes.startloopAddrsOffset] = { min: -32768, max: 32768, def: 0, nrpn: 1 };
84
- generatorLimits[generatorTypes.endloopAddrsOffset] = { min: -32768, max: 32768, def: 0, nrpn: 1 };
85
- generatorLimits[generatorTypes.startAddrsCoarseOffset] = { min: 0, max: 32768, def: 0, nrpn: 1 };
86
-
87
- // pitch influence
88
- generatorLimits[generatorTypes.modLfoToPitch] = { min: -12000, max: 12000, def: 0, nrpn: 2 };
89
- generatorLimits[generatorTypes.vibLfoToPitch] = { min: -12000, max: 12000, def: 0, nrpn: 2 };
90
- generatorLimits[generatorTypes.modEnvToPitch] = { min: -12000, max: 12000, def: 0, nrpn: 2 };
91
-
92
- // lowpass
93
- generatorLimits[generatorTypes.initialFilterFc] = { min: 1500, max: 13500, def: 13500, nrpn: 2 };
94
- generatorLimits[generatorTypes.initialFilterQ] = { min: 0, max: 960, def: 0, nrpn: 1 };
95
- generatorLimits[generatorTypes.modLfoToFilterFc] = { min: -12000, max: 12000, def: 0, nrpn: 2 };
96
- generatorLimits[generatorTypes.vibLfoToFilterFc] = { min: -12000, max: 12000, def: 0, nrpn: 2 }; // NON-STANDARD
97
- generatorLimits[generatorTypes.modEnvToFilterFc] = { min: -12000, max: 12000, def: 0, nrpn: 2 };
98
-
99
- generatorLimits[generatorTypes.endAddrsCoarseOffset] = { min: -32768, max: 32768, def: 0, nrpn: 1 };
100
-
101
- generatorLimits[generatorTypes.modLfoToVolume] = { min: -960, max: 960, def: 0, nrpn: 1 };
102
- generatorLimits[generatorTypes.vibLfoToVolume] = { min: -960, max: 960, def: 0, nrpn: 1 }; // NON-STANDARD
103
-
104
- // effects, pan
105
- generatorLimits[generatorTypes.chorusEffectsSend] = { min: 0, max: 1000, def: 0, nrpn: 1 };
106
- generatorLimits[generatorTypes.reverbEffectsSend] = { min: 0, max: 1000, def: 0, nrpn: 1 };
107
- generatorLimits[generatorTypes.pan] = { min: -500, max: 500, def: 0, nrpn: 1 };
1
+ import { generatorLimits, generatorTypes } from "./generator_types.js";
108
2
 
109
- // lfo
110
- generatorLimits[generatorTypes.delayModLFO] = { min: -12000, max: 5000, def: -12000, nrpn: 2 };
111
- generatorLimits[generatorTypes.freqModLFO] = { min: -16000, max: 4500, def: 0, nrpn: 4 };
112
- generatorLimits[generatorTypes.delayVibLFO] = { min: -12000, max: 5000, def: -12000, nrpn: 2 };
113
- generatorLimits[generatorTypes.freqVibLFO] = { min: -16000, max: 4500, def: 0, nrpn: 4 };
114
-
115
- // mod env
116
- generatorLimits[generatorTypes.delayModEnv] = { min: -32768, max: 5000, def: -32768, nrpn: 2 }; // -32,768 indicates instant phase,
117
- // this is done to prevent click at the start of filter modenv
118
- generatorLimits[generatorTypes.attackModEnv] = { min: -32768, max: 8000, def: -32768, nrpn: 2 };
119
- generatorLimits[generatorTypes.holdModEnv] = { min: -12000, max: 5000, def: -12000, nrpn: 2 };
120
- generatorLimits[generatorTypes.decayModEnv] = { min: -12000, max: 8000, def: -12000, nrpn: 2 };
121
- generatorLimits[generatorTypes.sustainModEnv] = { min: 0, max: 1000, def: 0, nrpn: 1 };
122
- generatorLimits[generatorTypes.releaseModEnv] = { min: -7200, max: 8000, def: -12000, nrpn: 2 }; // min is set to -7200 to prevent lowpass clicks
123
- // key num to mod env
124
- generatorLimits[generatorTypes.keyNumToModEnvHold] = { min: -1200, max: 1200, def: 0, nrpn: 1 };
125
- generatorLimits[generatorTypes.keyNumToModEnvDecay] = { min: -1200, max: 1200, def: 0, nrpn: 1 };
126
-
127
- // vol env
128
- generatorLimits[generatorTypes.delayVolEnv] = { min: -12000, max: 5000, def: -12000, nrpn: 2 };
129
- generatorLimits[generatorTypes.attackVolEnv] = { min: -12000, max: 8000, def: -12000, nrpn: 2 };
130
- generatorLimits[generatorTypes.holdVolEnv] = { min: -12000, max: 5000, def: -12000, nrpn: 2 };
131
- generatorLimits[generatorTypes.decayVolEnv] = { min: -12000, max: 8000, def: -12000, nrpn: 2 };
132
- generatorLimits[generatorTypes.sustainVolEnv] = { min: 0, max: 1440, def: 0, nrpn: 1 };
133
- generatorLimits[generatorTypes.releaseVolEnv] = { min: -7200, max: 8000, def: -12000, nrpn: 2 }; // min is set to -7200 prevent clicks
134
- // key num to vol env
135
- generatorLimits[generatorTypes.keyNumToVolEnvHold] = { min: -1200, max: 1200, def: 0, nrpn: 1 };
136
- generatorLimits[generatorTypes.keyNumToVolEnvDecay] = { min: -1200, max: 1200, def: 0, nrpn: 1 };
137
-
138
- generatorLimits[generatorTypes.startloopAddrsCoarseOffset] = { min: -32768, max: 32768, def: 0, nrpn: 1 };
139
- generatorLimits[generatorTypes.keyNum] = { min: -1, max: 127, def: -1, nrpn: 1 };
140
- generatorLimits[generatorTypes.velocity] = { min: -1, max: 127, def: -1, nrpn: 1 };
141
-
142
- generatorLimits[generatorTypes.initialAttenuation] = { min: 0, max: 1440, def: 0, nrpn: 1 };
143
-
144
- generatorLimits[generatorTypes.endloopAddrsCoarseOffset] = { min: -32768, max: 32768, def: 0, nrpn: 1 };
145
-
146
- generatorLimits[generatorTypes.coarseTune] = { min: -120, max: 120, def: 0, nrpn: 1 };
147
- generatorLimits[generatorTypes.fineTune] = { min: -12700, max: 12700, def: 0, nrpn: 1 }; // this generator is used as initial pitch, hence this range
148
- generatorLimits[generatorTypes.scaleTuning] = { min: 0, max: 1200, def: 100, nrpn: 1 };
149
- generatorLimits[generatorTypes.exclusiveClass] = { min: 0, max: 99999, def: 0, nrpn: 0 };
150
- generatorLimits[generatorTypes.overridingRootKey] = { min: 0 - 1, max: 127, def: -1, nrpn: 0 };
151
- generatorLimits[generatorTypes.sampleModes] = { min: 0, max: 3, def: 0, nrpn: 0 };
152
-
153
- export { generatorLimits };
3
+ export const GEN_BYTE_SIZE = 4;
154
4
 
155
5
  export class Generator
156
6
  {
@@ -218,15 +68,6 @@ export function addAndClampGenerator(generatorType, presetGens, instrumentGens)
218
68
  instruValue = instruGen.generatorValue;
219
69
  }
220
70
 
221
- let value = instruValue + presetValue;
222
-
223
- // Special case, initial attenuation.
224
- // Shall get clamped in the volume envelope,
225
- // so the modulators can be affected by negative generators (the "Brass" patch was problematic...)
226
- if (generatorType === generatorTypes.initialAttenuation)
227
- {
228
- return value;
229
- }
230
-
231
- return Math.max(limits.min, Math.min(limits.max, value));
71
+ // limits are applied in the compute_modulator function
72
+ return instruValue + presetValue;
232
73
  }
@@ -0,0 +1,151 @@
1
+ /**
2
+ * @enum {number}
3
+ */
4
+ export const generatorTypes = {
5
+ INVALID: -1, // invalid generator
6
+ startAddrsOffset: 0, // sample control - moves sample start point
7
+ endAddrOffset: 1, // sample control - moves sample end point
8
+ startloopAddrsOffset: 2, // loop control - moves loop start point
9
+ endloopAddrsOffset: 3, // loop control - moves loop end point
10
+ startAddrsCoarseOffset: 4, // sample control - moves sample start point in 32,768 increments
11
+ modLfoToPitch: 5, // pitch modulation - modulation lfo pitch modulation in cents
12
+ vibLfoToPitch: 6, // pitch modulation - vibrato lfo pitch modulation in cents
13
+ modEnvToPitch: 7, // pitch modulation - modulation envelope pitch modulation in cents
14
+ initialFilterFc: 8, // filter - lowpass filter cutoff in cents
15
+ initialFilterQ: 9, // filter - lowpass filter resonance
16
+ modLfoToFilterFc: 10, // filter modulation - modulation lfo lowpass filter cutoff in cents
17
+ modEnvToFilterFc: 11, // filter modulation - modulation envelope lowpass filter cutoff in cents
18
+ endAddrsCoarseOffset: 12, // ample control - move sample end point in 32,768 increments
19
+ modLfoToVolume: 13, // modulation lfo - volume (tremolo), where 100 = 10dB
20
+ unused1: 14, // unused
21
+ chorusEffectsSend: 15, // effect send - how much is sent to chorus 0 - 1000
22
+ reverbEffectsSend: 16, // effect send - how much is sent to reverb 0 - 1000
23
+ pan: 17, // panning - where -500 = left, 0 = center, 500 = right
24
+ unused2: 18, // unused
25
+ unused3: 19, // unused
26
+ unused4: 20, // unused
27
+ delayModLFO: 21, // mod lfo - delay for mod lfo to start from zero
28
+ freqModLFO: 22, // mod lfo - frequency of mod lfo, 0 = 8.176 Hz, units: f => 1200log2(f/8.176)
29
+ delayVibLFO: 23, // vib lfo - delay for vibrato lfo to start from zero
30
+ freqVibLFO: 24, // vib lfo - frequency of vibrato lfo, 0 = 8.176Hz, unit: f => 1200log2(f/8.176)
31
+ delayModEnv: 25, // mod env - 0 = 1 s decay till mod env starts
32
+ attackModEnv: 26, // mod env - attack of mod env
33
+ holdModEnv: 27, // mod env - hold of mod env
34
+ decayModEnv: 28, // mod env - decay of mod env
35
+ sustainModEnv: 29, // mod env - sustain of mod env
36
+ releaseModEnv: 30, // mod env - release of mod env
37
+ keyNumToModEnvHold: 31, // mod env - also modulating mod envelope hold with key number
38
+ keyNumToModEnvDecay: 32, // mod env - also modulating mod envelope decay with key number
39
+ delayVolEnv: 33, // vol env - delay of envelope from zero (weird scale)
40
+ attackVolEnv: 34, // vol env - attack of envelope
41
+ holdVolEnv: 35, // vol env - hold of envelope
42
+ decayVolEnv: 36, // vol env - decay of envelope
43
+ sustainVolEnv: 37, // vol env - sustain of envelope
44
+ releaseVolEnv: 38, // vol env - release of envelope
45
+ keyNumToVolEnvHold: 39, // vol env - key number to volume envelope hold
46
+ keyNumToVolEnvDecay: 40, // vol env - key number to volume envelope decay
47
+ instrument: 41, // zone - instrument index to use for preset zone
48
+ reserved1: 42, // reserved
49
+ keyRange: 43, // zone - key range for which preset / instrument zone is active
50
+ velRange: 44, // zone - velocity range for which preset / instrument zone is active
51
+ startloopAddrsCoarseOffset: 45, // sample control - moves sample loop start point in 32,768 increments
52
+ keyNum: 46, // zone - instrument only: always use this midi number (ignore what's pressed)
53
+ velocity: 47, // zone - instrument only: always use this velocity (ignore what's pressed)
54
+ initialAttenuation: 48, // zone - allows turning down the volume, 10 = -1dB
55
+ reserved2: 49, // reserved
56
+ endloopAddrsCoarseOffset: 50, // sample control - moves sample loop end point in 32,768 increments
57
+ coarseTune: 51, // tune - pitch offset in semitones
58
+ fineTune: 52, // tune - pitch offset in cents
59
+ sampleID: 53, // sample - instrument zone only: which sample to use
60
+ sampleModes: 54, // sample - 0 = no loop, 1 = loop, 2 = reserved, 3 = loop and play till the end in release phase
61
+ reserved3: 55, // reserved
62
+ scaleTuning: 56, // sample - the degree to which MIDI key number influences pitch, 100 = default
63
+ exclusiveClass: 57, // sample - = cut = choke group
64
+ overridingRootKey: 58, // sample - can override the sample's original pitch
65
+ unused5: 59, // unused
66
+ endOper: 60, // end marker
67
+
68
+ // additional generators that are used in system exclusives and will not be saved
69
+ vibLfoToVolume: 61,
70
+ vibLfoToFilterFc: 62
71
+ };
72
+ export const GENERATORS_AMOUNT = Object.keys(generatorTypes).length;
73
+ export const MAX_GENERATOR = Math.max(...Object.values(generatorTypes));
74
+ /**
75
+ * @type {{min: number, max: number, def: number, nrpn: number}[]}
76
+ * min: minimum value, max: maximum value, def: default value, nrpn: nprn scale...
77
+ */
78
+ const generatorLimits = [];
79
+ // offsets
80
+ generatorLimits[generatorTypes.startAddrsOffset] = { min: 0, max: 32768, def: 0, nrpn: 1 };
81
+ generatorLimits[generatorTypes.endAddrOffset] = { min: -32768, max: 32768, def: 0, nrpn: 1 };
82
+ generatorLimits[generatorTypes.startloopAddrsOffset] = { min: -32768, max: 32768, def: 0, nrpn: 1 };
83
+ generatorLimits[generatorTypes.endloopAddrsOffset] = { min: -32768, max: 32768, def: 0, nrpn: 1 };
84
+ generatorLimits[generatorTypes.startAddrsCoarseOffset] = { min: 0, max: 32768, def: 0, nrpn: 1 };
85
+
86
+ // pitch influence
87
+ generatorLimits[generatorTypes.modLfoToPitch] = { min: -12000, max: 12000, def: 0, nrpn: 2 };
88
+ generatorLimits[generatorTypes.vibLfoToPitch] = { min: -12000, max: 12000, def: 0, nrpn: 2 };
89
+ generatorLimits[generatorTypes.modEnvToPitch] = { min: -12000, max: 12000, def: 0, nrpn: 2 };
90
+
91
+ // lowpass
92
+ generatorLimits[generatorTypes.initialFilterFc] = { min: 1500, max: 13500, def: 13500, nrpn: 2 };
93
+ generatorLimits[generatorTypes.initialFilterQ] = { min: 0, max: 960, def: 0, nrpn: 1 };
94
+ generatorLimits[generatorTypes.modLfoToFilterFc] = { min: -12000, max: 12000, def: 0, nrpn: 2 };
95
+ generatorLimits[generatorTypes.vibLfoToFilterFc] = { min: -12000, max: 12000, def: 0, nrpn: 2 }; // NON-STANDARD
96
+ generatorLimits[generatorTypes.modEnvToFilterFc] = { min: -12000, max: 12000, def: 0, nrpn: 2 };
97
+
98
+ generatorLimits[generatorTypes.endAddrsCoarseOffset] = { min: -32768, max: 32768, def: 0, nrpn: 1 };
99
+
100
+ generatorLimits[generatorTypes.modLfoToVolume] = { min: -960, max: 960, def: 0, nrpn: 1 };
101
+ generatorLimits[generatorTypes.vibLfoToVolume] = { min: -960, max: 960, def: 0, nrpn: 1 }; // NON-STANDARD
102
+
103
+ // effects, pan
104
+ generatorLimits[generatorTypes.chorusEffectsSend] = { min: 0, max: 1000, def: 0, nrpn: 1 };
105
+ generatorLimits[generatorTypes.reverbEffectsSend] = { min: 0, max: 1000, def: 0, nrpn: 1 };
106
+ generatorLimits[generatorTypes.pan] = { min: -500, max: 500, def: 0, nrpn: 1 };
107
+
108
+ // lfo
109
+ generatorLimits[generatorTypes.delayModLFO] = { min: -12000, max: 5000, def: -12000, nrpn: 2 };
110
+ generatorLimits[generatorTypes.freqModLFO] = { min: -16000, max: 4500, def: 0, nrpn: 4 };
111
+ generatorLimits[generatorTypes.delayVibLFO] = { min: -12000, max: 5000, def: -12000, nrpn: 2 };
112
+ generatorLimits[generatorTypes.freqVibLFO] = { min: -16000, max: 4500, def: 0, nrpn: 4 };
113
+
114
+ // mod env
115
+ generatorLimits[generatorTypes.delayModEnv] = { min: -32768, max: 5000, def: -32768, nrpn: 2 }; // -32,768 indicates instant phase,
116
+ // this is done to prevent click at the start of filter modenv
117
+ generatorLimits[generatorTypes.attackModEnv] = { min: -32768, max: 8000, def: -32768, nrpn: 2 };
118
+ generatorLimits[generatorTypes.holdModEnv] = { min: -12000, max: 5000, def: -12000, nrpn: 2 };
119
+ generatorLimits[generatorTypes.decayModEnv] = { min: -12000, max: 8000, def: -12000, nrpn: 2 };
120
+ generatorLimits[generatorTypes.sustainModEnv] = { min: 0, max: 1000, def: 0, nrpn: 1 };
121
+ generatorLimits[generatorTypes.releaseModEnv] = { min: -7200, max: 8000, def: -12000, nrpn: 2 }; // min is set to -7200 to prevent lowpass clicks
122
+ // key num to mod env
123
+ generatorLimits[generatorTypes.keyNumToModEnvHold] = { min: -1200, max: 1200, def: 0, nrpn: 1 };
124
+ generatorLimits[generatorTypes.keyNumToModEnvDecay] = { min: -1200, max: 1200, def: 0, nrpn: 1 };
125
+
126
+ // vol env
127
+ generatorLimits[generatorTypes.delayVolEnv] = { min: -12000, max: 5000, def: -12000, nrpn: 2 };
128
+ generatorLimits[generatorTypes.attackVolEnv] = { min: -12000, max: 8000, def: -12000, nrpn: 2 };
129
+ generatorLimits[generatorTypes.holdVolEnv] = { min: -12000, max: 5000, def: -12000, nrpn: 2 };
130
+ generatorLimits[generatorTypes.decayVolEnv] = { min: -12000, max: 8000, def: -12000, nrpn: 2 };
131
+ generatorLimits[generatorTypes.sustainVolEnv] = { min: 0, max: 1440, def: 0, nrpn: 1 };
132
+ generatorLimits[generatorTypes.releaseVolEnv] = { min: -7200, max: 8000, def: -12000, nrpn: 2 }; // min is set to -7200 prevent clicks
133
+ // key num to vol env
134
+ generatorLimits[generatorTypes.keyNumToVolEnvHold] = { min: -1200, max: 1200, def: 0, nrpn: 1 };
135
+ generatorLimits[generatorTypes.keyNumToVolEnvDecay] = { min: -1200, max: 1200, def: 0, nrpn: 1 };
136
+
137
+ generatorLimits[generatorTypes.startloopAddrsCoarseOffset] = { min: -32768, max: 32768, def: 0, nrpn: 1 };
138
+ generatorLimits[generatorTypes.keyNum] = { min: -1, max: 127, def: -1, nrpn: 1 };
139
+ generatorLimits[generatorTypes.velocity] = { min: -1, max: 127, def: -1, nrpn: 1 };
140
+
141
+ generatorLimits[generatorTypes.initialAttenuation] = { min: 0, max: 1440, def: 0, nrpn: 1 };
142
+
143
+ generatorLimits[generatorTypes.endloopAddrsCoarseOffset] = { min: -32768, max: 32768, def: 0, nrpn: 1 };
144
+
145
+ generatorLimits[generatorTypes.coarseTune] = { min: -120, max: 120, def: 0, nrpn: 1 };
146
+ generatorLimits[generatorTypes.fineTune] = { min: -12700, max: 12700, def: 0, nrpn: 1 }; // this generator is used as initial pitch, hence this range
147
+ generatorLimits[generatorTypes.scaleTuning] = { min: 0, max: 1200, def: 100, nrpn: 1 };
148
+ generatorLimits[generatorTypes.exclusiveClass] = { min: 0, max: 99999, def: 0, nrpn: 0 };
149
+ generatorLimits[generatorTypes.overridingRootKey] = { min: 0 - 1, max: 127, def: -1, nrpn: 0 };
150
+ generatorLimits[generatorTypes.sampleModes] = { min: 0, max: 3, def: 0, nrpn: 0 };
151
+ export { generatorLimits };