spessasynth_core 3.26.16 → 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 +251 -79
- 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 +21 -10
- package/src/soundfont/basic_soundfont/write_sf2/igen.js +31 -27
- 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 +20 -9
- package/src/soundfont/basic_soundfont/write_sf2/pgen.js +32 -29
- 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/basic_soundfont/write_sf2/write.js +2 -2
- 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,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { DecodedModulator } from "../basic_soundfont/modulator.js";
|
|
2
|
+
|
|
3
|
+
import { generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* @enum {number}
|
|
@@ -29,7 +30,7 @@ export const DLSSources = {
|
|
|
29
30
|
coarseTune: 0x102
|
|
30
31
|
};
|
|
31
32
|
|
|
32
|
-
export const DEFAULT_DLS_REVERB = new
|
|
33
|
+
export const DEFAULT_DLS_REVERB = new DecodedModulator(
|
|
33
34
|
0x00DB,
|
|
34
35
|
0x0,
|
|
35
36
|
generatorTypes.reverbEffectsSend,
|
|
@@ -37,7 +38,7 @@ export const DEFAULT_DLS_REVERB = new Modulator(
|
|
|
37
38
|
0
|
|
38
39
|
);
|
|
39
40
|
|
|
40
|
-
export const DEFAULT_DLS_CHORUS = new
|
|
41
|
+
export const DEFAULT_DLS_CHORUS = new DecodedModulator(
|
|
41
42
|
0x00DD,
|
|
42
43
|
0x0,
|
|
43
44
|
generatorTypes.chorusEffectsSend,
|
|
@@ -45,7 +46,7 @@ export const DEFAULT_DLS_CHORUS = new Modulator(
|
|
|
45
46
|
0
|
|
46
47
|
);
|
|
47
48
|
|
|
48
|
-
export const DLS_1_NO_VIBRATO_MOD = new
|
|
49
|
+
export const DLS_1_NO_VIBRATO_MOD = new DecodedModulator(
|
|
49
50
|
0x0081,
|
|
50
51
|
0x0,
|
|
51
52
|
generatorTypes.vibLfoToPitch,
|
|
@@ -53,7 +54,7 @@ export const DLS_1_NO_VIBRATO_MOD = new Modulator(
|
|
|
53
54
|
0
|
|
54
55
|
);
|
|
55
56
|
|
|
56
|
-
export const DLS_1_NO_VIBRATO_PRESSURE = new
|
|
57
|
+
export const DLS_1_NO_VIBRATO_PRESSURE = new DecodedModulator(
|
|
57
58
|
0x000D,
|
|
58
59
|
0x0,
|
|
59
60
|
generatorTypes.vibLfoToPitch,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Generator } from "../basic_soundfont/generator.js";
|
|
2
|
+
import { generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
3
|
+
import { BasicInstrumentZone } from "../basic_soundfont/basic_instrument_zone.js";
|
|
3
4
|
|
|
4
5
|
export class DLSZone extends BasicInstrumentZone
|
|
5
6
|
{
|
|
@@ -12,7 +13,6 @@ export class DLSZone extends BasicInstrumentZone
|
|
|
12
13
|
super();
|
|
13
14
|
this.keyRange = keyRange;
|
|
14
15
|
this.velRange = velRange;
|
|
15
|
-
this.isGlobal = true;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -89,7 +89,6 @@ export class DLSZone extends BasicInstrumentZone
|
|
|
89
89
|
}
|
|
90
90
|
// add sample ID
|
|
91
91
|
this.generators.push(new Generator(generatorTypes.sampleID, sampleID));
|
|
92
|
-
this.sample
|
|
93
|
-
sample.useCount++;
|
|
92
|
+
this.setSample(sample);
|
|
94
93
|
}
|
|
95
94
|
}
|
|
@@ -4,8 +4,9 @@ import { DLS_1_NO_VIBRATO_MOD, DLS_1_NO_VIBRATO_PRESSURE, DLSSources } from "./d
|
|
|
4
4
|
import { getSF2ModulatorFromArticulator } from "./articulator_converter.js";
|
|
5
5
|
import { SpessaSynthInfo, SpessaSynthWarn } from "../../utils/loggin.js";
|
|
6
6
|
import { consoleColors } from "../../utils/other.js";
|
|
7
|
-
import { Generator
|
|
7
|
+
import { Generator } from "../basic_soundfont/generator.js";
|
|
8
8
|
import { Modulator } from "../basic_soundfont/modulator.js";
|
|
9
|
+
import { generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -3,11 +3,10 @@ import { readLittleEndian } from "../../utils/byte_functions/little_endian.js";
|
|
|
3
3
|
import { DLSPreset } from "./dls_preset.js";
|
|
4
4
|
import { findRIFFListType, readRIFFChunk } from "../basic_soundfont/riff_chunk.js";
|
|
5
5
|
import { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd } from "../../utils/loggin.js";
|
|
6
|
-
import { BasicInstrumentZone } from "../basic_soundfont/basic_zones.js";
|
|
7
6
|
import { consoleColors } from "../../utils/other.js";
|
|
8
|
-
import { generatorLimits, generatorTypes } from "../basic_soundfont/generator.js";
|
|
9
7
|
import { Modulator } from "../basic_soundfont/modulator.js";
|
|
10
8
|
import { DEFAULT_DLS_CHORUS, DEFAULT_DLS_REVERB } from "./dls_sources.js";
|
|
9
|
+
import { generatorLimits, generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* @this {DLSSoundFont}
|
|
@@ -70,8 +69,7 @@ export function readDLSInstrument(chunk)
|
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
// global articulation: essentially global zone
|
|
73
|
-
const globalZone =
|
|
74
|
-
globalZone.isGlobal = true;
|
|
72
|
+
const globalZone = preset.DLSInstrument.globalZone;
|
|
75
73
|
|
|
76
74
|
// read articulators
|
|
77
75
|
const globalLart = findRIFFListType(chunks, "lart");
|
|
@@ -93,7 +91,6 @@ export function readDLSInstrument(chunk)
|
|
|
93
91
|
{
|
|
94
92
|
globalZone.modulators.push(Modulator.copy(DEFAULT_DLS_CHORUS));
|
|
95
93
|
}
|
|
96
|
-
preset.DLSInstrument.instrumentZones.push(globalZone);
|
|
97
94
|
|
|
98
95
|
// read regions
|
|
99
96
|
for (let i = 0; i < regions; i++)
|
|
@@ -111,7 +108,7 @@ export function readDLSInstrument(chunk)
|
|
|
111
108
|
const zone = this.readRegion(chunk);
|
|
112
109
|
if (zone)
|
|
113
110
|
{
|
|
114
|
-
preset.DLSInstrument.
|
|
111
|
+
preset.DLSInstrument.addZone(zone);
|
|
115
112
|
}
|
|
116
113
|
}
|
|
117
114
|
|
|
@@ -4,7 +4,7 @@ import { readArticulation } from "./read_articulation.js";
|
|
|
4
4
|
/**
|
|
5
5
|
* @param lartChunk {RiffChunk|undefined}
|
|
6
6
|
* @param lar2Chunk {RiffChunk|undefined}
|
|
7
|
-
* @param zone {
|
|
7
|
+
* @param zone {BasicZone}
|
|
8
8
|
* @this {DLSSoundFont}
|
|
9
9
|
*/
|
|
10
10
|
export function readLart(lartChunk, lar2Chunk, zone)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { readLittleEndian, signedInt16 } from "../../utils/byte_functions/little_endian.js";
|
|
2
2
|
import { findRIFFListType, readRIFFChunk } from "../basic_soundfont/riff_chunk.js";
|
|
3
3
|
import { DLSZone } from "./dls_zone.js";
|
|
4
|
-
import { Generator
|
|
4
|
+
import { Generator } from "../basic_soundfont/generator.js";
|
|
5
|
+
import { generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* @this {DLSSoundFont}
|
|
@@ -33,7 +33,16 @@ export class Instrument extends BasicInstrument
|
|
|
33
33
|
this.instrumentZonesAmount = amount;
|
|
34
34
|
for (let i = this.instrumentZoneIndex; i < this.instrumentZonesAmount + this.instrumentZoneIndex; i++)
|
|
35
35
|
{
|
|
36
|
-
|
|
36
|
+
const zone = zones[i];
|
|
37
|
+
if (zone.hasSample())
|
|
38
|
+
{
|
|
39
|
+
this.addZone(zone);
|
|
40
|
+
}
|
|
41
|
+
else
|
|
42
|
+
{
|
|
43
|
+
// global!
|
|
44
|
+
this.globalZone.copyFrom(zone);
|
|
45
|
+
}
|
|
37
46
|
}
|
|
38
47
|
}
|
|
39
48
|
}
|
|
@@ -1,24 +1,5 @@
|
|
|
1
1
|
import { readLittleEndian, signedInt16 } from "../../utils/byte_functions/little_endian.js";
|
|
2
|
-
import {
|
|
3
|
-
import { Modulator } from "../basic_soundfont/modulator.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export class ReadModulator extends Modulator
|
|
7
|
-
{
|
|
8
|
-
/**
|
|
9
|
-
* Creates a modulator
|
|
10
|
-
* @param dataArray {IndexedByteArray}
|
|
11
|
-
*/
|
|
12
|
-
constructor(dataArray)
|
|
13
|
-
{
|
|
14
|
-
const srcEnum = readLittleEndian(dataArray, 2);
|
|
15
|
-
const destination = readLittleEndian(dataArray, 2);
|
|
16
|
-
const amount = signedInt16(dataArray[dataArray.currentIndex++], dataArray[dataArray.currentIndex++]);
|
|
17
|
-
const secSrcEnum = readLittleEndian(dataArray, 2);
|
|
18
|
-
const transformType = readLittleEndian(dataArray, 2);
|
|
19
|
-
super(srcEnum, secSrcEnum, destination, amount, transformType);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
2
|
+
import { DecodedModulator, Modulator } from "../basic_soundfont/modulator.js";
|
|
22
3
|
|
|
23
4
|
/**
|
|
24
5
|
* Reads the modulator read
|
|
@@ -27,10 +8,16 @@ export class ReadModulator extends Modulator
|
|
|
27
8
|
*/
|
|
28
9
|
export function readModulators(modulatorChunk)
|
|
29
10
|
{
|
|
30
|
-
let
|
|
11
|
+
let mods = [];
|
|
31
12
|
while (modulatorChunk.chunkData.length > modulatorChunk.chunkData.currentIndex)
|
|
32
13
|
{
|
|
33
|
-
|
|
14
|
+
const dataArray = modulatorChunk.chunkData;
|
|
15
|
+
const sourceEnum = readLittleEndian(dataArray, 2);
|
|
16
|
+
const destination = readLittleEndian(dataArray, 2);
|
|
17
|
+
const amount = signedInt16(dataArray[dataArray.currentIndex++], dataArray[dataArray.currentIndex++]);
|
|
18
|
+
const secondarySourceEnum = readLittleEndian(dataArray, 2);
|
|
19
|
+
const transformType = readLittleEndian(dataArray, 2);
|
|
20
|
+
mods.push(new DecodedModulator(sourceEnum, secondarySourceEnum, destination, amount, transformType));
|
|
34
21
|
}
|
|
35
|
-
return
|
|
22
|
+
return mods;
|
|
36
23
|
}
|
|
@@ -43,7 +43,16 @@ export class Preset extends BasicPreset
|
|
|
43
43
|
this.presetZonesAmount = amount;
|
|
44
44
|
for (let i = this.presetZoneStartIndex; i < this.presetZonesAmount + this.presetZoneStartIndex; i++)
|
|
45
45
|
{
|
|
46
|
-
|
|
46
|
+
const zone = zones[i];
|
|
47
|
+
if (zone.hasInstrument())
|
|
48
|
+
{
|
|
49
|
+
this.presetZones.push(zone);
|
|
50
|
+
}
|
|
51
|
+
else
|
|
52
|
+
{
|
|
53
|
+
// global!
|
|
54
|
+
this.globalZone.copyFrom(zone);
|
|
55
|
+
}
|
|
47
56
|
}
|
|
48
57
|
}
|
|
49
58
|
}
|
|
@@ -11,7 +11,7 @@ import { consoleColors } from "../../utils/other.js";
|
|
|
11
11
|
import { SpessaSynthGroup, SpessaSynthGroupEnd, SpessaSynthInfo } from "../../utils/loggin.js";
|
|
12
12
|
import { readBytesAsString } from "../../utils/byte_functions/string.js";
|
|
13
13
|
import { stbvorbis } from "../../externals/stbvorbis_sync/stbvorbis_sync.min.js";
|
|
14
|
-
import { BasicSoundBank } from "../basic_soundfont/
|
|
14
|
+
import { BasicSoundBank } from "../basic_soundfont/basic_soundbank.js";
|
|
15
15
|
import { Generator } from "../basic_soundfont/generator.js";
|
|
16
16
|
import { Modulator } from "../basic_soundfont/modulator.js";
|
|
17
17
|
|
|
@@ -215,7 +215,6 @@ export class SoundFont2 extends BasicSoundBank
|
|
|
215
215
|
* @type {Modulator[]}
|
|
216
216
|
*/
|
|
217
217
|
let instrumentModulators = readModulators(presetInstrumentModulatorsChunk);
|
|
218
|
-
|
|
219
218
|
/**
|
|
220
219
|
* read all the instrument zones
|
|
221
220
|
* @type {InstrumentZone[]}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { readLittleEndian } from "../../utils/byte_functions/little_endian.js";
|
|
2
2
|
import { IndexedByteArray } from "../../utils/indexed_array.js";
|
|
3
3
|
import { RiffChunk } from "../basic_soundfont/riff_chunk.js";
|
|
4
|
-
import {
|
|
5
|
-
import { Generator
|
|
4
|
+
import { BasicPresetZone } from "../basic_soundfont/basic_preset_zone.js";
|
|
5
|
+
import { Generator } from "../basic_soundfont/generator.js";
|
|
6
6
|
import { Modulator } from "../basic_soundfont/modulator.js";
|
|
7
|
+
import { generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
8
|
+
import { BasicInstrumentZone } from "../basic_soundfont/basic_instrument_zone.js";
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* zones.js
|
|
@@ -23,7 +25,6 @@ export class InstrumentZone extends BasicInstrumentZone
|
|
|
23
25
|
this.modulatorZoneStartIndex = readLittleEndian(dataArray, 2);
|
|
24
26
|
this.modulatorZoneSize = 0;
|
|
25
27
|
this.generatorZoneSize = 0;
|
|
26
|
-
this.isGlobal = true;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
setZoneSize(modulatorZoneSize, generatorZoneSize)
|
|
@@ -40,7 +41,12 @@ export class InstrumentZone extends BasicInstrumentZone
|
|
|
40
41
|
{
|
|
41
42
|
for (let i = this.generatorZoneStartIndex; i < this.generatorZoneStartIndex + this.generatorZoneSize; i++)
|
|
42
43
|
{
|
|
43
|
-
|
|
44
|
+
const g = generators[i];
|
|
45
|
+
if (!g)
|
|
46
|
+
{
|
|
47
|
+
throw new Error("Missing generator in instrument zone! The file may corrupted.");
|
|
48
|
+
}
|
|
49
|
+
this.generators.push(g);
|
|
44
50
|
}
|
|
45
51
|
}
|
|
46
52
|
|
|
@@ -52,7 +58,12 @@ export class InstrumentZone extends BasicInstrumentZone
|
|
|
52
58
|
{
|
|
53
59
|
for (let i = this.modulatorZoneStartIndex; i < this.modulatorZoneStartIndex + this.modulatorZoneSize; i++)
|
|
54
60
|
{
|
|
55
|
-
|
|
61
|
+
const m = modulators[i];
|
|
62
|
+
if (!m)
|
|
63
|
+
{
|
|
64
|
+
throw new Error("Missing modulator in instrument zone! The file may corrupted.");
|
|
65
|
+
}
|
|
66
|
+
this.modulators.push(m);
|
|
56
67
|
}
|
|
57
68
|
}
|
|
58
69
|
|
|
@@ -65,9 +76,7 @@ export class InstrumentZone extends BasicInstrumentZone
|
|
|
65
76
|
let sampleID = this.generators.find(g => g.generatorType === generatorTypes.sampleID);
|
|
66
77
|
if (sampleID)
|
|
67
78
|
{
|
|
68
|
-
this.
|
|
69
|
-
this.isGlobal = false;
|
|
70
|
-
this.sample.useCount++;
|
|
79
|
+
this.setSample(samples[sampleID.generatorValue]);
|
|
71
80
|
}
|
|
72
81
|
}
|
|
73
82
|
|
|
@@ -149,7 +158,6 @@ export class PresetZone extends BasicPresetZone
|
|
|
149
158
|
this.modulatorZoneStartIndex = readLittleEndian(dataArray, 2);
|
|
150
159
|
this.modulatorZoneSize = 0;
|
|
151
160
|
this.generatorZoneSize = 0;
|
|
152
|
-
this.isGlobal = true;
|
|
153
161
|
}
|
|
154
162
|
|
|
155
163
|
setZoneSize(modulatorZoneSize, generatorZoneSize)
|
|
@@ -166,7 +174,12 @@ export class PresetZone extends BasicPresetZone
|
|
|
166
174
|
{
|
|
167
175
|
for (let i = this.generatorZoneStartIndex; i < this.generatorZoneStartIndex + this.generatorZoneSize; i++)
|
|
168
176
|
{
|
|
169
|
-
|
|
177
|
+
const g = generators[i];
|
|
178
|
+
if (!g)
|
|
179
|
+
{
|
|
180
|
+
throw new Error("Missing generator in preset zone! The file may corrupted.");
|
|
181
|
+
}
|
|
182
|
+
this.generators.push(g);
|
|
170
183
|
}
|
|
171
184
|
}
|
|
172
185
|
|
|
@@ -178,7 +191,12 @@ export class PresetZone extends BasicPresetZone
|
|
|
178
191
|
{
|
|
179
192
|
for (let i = this.modulatorZoneStartIndex; i < this.modulatorZoneStartIndex + this.modulatorZoneSize; i++)
|
|
180
193
|
{
|
|
181
|
-
|
|
194
|
+
const m = modulators[i];
|
|
195
|
+
if (!m)
|
|
196
|
+
{
|
|
197
|
+
throw new Error("Missing modulator in preset zone! The file may corrupted.");
|
|
198
|
+
}
|
|
199
|
+
this.modulators.push(m);
|
|
182
200
|
}
|
|
183
201
|
}
|
|
184
202
|
|
|
@@ -191,9 +209,7 @@ export class PresetZone extends BasicPresetZone
|
|
|
191
209
|
let instrumentID = this.generators.find(g => g.generatorType === generatorTypes.instrument);
|
|
192
210
|
if (instrumentID)
|
|
193
211
|
{
|
|
194
|
-
this.
|
|
195
|
-
this.instrument.addUseCount();
|
|
196
|
-
this.isGlobal = false;
|
|
212
|
+
this.setInstrument(instruments[instrumentID.generatorValue]);
|
|
197
213
|
}
|
|
198
214
|
}
|
|
199
215
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
## This is the
|
|
1
|
+
## This is the synthesizer folder.
|
|
2
2
|
|
|
3
3
|
The code here is responsible for making the actual sound.
|
|
4
4
|
This is the heart of the SpessaSynth library.
|
|
5
5
|
|
|
6
|
-
- `audio_engine` - the core synthesis engine, it theoretically can run on non-browser environments
|
|
7
|
-
- `
|
|
6
|
+
- `audio_engine` - the core synthesis engine, it theoretically can run on non-browser environments
|
|
7
|
+
- `synth_constants.js` - contains the synthesizer's configuration constants
|
|
@@ -6,4 +6,4 @@ The code here is responsible for a single midi channel, synthesizing the sound t
|
|
|
6
6
|
- `engine_components` contains the various digital signal processing functions such as the wavetable oscillator, low
|
|
7
7
|
pass filter, etc.
|
|
8
8
|
|
|
9
|
-
For those interested, `render_voice.js` file contains the actual DSP synthesis code.
|
|
9
|
+
For those interested, `engine_methods/render_voice.js` file contains the actual DSP synthesis code.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { getModulatorCurveValue, MOD_PRECOMPUTED_LENGTH } from "./modulator_curves.js";
|
|
2
2
|
import { VolumeEnvelope } from "./volume_envelope.js";
|
|
3
3
|
import { ModulationEnvelope } from "./modulation_envelope.js";
|
|
4
|
-
import { generatorLimits, generatorTypes } from "../../../soundfont/basic_soundfont/generator.js";
|
|
5
4
|
import { Modulator, modulatorSources } from "../../../soundfont/basic_soundfont/modulator.js";
|
|
6
5
|
import { NON_CC_INDEX_OFFSET } from "./controller_tables.js";
|
|
7
6
|
import { SpessaSynthWarn } from "../../../utils/loggin.js";
|
|
7
|
+
import { generatorLimits, generatorTypes } from "../../../soundfont/basic_soundfont/generator_types.js";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* compute_modulator.js
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Modulator, modulatorCurveTypes, modulatorSources } from "../../../soundfont/basic_soundfont/modulator.js";
|
|
2
2
|
import { NON_CC_INDEX_OFFSET } from "./controller_tables.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -72,8 +72,16 @@ export class DynamicModulatorSystem
|
|
|
72
72
|
isCC = true;
|
|
73
73
|
}
|
|
74
74
|
const modulator = new Modulator(
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
srcNum,
|
|
76
|
+
modulatorCurveTypes.linear,
|
|
77
|
+
isCC ? 1 : 0,
|
|
78
|
+
isBipolar ? 1 : 0,
|
|
79
|
+
0,
|
|
80
|
+
modulatorSources.noController,
|
|
81
|
+
modulatorCurveTypes.linear,
|
|
82
|
+
0,
|
|
83
|
+
0,
|
|
84
|
+
0,
|
|
77
85
|
destination,
|
|
78
86
|
amount,
|
|
79
87
|
0
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { absCentsToHz, decibelAttenuationToGain } from "./unit_converter.js";
|
|
2
|
-
import { generatorTypes } from "../../../soundfont/basic_soundfont/
|
|
2
|
+
import { generatorTypes } from "../../../soundfont/basic_soundfont/generator_types.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* lowpass_filter.js
|
|
@@ -32,8 +32,8 @@ import { chooseBank, isSystemXG, parseBankSelect } from "../../../utils/xg_hacks
|
|
|
32
32
|
import { DEFAULT_PERCUSSION, GENERATOR_OVERRIDE_NO_CHANGE_VALUE } from "../../synth_constants.js";
|
|
33
33
|
import { modulatorSources } from "../../../soundfont/basic_soundfont/modulator.js";
|
|
34
34
|
import { DynamicModulatorSystem } from "./dynamic_modulator_system.js";
|
|
35
|
-
import { generatorLimits, GENERATORS_AMOUNT } from "../../../soundfont/basic_soundfont/generator.js";
|
|
36
35
|
import { computeModulators } from "./compute_modulator.js";
|
|
36
|
+
import { generatorLimits, GENERATORS_AMOUNT } from "../../../soundfont/basic_soundfont/generator_types.js";
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* This class represents a single MIDI Channel within the synthesizer.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { timecentsToSeconds } from "./unit_converter.js";
|
|
2
2
|
import { getModulatorCurveValue } from "./modulator_curves.js";
|
|
3
|
-
import { generatorTypes } from "../../../soundfont/basic_soundfont/generator.js";
|
|
4
3
|
import { modulatorCurveTypes } from "../../../soundfont/basic_soundfont/modulator.js";
|
|
4
|
+
import { generatorTypes } from "../../../soundfont/basic_soundfont/generator_types.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* modulation_envelope.js
|
|
@@ -7,12 +7,9 @@ import { SpessaSynthWarn } from "../../../utils/loggin.js";
|
|
|
7
7
|
import { LowpassFilter } from "./lowpass_filter.js";
|
|
8
8
|
import { VolumeEnvelope } from "./volume_envelope.js";
|
|
9
9
|
import { ModulationEnvelope } from "./modulation_envelope.js";
|
|
10
|
-
import {
|
|
11
|
-
addAndClampGenerator,
|
|
12
|
-
GENERATORS_AMOUNT,
|
|
13
|
-
generatorTypes
|
|
14
|
-
} from "../../../soundfont/basic_soundfont/generator.js";
|
|
10
|
+
import { addAndClampGenerator } from "../../../soundfont/basic_soundfont/generator.js";
|
|
15
11
|
import { Modulator } from "../../../soundfont/basic_soundfont/modulator.js";
|
|
12
|
+
import { GENERATORS_AMOUNT, generatorTypes } from "../../../soundfont/basic_soundfont/generator_types.js";
|
|
16
13
|
|
|
17
14
|
const EXCLUSIVE_CUTOFF_TIME = -2320;
|
|
18
15
|
const EXCLUSIVE_MOD_CUTOFF_TIME = -1130; // less because filter shenanigans
|
|
@@ -330,7 +327,7 @@ class Voice
|
|
|
330
327
|
currentTime,
|
|
331
328
|
voice.targetKey,
|
|
332
329
|
realKey,
|
|
333
|
-
voice.generators,
|
|
330
|
+
new Int16Array(voice.generators),
|
|
334
331
|
voice.modulators.map(m => Modulator.copy(m))
|
|
335
332
|
);
|
|
336
333
|
}
|
|
@@ -401,7 +398,7 @@ export function getVoicesForPreset(preset, bank, program, midiNote, velocity, re
|
|
|
401
398
|
}
|
|
402
399
|
|
|
403
400
|
// EMU initial attenuation correction, multiply initial attenuation by 0.4!
|
|
404
|
-
// all EMU sound cards have this quirk and all sf2 editors and players emulate it too
|
|
401
|
+
// all EMU sound cards have this quirk, and all sf2 editors and players emulate it too
|
|
405
402
|
generators[generatorTypes.initialAttenuation] = Math.floor(generators[generatorTypes.initialAttenuation] * 0.4);
|
|
406
403
|
|
|
407
404
|
// key override
|
|
@@ -473,9 +470,9 @@ export function getVoicesForPreset(preset, bank, program, midiNote, velocity, re
|
|
|
473
470
|
return voices;
|
|
474
471
|
}, []);
|
|
475
472
|
// cache the voice
|
|
476
|
-
this.setCachedVoice(bank, program, midiNote, velocity, voices
|
|
477
|
-
|
|
478
|
-
|
|
473
|
+
this.setCachedVoice(bank, program, midiNote, velocity, voices);
|
|
474
|
+
return voices.map(v =>
|
|
475
|
+
Voice.copy(v, this.currentSynthTime, realKey));
|
|
479
476
|
}
|
|
480
477
|
|
|
481
478
|
/**
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { decibelAttenuationToGain, timecentsToSeconds } from "./unit_converter.js";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
import { generatorTypes } from "../../../soundfont/basic_soundfont/generator_types.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* volume_envelope.js
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { generatorTypes } from "../../../../soundfont/basic_soundfont/generator.js";
|
|
2
1
|
import { SpessaSynthWarn } from "../../../../utils/loggin.js";
|
|
3
2
|
import { consoleColors } from "../../../../utils/other.js";
|
|
3
|
+
import { generatorTypes } from "../../../../soundfont/basic_soundfont/generator_types.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* http://archive.gamedev.net/archive/reference/articles/article445.html
|
|
@@ -54,6 +54,13 @@ export function dataEntryCoarse(dataValue)
|
|
|
54
54
|
{
|
|
55
55
|
// store in cc table
|
|
56
56
|
this.midiControllers[midiControllers.dataEntryMsb] = dataValue << 7;
|
|
57
|
+
/*
|
|
58
|
+
A note on this vibrato.
|
|
59
|
+
This is a completely custom vibrato, with its own oscillator and parameters.
|
|
60
|
+
It is disabled by default,
|
|
61
|
+
only being enabled when one of the NPRN messages changing it is received
|
|
62
|
+
and stays on until the next system-reset.
|
|
63
|
+
*/
|
|
57
64
|
const addDefaultVibrato = () =>
|
|
58
65
|
{
|
|
59
66
|
if (this.channelVibrato.delay === 0 && this.channelVibrato.rate === 0 && this.channelVibrato.depth === 0)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { generatorTypes } from "../../../soundfont/basic_soundfont/generator.js";
|
|
2
1
|
import { midiControllers } from "../../../midi/midi_message.js";
|
|
3
2
|
import { portamentoTimeToSeconds } from "./portamento_time.js";
|
|
4
3
|
import { customControllers } from "../engine_components/controller_tables.js";
|
|
5
4
|
import { Modulator } from "../../../soundfont/basic_soundfont/modulator.js";
|
|
6
5
|
import { GENERATOR_OVERRIDE_NO_CHANGE_VALUE } from "../../synth_constants.js";
|
|
6
|
+
import { generatorTypes } from "../../../soundfont/basic_soundfont/generator_types.js";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* sends a "MIDI Note on message"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { VolumeEnvelope } from "../engine_components/volume_envelope.js";
|
|
2
2
|
import { ModulationEnvelope } from "../engine_components/modulation_envelope.js";
|
|
3
|
-
import { generatorTypes } from "../../../soundfont/basic_soundfont/generator.js";
|
|
4
3
|
import { customControllers } from "../engine_components/controller_tables.js";
|
|
5
4
|
import { absCentsToHz, timecentsToSeconds } from "../engine_components/unit_converter.js";
|
|
6
5
|
import { getLFOValue } from "../engine_components/lfo.js";
|
|
7
6
|
import { WavetableOscillator } from "../engine_components/wavetable_oscillator.js";
|
|
8
7
|
import { LowpassFilter } from "../engine_components/lowpass_filter.js";
|
|
9
8
|
import { interpolationTypes } from "../engine_components/enums.js";
|
|
9
|
+
import { generatorTypes } from "../../../soundfont/basic_soundfont/generator_types.js";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Renders a voice to the stereo output buffer
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { generatorTypes } from "../../../../soundfont/basic_soundfont/generator.js";
|
|
2
1
|
import { customControllers } from "../../engine_components/controller_tables.js";
|
|
2
|
+
import { generatorTypes } from "../../../../soundfont/basic_soundfont/generator_types.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Stops a note nearly instantly
|
|
@@ -8,7 +8,8 @@ import { readBytesAsString } from "../../../utils/byte_functions/string.js";
|
|
|
8
8
|
import { synthDisplayTypes } from "../engine_components/enums.js";
|
|
9
9
|
import { customControllers, NON_CC_INDEX_OFFSET } from "../engine_components/controller_tables.js";
|
|
10
10
|
import { modulatorSources } from "../../../soundfont/basic_soundfont/modulator.js";
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
import { generatorTypes } from "../../../soundfont/basic_soundfont/generator_types.js";
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* KeyNum: tuning
|
package/src/utils/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
## This is the utility folder.
|
|
2
2
|
|
|
3
|
-
There are various
|
|
3
|
+
There are various utilities here used by the SpessaSynth library.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
- `byte_functions` - low-level byte manipulation utilities
|
|
6
|
+
- `buffer_to_wav.js` - converts audio buffer to WAV format
|
|
7
|
+
- `sysex_detector.js` - detects various System Exclusive messages
|
|
8
|
+
- `xg_hacks.js` - XG-specific MIDI handling utilities
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { BasicZone } from "./basic_zone.js";
|
|
2
|
-
|
|
3
|
-
export class BasicInstrumentZone extends BasicZone
|
|
4
|
-
{
|
|
5
|
-
/**
|
|
6
|
-
* Zone's sample. Undefined if global
|
|
7
|
-
* @type {BasicSample|undefined}
|
|
8
|
-
*/
|
|
9
|
-
sample = undefined;
|
|
10
|
-
/**
|
|
11
|
-
* The zone's use count
|
|
12
|
-
* @type {number}
|
|
13
|
-
*/
|
|
14
|
-
useCount = 0;
|
|
15
|
-
|
|
16
|
-
deleteZone()
|
|
17
|
-
{
|
|
18
|
-
this.useCount--;
|
|
19
|
-
if (this.isGlobal)
|
|
20
|
-
{
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
this.sample.useCount--;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export class BasicPresetZone extends BasicZone
|
|
28
|
-
{
|
|
29
|
-
/**
|
|
30
|
-
* Zone's instrument. Undefined if global
|
|
31
|
-
* @type {BasicInstrument|undefined}
|
|
32
|
-
*/
|
|
33
|
-
instrument = undefined;
|
|
34
|
-
|
|
35
|
-
deleteZone()
|
|
36
|
-
{
|
|
37
|
-
if (this.isGlobal)
|
|
38
|
-
{
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
this.instrument.removeUseCount();
|
|
42
|
-
}
|
|
43
|
-
}
|