spessasynth_core 3.26.17 → 3.26.18
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/index.js +5 -3
- package/package.json +1 -1
- package/src/externals/README.md +6 -0
- package/src/sequencer/README.md +5 -1
- package/src/soundfont/README.md +6 -8
- package/src/soundfont/basic_soundfont/basic_global_zone.js +16 -0
- package/src/soundfont/basic_soundfont/basic_instrument.js +26 -22
- package/src/soundfont/basic_soundfont/basic_instrument_zone.js +35 -0
- package/src/soundfont/basic_soundfont/basic_preset.js +45 -42
- package/src/soundfont/basic_soundfont/basic_preset_zone.js +30 -0
- package/src/soundfont/basic_soundfont/{basic_soundfont.js → basic_soundbank.js} +22 -44
- package/src/soundfont/basic_soundfont/basic_zone.js +1 -5
- package/src/soundfont/basic_soundfont/generator.js +2 -152
- package/src/soundfont/basic_soundfont/generator_types.js +151 -0
- package/src/soundfont/basic_soundfont/modulator.js +217 -65
- package/src/soundfont/basic_soundfont/write_dls/art2.js +3 -2
- package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +25 -42
- package/src/soundfont/basic_soundfont/write_dls/ins.js +11 -27
- package/src/soundfont/basic_soundfont/write_dls/modulator_converter.js +2 -2
- package/src/soundfont/basic_soundfont/write_dls/rgn2.js +2 -2
- package/src/soundfont/basic_soundfont/write_sf2/ibag.js +22 -19
- package/src/soundfont/basic_soundfont/write_sf2/igen.js +29 -25
- package/src/soundfont/basic_soundfont/write_sf2/imod.js +24 -14
- package/src/soundfont/basic_soundfont/write_sf2/inst.js +4 -5
- package/src/soundfont/basic_soundfont/write_sf2/pbag.js +21 -18
- package/src/soundfont/basic_soundfont/write_sf2/pgen.js +30 -27
- package/src/soundfont/basic_soundfont/write_sf2/phdr.js +4 -2
- package/src/soundfont/basic_soundfont/write_sf2/pmod.js +25 -15
- package/src/soundfont/dls/articulator_converter.js +9 -3
- package/src/soundfont/dls/dls_preset.js +2 -3
- package/src/soundfont/dls/dls_soundfont.js +1 -1
- package/src/soundfont/dls/dls_sources.js +7 -6
- package/src/soundfont/dls/dls_zone.js +4 -5
- package/src/soundfont/dls/read_articulation.js +2 -1
- package/src/soundfont/dls/read_instrument.js +3 -6
- package/src/soundfont/dls/read_lart.js +1 -1
- package/src/soundfont/dls/read_region.js +2 -1
- package/src/soundfont/read_sf2/instruments.js +10 -1
- package/src/soundfont/read_sf2/modulators.js +10 -23
- package/src/soundfont/read_sf2/presets.js +10 -1
- package/src/soundfont/read_sf2/soundfont.js +1 -2
- package/src/soundfont/read_sf2/zones.js +30 -14
- package/src/synthetizer/README.md +3 -3
- package/src/synthetizer/audio_engine/README.md +1 -1
- package/src/synthetizer/audio_engine/engine_components/compute_modulator.js +1 -1
- package/src/synthetizer/audio_engine/engine_components/dynamic_modulator_system.js +11 -3
- package/src/synthetizer/audio_engine/engine_components/lowpass_filter.js +1 -1
- package/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js +1 -1
- package/src/synthetizer/audio_engine/engine_components/modulation_envelope.js +1 -1
- package/src/synthetizer/audio_engine/engine_components/stereo_panner.js +1 -1
- package/src/synthetizer/audio_engine/engine_components/voice.js +7 -10
- package/src/synthetizer/audio_engine/engine_components/volume_envelope.js +2 -1
- package/src/synthetizer/audio_engine/engine_methods/data_entry/awe32.js +1 -1
- package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +7 -0
- package/src/synthetizer/audio_engine/engine_methods/note_on.js +1 -1
- package/src/synthetizer/audio_engine/engine_methods/render_voice.js +1 -1
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +1 -1
- package/src/synthetizer/audio_engine/engine_methods/system_exclusive.js +2 -1
- package/src/utils/README.md +5 -2
- package/src/soundfont/basic_soundfont/basic_zones.js +0 -43
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import { generatorTypes, MAX_GENERATOR } from "./generator.js";
|
|
2
1
|
import { midiControllers } from "../../midi/midi_message.js";
|
|
2
|
+
import { generatorTypes, MAX_GENERATOR } from "./generator_types.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* modulators.js
|
|
6
6
|
* purpose: parses soundfont modulators and the source enums, also includes the default modulators list
|
|
7
7
|
**/
|
|
8
8
|
|
|
9
|
+
export const MOD_BYTE_SIZE = 10;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @enum {number}
|
|
13
|
+
*/
|
|
9
14
|
export const modulatorSources = {
|
|
10
15
|
noController: 0,
|
|
11
16
|
noteOnVelocity: 2,
|
|
@@ -17,6 +22,11 @@ export const modulatorSources = {
|
|
|
17
22
|
link: 127
|
|
18
23
|
|
|
19
24
|
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
*
|
|
28
|
+
* @enum {number}
|
|
29
|
+
*/
|
|
20
30
|
export const modulatorCurveTypes = {
|
|
21
31
|
linear: 0,
|
|
22
32
|
concave: 1,
|
|
@@ -27,7 +37,7 @@ export const modulatorCurveTypes = {
|
|
|
27
37
|
export class Modulator
|
|
28
38
|
{
|
|
29
39
|
/**
|
|
30
|
-
* The current computed value of this modulator
|
|
40
|
+
* The current computed value of this modulator. Only used in the synthesis engine for local voices
|
|
31
41
|
* @type {number}
|
|
32
42
|
*/
|
|
33
43
|
currentValue = 0;
|
|
@@ -51,18 +61,123 @@ export class Modulator
|
|
|
51
61
|
transformType;
|
|
52
62
|
|
|
53
63
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
64
|
+
* Indicates if the given modulator is chorus or reverb effects modulator.
|
|
65
|
+
* This is done to simulate BASSMIDI effects behavior:
|
|
66
|
+
* - defaults to 1000 transform amount rather than 200
|
|
67
|
+
* - values can be changed, but anything above 200 is 1000
|
|
68
|
+
* (except for values above 1000, they are copied directly)
|
|
69
|
+
* - all values below are multiplied by 5 (200 * 5 = 1000)
|
|
70
|
+
* - still can be disabled if the soundfont has its own modulator curve
|
|
71
|
+
* - this fixes the very low amount of reverb by default and doesn't break soundfonts
|
|
72
|
+
* @type {boolean}
|
|
73
|
+
*/
|
|
74
|
+
isEffectModulator = false;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 1 if the source is bipolar (min is -1, max is 1)
|
|
78
|
+
* otherwise min is 0 and max is 1
|
|
79
|
+
* @type {0|1}
|
|
80
|
+
*/
|
|
81
|
+
sourcePolarity;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 1 if the source is negative (from 1 to 0)
|
|
85
|
+
* @type {0|1}
|
|
86
|
+
*/
|
|
87
|
+
sourceDirection;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 1 if the source uses a MIDI CC
|
|
91
|
+
* @type {0|1}
|
|
92
|
+
*/
|
|
93
|
+
sourceUsesCC;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* source index/CC number
|
|
97
|
+
* @type {modulatorSources|midiControllers}
|
|
98
|
+
*/
|
|
99
|
+
sourceIndex;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* source curve type
|
|
103
|
+
* @type {modulatorCurveTypes}
|
|
104
|
+
*/
|
|
105
|
+
sourceCurveType;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 1 if the source is bipolar (min is -1, max is 1)
|
|
109
|
+
* otherwise min is 0 and max is 1
|
|
110
|
+
* @type {0|1}
|
|
111
|
+
*/
|
|
112
|
+
secSrcPolarity;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* 1 if the source is negative (from 1 to 0)
|
|
116
|
+
* @type {0|1}
|
|
117
|
+
*/
|
|
118
|
+
secSrcDirection;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* 1 if the source uses a MIDI CC
|
|
122
|
+
* @type {0|1}
|
|
123
|
+
*/
|
|
124
|
+
secSrcUsesCC;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* source index/CC number
|
|
128
|
+
* @type {modulatorSources|midiControllers}
|
|
129
|
+
*/
|
|
130
|
+
secSrcIndex;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* source curve type
|
|
134
|
+
* @type {modulatorCurveTypes}
|
|
135
|
+
*/
|
|
136
|
+
secSrcCurveType;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Creates a new SF2 Modulator
|
|
140
|
+
* @param sourceIndex {modulatorSources|midiControllers}
|
|
141
|
+
* @param sourceCurveType {modulatorCurveTypes}
|
|
142
|
+
* @param sourceUsesCC {0|1}
|
|
143
|
+
* @param sourcePolarity {0|1}
|
|
144
|
+
* @param sourceDirection {0|1}
|
|
145
|
+
* @param secSrcIndex {modulatorSources|midiControllers}
|
|
146
|
+
* @param secSrcCurveType {modulatorCurveTypes}
|
|
147
|
+
* @param secSrcUsesCC {0|1}
|
|
148
|
+
* @param secSrcPolarity {0|1}
|
|
149
|
+
* @param secSrcDirection {0|1}
|
|
150
|
+
* @param destination {generatorTypes}
|
|
58
151
|
* @param amount {number}
|
|
59
|
-
* @param transformType {
|
|
152
|
+
* @param transformType {0|2}
|
|
60
153
|
*/
|
|
61
|
-
constructor(
|
|
154
|
+
constructor(sourceIndex,
|
|
155
|
+
sourceCurveType,
|
|
156
|
+
sourceUsesCC,
|
|
157
|
+
sourcePolarity,
|
|
158
|
+
sourceDirection,
|
|
159
|
+
secSrcIndex,
|
|
160
|
+
secSrcCurveType,
|
|
161
|
+
secSrcUsesCC,
|
|
162
|
+
secSrcPolarity,
|
|
163
|
+
secSrcDirection,
|
|
164
|
+
destination,
|
|
165
|
+
amount,
|
|
166
|
+
transformType)
|
|
62
167
|
{
|
|
63
|
-
|
|
168
|
+
this.sourcePolarity = sourcePolarity;
|
|
169
|
+
this.sourceDirection = sourceDirection;
|
|
170
|
+
this.sourceUsesCC = sourceUsesCC;
|
|
171
|
+
this.sourceIndex = sourceIndex;
|
|
172
|
+
this.sourceCurveType = sourceCurveType;
|
|
173
|
+
|
|
174
|
+
this.secSrcPolarity = secSrcPolarity;
|
|
175
|
+
this.secSrcDirection = secSrcDirection;
|
|
176
|
+
this.secSrcUsesCC = secSrcUsesCC;
|
|
177
|
+
this.secSrcIndex = secSrcIndex;
|
|
178
|
+
this.secSrcCurveType = secSrcCurveType;
|
|
179
|
+
|
|
64
180
|
this.modulatorDestination = destination;
|
|
65
|
-
const secondarySourceEnum = secSrcEnum;
|
|
66
181
|
this.transformAmount = amount;
|
|
67
182
|
this.transformType = transformType;
|
|
68
183
|
|
|
@@ -72,41 +187,6 @@ export class Modulator
|
|
|
72
187
|
this.modulatorDestination = generatorTypes.INVALID; // flag as invalid (for linked ones)
|
|
73
188
|
}
|
|
74
189
|
|
|
75
|
-
// decode the source
|
|
76
|
-
this.sourcePolarity = sourceEnum >> 9 & 1;
|
|
77
|
-
this.sourceDirection = sourceEnum >> 8 & 1;
|
|
78
|
-
this.sourceUsesCC = sourceEnum >> 7 & 1;
|
|
79
|
-
this.sourceIndex = sourceEnum & 127;
|
|
80
|
-
this.sourceCurveType = sourceEnum >> 10 & 3;
|
|
81
|
-
|
|
82
|
-
// decode the secondary source
|
|
83
|
-
this.secSrcPolarity = secondarySourceEnum >> 9 & 1;
|
|
84
|
-
this.secSrcDirection = secondarySourceEnum >> 8 & 1;
|
|
85
|
-
this.secSrcUsesCC = secondarySourceEnum >> 7 & 1;
|
|
86
|
-
this.secSrcIndex = secondarySourceEnum & 127;
|
|
87
|
-
this.secSrcCurveType = secondarySourceEnum >> 10 & 3;
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Indicates if the given modulator is chorus or reverb effects modulator.
|
|
91
|
-
* This is done to simulate BASSMIDI effects behavior:
|
|
92
|
-
* - defaults to 1000 transform amount rather than 200
|
|
93
|
-
* - values can be changed, but anything above 200 is 1000
|
|
94
|
-
* (except for values above 1000, they are copied directly)
|
|
95
|
-
* - all values below are multiplied by 5 (200 * 5 = 1000)
|
|
96
|
-
* - still can be disabled if the soundfont has its own modulator curve
|
|
97
|
-
* - this fixes the very low amount of reverb by default and doesn't break soundfonts
|
|
98
|
-
* @type {boolean}
|
|
99
|
-
*/
|
|
100
|
-
this.isEffectModulator =
|
|
101
|
-
(
|
|
102
|
-
sourceEnum === 0x00DB
|
|
103
|
-
|| sourceEnum === 0x00DD
|
|
104
|
-
)
|
|
105
|
-
&& secondarySourceEnum === 0x0
|
|
106
|
-
&& (
|
|
107
|
-
this.modulatorDestination === generatorTypes.reverbEffectsSend
|
|
108
|
-
|| this.modulatorDestination === generatorTypes.chorusEffectsSend
|
|
109
|
-
);
|
|
110
190
|
}
|
|
111
191
|
|
|
112
192
|
/**
|
|
@@ -116,8 +196,16 @@ export class Modulator
|
|
|
116
196
|
static copy(modulator)
|
|
117
197
|
{
|
|
118
198
|
return new Modulator(
|
|
119
|
-
modulator.
|
|
120
|
-
modulator.
|
|
199
|
+
modulator.sourceIndex,
|
|
200
|
+
modulator.sourceCurveType,
|
|
201
|
+
modulator.sourceUsesCC,
|
|
202
|
+
modulator.sourcePolarity,
|
|
203
|
+
modulator.sourceDirection,
|
|
204
|
+
modulator.secSrcIndex,
|
|
205
|
+
modulator.secSrcCurveType,
|
|
206
|
+
modulator.secSrcUsesCC,
|
|
207
|
+
modulator.secSrcPolarity,
|
|
208
|
+
modulator.secSrcDirection,
|
|
121
209
|
modulator.modulatorDestination,
|
|
122
210
|
modulator.transformAmount,
|
|
123
211
|
modulator.transformType
|
|
@@ -174,7 +262,7 @@ export class Modulator
|
|
|
174
262
|
|
|
175
263
|
let secSrcString = getKeyByValue(modulatorCurveTypes, mod.secSrcCurveType);
|
|
176
264
|
secSrcString += mod.secSrcPolarity === 0 ? " unipolar " : " bipolar ";
|
|
177
|
-
secSrcString += mod.
|
|
265
|
+
secSrcString += mod.secSrcDirection === 0 ? "forwards " : "backwards ";
|
|
178
266
|
if (mod.secSrcUsesCC)
|
|
179
267
|
{
|
|
180
268
|
secSrcString += getKeyByValue(midiControllers, mod.secSrcIndex);
|
|
@@ -222,8 +310,16 @@ export class Modulator
|
|
|
222
310
|
sumTransform(modulator)
|
|
223
311
|
{
|
|
224
312
|
return new Modulator(
|
|
225
|
-
this.
|
|
226
|
-
this.
|
|
313
|
+
this.sourceIndex,
|
|
314
|
+
this.sourceCurveType,
|
|
315
|
+
this.sourceUsesCC,
|
|
316
|
+
this.sourcePolarity,
|
|
317
|
+
this.sourceDirection,
|
|
318
|
+
this.secSrcIndex,
|
|
319
|
+
this.secSrcCurveType,
|
|
320
|
+
this.secSrcUsesCC,
|
|
321
|
+
this.secSrcPolarity,
|
|
322
|
+
this.secSrcDirection,
|
|
227
323
|
this.modulatorDestination,
|
|
228
324
|
this.transformAmount + modulator.transformAmount,
|
|
229
325
|
this.transformType
|
|
@@ -231,6 +327,62 @@ export class Modulator
|
|
|
231
327
|
}
|
|
232
328
|
}
|
|
233
329
|
|
|
330
|
+
export class DecodedModulator extends Modulator
|
|
331
|
+
{
|
|
332
|
+
/**
|
|
333
|
+
* reads an SF2 modulator
|
|
334
|
+
* @param sourceEnum {number} SF2 source enum
|
|
335
|
+
* @param secondarySourceEnum {number} SF2 secondary source enum
|
|
336
|
+
* @param destination {generatorTypes|number} destination
|
|
337
|
+
* @param amount {number} amount
|
|
338
|
+
* @param transformType {number} transform type
|
|
339
|
+
*/
|
|
340
|
+
constructor(sourceEnum, secondarySourceEnum, destination, amount, transformType)
|
|
341
|
+
{
|
|
342
|
+
// decode the source
|
|
343
|
+
const sourcePolarity = sourceEnum >> 9 & 1;
|
|
344
|
+
const sourceDirection = sourceEnum >> 8 & 1;
|
|
345
|
+
const sourceUsesCC = sourceEnum >> 7 & 1;
|
|
346
|
+
const sourceIndex = /** @type {modulatorSources} **/ sourceEnum & 127;
|
|
347
|
+
const sourceCurveType = /** @type {modulatorCurveTypes} **/ sourceEnum >> 10 & 3;
|
|
348
|
+
|
|
349
|
+
// decode the secondary source
|
|
350
|
+
const secSrcPolarity = secondarySourceEnum >> 9 & 1;
|
|
351
|
+
const secSrcDirection = secondarySourceEnum >> 8 & 1;
|
|
352
|
+
const secSrcUsesCC = secondarySourceEnum >> 7 & 1;
|
|
353
|
+
const secSrcIndex = /** @type {modulatorSources} **/ secondarySourceEnum & 127;
|
|
354
|
+
const secSrcCurveType = /** @type {modulatorCurveTypes} **/ secondarySourceEnum >> 10 & 3;
|
|
355
|
+
|
|
356
|
+
super(
|
|
357
|
+
sourceIndex,
|
|
358
|
+
sourceCurveType,
|
|
359
|
+
sourceUsesCC,
|
|
360
|
+
sourcePolarity,
|
|
361
|
+
sourceDirection,
|
|
362
|
+
secSrcIndex,
|
|
363
|
+
secSrcCurveType,
|
|
364
|
+
secSrcUsesCC,
|
|
365
|
+
secSrcPolarity,
|
|
366
|
+
secSrcDirection,
|
|
367
|
+
destination,
|
|
368
|
+
amount,
|
|
369
|
+
transformType
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
this.isEffectModulator =
|
|
374
|
+
(
|
|
375
|
+
sourceEnum === 0x00DB
|
|
376
|
+
|| sourceEnum === 0x00DD
|
|
377
|
+
)
|
|
378
|
+
&& secondarySourceEnum === 0x0
|
|
379
|
+
&& (
|
|
380
|
+
this.modulatorDestination === generatorTypes.reverbEffectsSend
|
|
381
|
+
|| this.modulatorDestination === generatorTypes.chorusEffectsSend
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
234
386
|
export const DEFAULT_ATTENUATION_MOD_AMOUNT = 960;
|
|
235
387
|
export const DEFAULT_ATTENUATION_MOD_CURVE_TYPE = modulatorCurveTypes.concave;
|
|
236
388
|
|
|
@@ -241,7 +393,7 @@ export function getModSourceEnum(curveType, polarity, direction, isCC, index)
|
|
|
241
393
|
|
|
242
394
|
const soundFontModulators = [
|
|
243
395
|
// vel to attenuation
|
|
244
|
-
new
|
|
396
|
+
new DecodedModulator(
|
|
245
397
|
getModSourceEnum(
|
|
246
398
|
DEFAULT_ATTENUATION_MOD_CURVE_TYPE,
|
|
247
399
|
0,
|
|
@@ -256,10 +408,10 @@ const soundFontModulators = [
|
|
|
256
408
|
),
|
|
257
409
|
|
|
258
410
|
// mod wheel to vibrato
|
|
259
|
-
new
|
|
411
|
+
new DecodedModulator(0x0081, 0x0, generatorTypes.vibLfoToPitch, 50, 0),
|
|
260
412
|
|
|
261
413
|
// vol to attenuation
|
|
262
|
-
new
|
|
414
|
+
new DecodedModulator(
|
|
263
415
|
getModSourceEnum(
|
|
264
416
|
DEFAULT_ATTENUATION_MOD_CURVE_TYPE,
|
|
265
417
|
0,
|
|
@@ -274,17 +426,17 @@ const soundFontModulators = [
|
|
|
274
426
|
),
|
|
275
427
|
|
|
276
428
|
// channel pressure to vibrato
|
|
277
|
-
new
|
|
429
|
+
new DecodedModulator(0x000D, 0x0, generatorTypes.vibLfoToPitch, 50, 0),
|
|
278
430
|
|
|
279
431
|
// pitch wheel to tuning
|
|
280
|
-
new
|
|
432
|
+
new DecodedModulator(0x020E, 0x0010, generatorTypes.fineTune, 12700, 0),
|
|
281
433
|
|
|
282
434
|
// pan to uhh, pan
|
|
283
435
|
// amount is 500 instead of 1000, see #59
|
|
284
|
-
new
|
|
436
|
+
new DecodedModulator(0x028A, 0x0, generatorTypes.pan, 500, 0),
|
|
285
437
|
|
|
286
438
|
// expression to attenuation
|
|
287
|
-
new
|
|
439
|
+
new DecodedModulator(
|
|
288
440
|
getModSourceEnum(
|
|
289
441
|
DEFAULT_ATTENUATION_MOD_CURVE_TYPE,
|
|
290
442
|
0,
|
|
@@ -299,16 +451,16 @@ const soundFontModulators = [
|
|
|
299
451
|
),
|
|
300
452
|
|
|
301
453
|
// reverb effects to send
|
|
302
|
-
new
|
|
454
|
+
new DecodedModulator(0x00DB, 0x0, generatorTypes.reverbEffectsSend, 200, 0),
|
|
303
455
|
|
|
304
456
|
// chorus effects to send
|
|
305
|
-
new
|
|
457
|
+
new DecodedModulator(0x00DD, 0x0, generatorTypes.chorusEffectsSend, 200, 0)
|
|
306
458
|
];
|
|
307
459
|
|
|
308
460
|
const customModulators = [
|
|
309
461
|
// custom modulators heck yeah
|
|
310
462
|
// poly pressure to vibrato
|
|
311
|
-
new
|
|
463
|
+
new DecodedModulator(
|
|
312
464
|
getModSourceEnum(modulatorCurveTypes.linear, 0, 0, 0, modulatorSources.polyPressure),
|
|
313
465
|
0x0,
|
|
314
466
|
generatorTypes.vibLfoToPitch,
|
|
@@ -317,7 +469,7 @@ const customModulators = [
|
|
|
317
469
|
),
|
|
318
470
|
|
|
319
471
|
// cc 92 (tremolo) to modLFO volume
|
|
320
|
-
new
|
|
472
|
+
new DecodedModulator(
|
|
321
473
|
getModSourceEnum(
|
|
322
474
|
modulatorCurveTypes.linear,
|
|
323
475
|
0,
|
|
@@ -332,7 +484,7 @@ const customModulators = [
|
|
|
332
484
|
),
|
|
333
485
|
|
|
334
486
|
// cc 73 (attack time) to volEnv attack
|
|
335
|
-
new
|
|
487
|
+
new DecodedModulator(
|
|
336
488
|
getModSourceEnum(
|
|
337
489
|
modulatorCurveTypes.convex,
|
|
338
490
|
1,
|
|
@@ -347,7 +499,7 @@ const customModulators = [
|
|
|
347
499
|
),
|
|
348
500
|
|
|
349
501
|
// cc 72 (release time) to volEnv release
|
|
350
|
-
new
|
|
502
|
+
new DecodedModulator(
|
|
351
503
|
getModSourceEnum(
|
|
352
504
|
modulatorCurveTypes.linear,
|
|
353
505
|
1,
|
|
@@ -362,7 +514,7 @@ const customModulators = [
|
|
|
362
514
|
),
|
|
363
515
|
|
|
364
516
|
// cc 74 (brightness) to filterFc
|
|
365
|
-
new
|
|
517
|
+
new DecodedModulator(
|
|
366
518
|
getModSourceEnum(
|
|
367
519
|
modulatorCurveTypes.linear,
|
|
368
520
|
1,
|
|
@@ -377,7 +529,7 @@ const customModulators = [
|
|
|
377
529
|
),
|
|
378
530
|
|
|
379
531
|
// cc 71 (filter Q) to filter Q
|
|
380
|
-
new
|
|
532
|
+
new DecodedModulator(
|
|
381
533
|
getModSourceEnum(
|
|
382
534
|
modulatorCurveTypes.linear,
|
|
383
535
|
1,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getDLSArticulatorFromSf2Generator, getDLSArticulatorFromSf2Modulator } from "./modulator_converter.js";
|
|
2
2
|
import { writeRIFFOddSize } from "../riff_chunk.js";
|
|
3
3
|
import { combineArrays, IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
4
|
-
import { Generator
|
|
4
|
+
import { Generator } from "../generator.js";
|
|
5
5
|
import { writeDword } from "../../../utils/byte_functions/little_endian.js";
|
|
6
6
|
import { consoleColors } from "../../../utils/other.js";
|
|
7
7
|
import { SpessaSynthInfo, SpessaSynthWarn } from "../../../utils/loggin.js";
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
DLS_1_NO_VIBRATO_MOD,
|
|
13
13
|
DLS_1_NO_VIBRATO_PRESSURE
|
|
14
14
|
} from "../../dls/dls_sources.js";
|
|
15
|
+
import { generatorTypes } from "../generator_types.js";
|
|
15
16
|
|
|
16
17
|
const invalidGeneratorTypes = new Set([
|
|
17
18
|
generatorTypes.sampleModes,
|
|
@@ -34,7 +35,7 @@ const invalidGeneratorTypes = new Set([
|
|
|
34
35
|
]);
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
|
-
* @param zone {
|
|
38
|
+
* @param zone {BasicZone}
|
|
38
39
|
* @returns {IndexedByteArray}
|
|
39
40
|
*/
|
|
40
41
|
export function writeArticulator(zone)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Modulator } from "../modulator.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { Generator } from "../generator.js";
|
|
3
|
+
import { generatorLimits, generatorTypes } from "../generator_types.js";
|
|
4
|
+
import { BasicInstrumentZone } from "../basic_instrument_zone.js";
|
|
5
|
+
import { BasicGlobalZone } from "../basic_global_zone.js";
|
|
4
6
|
|
|
5
7
|
const notGlobalizedTypes = new Set([
|
|
6
8
|
generatorTypes.velRange,
|
|
@@ -30,7 +32,7 @@ const notGlobalizedTypes = new Set([
|
|
|
30
32
|
* Combines preset zones
|
|
31
33
|
* @param preset {BasicPreset}
|
|
32
34
|
* @param globalize {boolean}
|
|
33
|
-
* @returns {BasicInstrumentZone[]}
|
|
35
|
+
* @returns {{global: BasicGlobalZone, zones: BasicInstrumentZone[]}}
|
|
34
36
|
*/
|
|
35
37
|
export function combineZones(preset, globalize = true)
|
|
36
38
|
{
|
|
@@ -75,25 +77,16 @@ export function combineZones(preset, globalize = true)
|
|
|
75
77
|
* @type {Modulator[]}
|
|
76
78
|
*/
|
|
77
79
|
const globalPresetModulators = [];
|
|
78
|
-
let globalPresetKeyRange = { min: 0, max: 127 };
|
|
79
|
-
let globalPresetVelRange = { min: 0, max: 127 };
|
|
80
80
|
|
|
81
81
|
// find the global zone and apply ranges, generators, and modulators
|
|
82
|
-
const globalPresetZone = preset.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
globalPresetKeyRange = globalPresetZone.keyRange;
|
|
88
|
-
globalPresetVelRange = globalPresetZone.velRange;
|
|
89
|
-
}
|
|
82
|
+
const globalPresetZone = preset.globalZone;
|
|
83
|
+
globalPresetGenerators.push(...globalPresetZone.generators);
|
|
84
|
+
globalPresetModulators.push(...globalPresetZone.modulators);
|
|
85
|
+
let globalPresetKeyRange = globalPresetZone.keyRange;
|
|
86
|
+
let globalPresetVelRange = globalPresetZone.velRange;
|
|
90
87
|
// for each non-global preset zone
|
|
91
88
|
for (const presetZone of preset.presetZones)
|
|
92
89
|
{
|
|
93
|
-
if (presetZone.isGlobal)
|
|
94
|
-
{
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
90
|
// use global ranges if not provided
|
|
98
91
|
let presetZoneKeyRange = presetZone.keyRange;
|
|
99
92
|
if (!presetZone.hasKeyRange)
|
|
@@ -110,8 +103,8 @@ export function combineZones(preset, globalize = true)
|
|
|
110
103
|
addUnique(presetGenerators, globalPresetGenerators);
|
|
111
104
|
const presetModulators = [...presetZone.modulators];
|
|
112
105
|
addUniqueMods(presetModulators, globalPresetModulators);
|
|
113
|
-
|
|
114
|
-
const iZones =
|
|
106
|
+
const instrument = presetZone.instrument;
|
|
107
|
+
const iZones = instrument.instrumentZones;
|
|
115
108
|
/**
|
|
116
109
|
* @type {Generator[]}
|
|
117
110
|
*/
|
|
@@ -120,23 +113,14 @@ export function combineZones(preset, globalize = true)
|
|
|
120
113
|
* @type {Modulator[]}
|
|
121
114
|
*/
|
|
122
115
|
const globalInstModulators = [];
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
globalInstGenerators.push(...globalInstZone.generators);
|
|
129
|
-
globalInstModulators.push(...globalInstZone.modulators);
|
|
130
|
-
globalInstKeyRange = globalInstZone.keyRange;
|
|
131
|
-
globalInstVelRange = globalInstZone.velRange;
|
|
132
|
-
}
|
|
116
|
+
const globalInstZone = instrument.globalZone;
|
|
117
|
+
globalInstGenerators.push(...globalInstZone.generators);
|
|
118
|
+
globalInstModulators.push(...globalInstZone.modulators);
|
|
119
|
+
let globalInstKeyRange = globalInstZone.keyRange;
|
|
120
|
+
let globalInstVelRange = globalInstZone.velRange;
|
|
133
121
|
// for each non-global instrument zone
|
|
134
122
|
for (const instZone of iZones)
|
|
135
123
|
{
|
|
136
|
-
if (instZone.isGlobal)
|
|
137
|
-
{
|
|
138
|
-
continue;
|
|
139
|
-
}
|
|
140
124
|
// use global ranges if not provided
|
|
141
125
|
let instZoneKeyRange = instZone.keyRange;
|
|
142
126
|
if (!instZone.hasKeyRange)
|
|
@@ -236,20 +220,17 @@ export function combineZones(preset, globalize = true)
|
|
|
236
220
|
{
|
|
237
221
|
zone.velRange.min = -1;
|
|
238
222
|
}
|
|
239
|
-
zone.
|
|
240
|
-
zone.sample = instZone.sample;
|
|
223
|
+
zone.setSample(instZone.sample);
|
|
241
224
|
zone.generators = finalGenList;
|
|
242
225
|
zone.modulators = finalModList;
|
|
243
226
|
finalZones.push(zone);
|
|
244
227
|
}
|
|
245
228
|
}
|
|
246
|
-
|
|
229
|
+
const globalZone = new BasicGlobalZone();
|
|
247
230
|
if (globalize)
|
|
248
231
|
{
|
|
249
232
|
// create a global zone and add repeating generators to it
|
|
250
233
|
// also modulators
|
|
251
|
-
const globalZone = new BasicInstrumentZone();
|
|
252
|
-
globalZone.isGlobal = true;
|
|
253
234
|
// iterate over every type of generator
|
|
254
235
|
for (let checkedType = 0; checkedType < 58; checkedType++)
|
|
255
236
|
{
|
|
@@ -356,14 +337,14 @@ export function combineZones(preset, globalize = true)
|
|
|
356
337
|
}
|
|
357
338
|
|
|
358
339
|
// globalize only modulators that exist in all zones
|
|
359
|
-
const firstZone = finalZones
|
|
340
|
+
const firstZone = finalZones[0];
|
|
360
341
|
const modulators = firstZone.modulators.map(m => Modulator.copy(m));
|
|
361
342
|
for (const checkedModulator of modulators)
|
|
362
343
|
{
|
|
363
344
|
let existsForAllZones = true;
|
|
364
345
|
for (const zone of finalZones)
|
|
365
346
|
{
|
|
366
|
-
if (
|
|
347
|
+
if (!existsForAllZones)
|
|
367
348
|
{
|
|
368
349
|
continue;
|
|
369
350
|
}
|
|
@@ -394,7 +375,9 @@ export function combineZones(preset, globalize = true)
|
|
|
394
375
|
}
|
|
395
376
|
}
|
|
396
377
|
}
|
|
397
|
-
finalZones.splice(0, 0, globalZone);
|
|
398
378
|
}
|
|
399
|
-
return
|
|
379
|
+
return {
|
|
380
|
+
zones: finalZones,
|
|
381
|
+
global: globalZone
|
|
382
|
+
};
|
|
400
383
|
}
|
|
@@ -22,20 +22,12 @@ export function writeIns(preset)
|
|
|
22
22
|
consoleColors.info
|
|
23
23
|
);
|
|
24
24
|
// combine preset and instrument zones into a single instrument zone (region) list
|
|
25
|
-
const
|
|
25
|
+
const { global, zones } = combineZones(preset);
|
|
26
26
|
|
|
27
|
-
const nonGlobalRegionsCount = combined.reduce((sum, z) =>
|
|
28
|
-
{
|
|
29
|
-
if (!z.isGlobal)
|
|
30
|
-
{
|
|
31
|
-
return sum + 1;
|
|
32
|
-
}
|
|
33
|
-
return sum;
|
|
34
|
-
}, 0);
|
|
35
27
|
|
|
36
28
|
// insh: instrument header
|
|
37
29
|
const inshData = new IndexedByteArray(12);
|
|
38
|
-
writeDword(inshData,
|
|
30
|
+
writeDword(inshData, zones.length); // cRegions
|
|
39
31
|
// bank MSB is in bits 8-14
|
|
40
32
|
let ulBank = (preset.bank & 127) << 8;
|
|
41
33
|
// bit 32 means drums
|
|
@@ -52,26 +44,18 @@ export function writeIns(preset)
|
|
|
52
44
|
);
|
|
53
45
|
|
|
54
46
|
// write global zone
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
art2,
|
|
63
|
-
false,
|
|
64
|
-
true
|
|
65
|
-
);
|
|
66
|
-
}
|
|
47
|
+
const art2 = writeArticulator(global);
|
|
48
|
+
let lar2 = writeRIFFOddSize(
|
|
49
|
+
"lar2",
|
|
50
|
+
art2,
|
|
51
|
+
false,
|
|
52
|
+
true
|
|
53
|
+
);
|
|
67
54
|
|
|
68
55
|
// write the region list
|
|
69
|
-
const lrgnData = combineArrays(
|
|
56
|
+
const lrgnData = combineArrays(zones.reduce((arrs, z) =>
|
|
70
57
|
{
|
|
71
|
-
|
|
72
|
-
{
|
|
73
|
-
arrs.push(writeDLSRegion.apply(this, [z, globalZone]));
|
|
74
|
-
}
|
|
58
|
+
arrs.push(writeDLSRegion.apply(this, [z, global]));
|
|
75
59
|
return arrs;
|
|
76
60
|
}, []));
|
|
77
61
|
const lrgn = writeRIFFOddSize(
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { midiControllers } from "../../../midi/midi_message.js";
|
|
2
2
|
import { DLSSources } from "../../dls/dls_sources.js";
|
|
3
3
|
import { modulatorCurveTypes, modulatorSources } from "../modulator.js";
|
|
4
|
-
import { generatorTypes } from "../generator.js";
|
|
5
4
|
import { DLSDestinations } from "../../dls/dls_destinations.js";
|
|
6
5
|
import { Articulator } from "./articulator.js";
|
|
7
6
|
import { SpessaSynthWarn } from "../../../utils/loggin.js";
|
|
7
|
+
import { generatorTypes } from "../generator_types.js";
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* @param cc {
|
|
11
|
+
* @param cc {0|1}
|
|
12
12
|
* @param index {number}
|
|
13
13
|
* @returns {number|undefined}
|
|
14
14
|
*/
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { combineArrays, IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
2
|
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
|
-
import { generatorTypes } from "../generator.js";
|
|
4
3
|
import { writeRIFFOddSize } from "../riff_chunk.js";
|
|
5
4
|
import { writeWavesample } from "./wsmp.js";
|
|
6
5
|
import { writeArticulator } from "./art2.js";
|
|
6
|
+
import { generatorTypes } from "../generator_types.js";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @param zone {BasicInstrumentZone}
|
|
10
|
-
* @param globalZone {
|
|
10
|
+
* @param globalZone {BasicGlobalZone}
|
|
11
11
|
* @this {BasicSoundBank}
|
|
12
12
|
* @returns {IndexedByteArray}
|
|
13
13
|
*/
|