spessasynth_core 3.26.20 → 3.26.22
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/package.json +5 -2
- package/src/soundfont/basic_soundfont/basic_global_zone.js +1 -11
- package/src/soundfont/basic_soundfont/basic_instrument.js +28 -16
- package/src/soundfont/basic_soundfont/basic_instrument_zone.js +29 -7
- package/src/soundfont/basic_soundfont/basic_preset.js +11 -8
- package/src/soundfont/basic_soundfont/basic_preset_zone.js +27 -6
- package/src/soundfont/basic_soundfont/basic_sample.js +48 -5
- package/src/soundfont/basic_soundfont/basic_soundbank.js +19 -15
- package/src/soundfont/basic_soundfont/basic_zone.js +12 -0
- package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +13 -22
- package/src/soundfont/basic_soundfont/write_dls/ins.js +3 -1
- package/src/soundfont/dls/dls_instrument.js +20 -0
- package/src/soundfont/dls/dls_preset.js +8 -8
- package/src/soundfont/dls/dls_zone.js +4 -7
- package/src/soundfont/dls/read_instrument.js +5 -9
- package/src/soundfont/dls/read_region.js +5 -8
- package/src/soundfont/read_sf2/generators.js +2 -5
- package/src/soundfont/read_sf2/instrument_zones.js +88 -0
- package/src/soundfont/read_sf2/instruments.js +26 -30
- package/src/soundfont/read_sf2/modulators.js +2 -0
- package/src/soundfont/read_sf2/preset_zones.js +92 -0
- package/src/soundfont/read_sf2/presets.js +23 -31
- package/src/soundfont/read_sf2/samples.js +5 -5
- package/src/soundfont/read_sf2/soundfont.js +44 -32
- package/src/utils/buffer_to_wav.js +34 -19
- package/src/soundfont/read_sf2/zones.js +0 -223
|
@@ -52,7 +52,7 @@ export function readDLSInstrument(chunk)
|
|
|
52
52
|
presetName = readBytesAsString(info.chunkData, info.chunkData.length).trim();
|
|
53
53
|
}
|
|
54
54
|
preset.presetName = presetName;
|
|
55
|
-
preset.
|
|
55
|
+
preset.dlsInstrument.instrumentName = presetName;
|
|
56
56
|
SpessaSynthGroupCollapsed(
|
|
57
57
|
`%cParsing %c"${presetName}"%c...`,
|
|
58
58
|
consoleColors.info,
|
|
@@ -69,7 +69,7 @@ export function readDLSInstrument(chunk)
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
// global articulation: essentially global zone
|
|
72
|
-
const globalZone = preset.
|
|
72
|
+
const globalZone = preset.dlsInstrument.globalZone;
|
|
73
73
|
|
|
74
74
|
// read articulators
|
|
75
75
|
const globalLart = findRIFFListType(chunks, "lart");
|
|
@@ -105,14 +105,10 @@ export function readDLSInstrument(chunk)
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
|
|
108
|
-
const zone =
|
|
109
|
-
|
|
110
|
-
{
|
|
111
|
-
preset.DLSInstrument.addZones(zone);
|
|
112
|
-
}
|
|
108
|
+
const zone = preset.dlsInstrument.createZone();
|
|
109
|
+
this.readRegion(chunk, zone);
|
|
113
110
|
}
|
|
114
|
-
|
|
115
111
|
this.addPresets(preset);
|
|
116
|
-
this.addInstruments(preset.
|
|
112
|
+
this.addInstruments(preset.dlsInstrument);
|
|
117
113
|
SpessaSynthGroupEnd();
|
|
118
114
|
}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { readLittleEndian, signedInt16 } from "../../utils/byte_functions/little_endian.js";
|
|
2
2
|
import { findRIFFListType, readRIFFChunk } from "../basic_soundfont/riff_chunk.js";
|
|
3
|
-
import { DLSZone } from "./dls_zone.js";
|
|
4
3
|
import { Generator } from "../basic_soundfont/generator.js";
|
|
5
4
|
import { generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* @this {DLSSoundFont}
|
|
9
8
|
* @param chunk {RiffChunk}
|
|
10
|
-
* @
|
|
9
|
+
* @param zone {DLSZone}
|
|
11
10
|
*/
|
|
12
|
-
export function readRegion(chunk)
|
|
11
|
+
export function readRegion(chunk, zone)
|
|
13
12
|
{
|
|
14
13
|
// regions are essentially instrument zones
|
|
15
14
|
|
|
@@ -40,10 +39,9 @@ export function readRegion(chunk)
|
|
|
40
39
|
}
|
|
41
40
|
// cannot do the same to key zones sadly
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
);
|
|
42
|
+
// apply ranges
|
|
43
|
+
zone.keyRange = { min: keyMin, max: keyMax };
|
|
44
|
+
zone.velRange = { min: velMin, max: velMax };
|
|
47
45
|
|
|
48
46
|
// fusOptions: no idea about that one???
|
|
49
47
|
readLittleEndian(regionHeader.chunkData, 2);
|
|
@@ -148,5 +146,4 @@ export function readRegion(chunk)
|
|
|
148
146
|
sampleID,
|
|
149
147
|
pitchCorrection
|
|
150
148
|
);
|
|
151
|
-
return zone;
|
|
152
149
|
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* instrument_zones.js
|
|
3
|
+
* purpose: reads instrument zones from soundfont and gets their respective samples and generators and modulators
|
|
4
|
+
*/
|
|
5
|
+
import { BasicInstrumentZone } from "../basic_soundfont/basic_instrument_zone.js";
|
|
6
|
+
import { generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
7
|
+
import { readLittleEndian } from "../../utils/byte_functions/little_endian.js";
|
|
8
|
+
|
|
9
|
+
export class InstrumentZone extends BasicInstrumentZone
|
|
10
|
+
{
|
|
11
|
+
/**
|
|
12
|
+
* Creates a zone (instrument)
|
|
13
|
+
* @param inst {Instrument}
|
|
14
|
+
*/
|
|
15
|
+
constructor(inst)
|
|
16
|
+
{
|
|
17
|
+
super(inst);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Loads the zone's sample
|
|
22
|
+
* @param samples {BasicSample[]}
|
|
23
|
+
*/
|
|
24
|
+
getSample(samples)
|
|
25
|
+
{
|
|
26
|
+
let sampleID = this.generators.find(g => g.generatorType === generatorTypes.sampleID);
|
|
27
|
+
if (sampleID)
|
|
28
|
+
{
|
|
29
|
+
this.setSample(samples[sampleID.generatorValue]);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Reads the given instrument zone
|
|
36
|
+
* @param zonesChunk {RiffChunk}
|
|
37
|
+
* @param instrumentGenerators {Generator[]}
|
|
38
|
+
* @param instrumentModulators {Modulator[]}
|
|
39
|
+
* @param samples {BasicSample[]}
|
|
40
|
+
* @param instruments {Instrument[]}
|
|
41
|
+
*/
|
|
42
|
+
export function readInstrumentZones(zonesChunk, instrumentGenerators, instrumentModulators, samples, instruments)
|
|
43
|
+
{
|
|
44
|
+
/**
|
|
45
|
+
* @type {number[]}
|
|
46
|
+
*/
|
|
47
|
+
const modStartIndexes = [];
|
|
48
|
+
/**
|
|
49
|
+
* @type {number[]}
|
|
50
|
+
*/
|
|
51
|
+
const genStartIndexes = [];
|
|
52
|
+
|
|
53
|
+
while (zonesChunk.chunkData.length > zonesChunk.chunkData.currentIndex)
|
|
54
|
+
{
|
|
55
|
+
genStartIndexes.push(readLittleEndian(zonesChunk.chunkData, 2));
|
|
56
|
+
modStartIndexes.push(readLittleEndian(zonesChunk.chunkData, 2));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let modIndex = 0;
|
|
60
|
+
let genIndex = 0;
|
|
61
|
+
for (const instrument of instruments)
|
|
62
|
+
{
|
|
63
|
+
for (let i = 0; i < instrument.zonesCount; i++)
|
|
64
|
+
{
|
|
65
|
+
const gensStart = genStartIndexes[genIndex++];
|
|
66
|
+
const gensEnd = genStartIndexes[genIndex];
|
|
67
|
+
const gens = instrumentGenerators.slice(gensStart, gensEnd);
|
|
68
|
+
const modsStart = modStartIndexes[modIndex++];
|
|
69
|
+
const modsEnd = modStartIndexes[modIndex];
|
|
70
|
+
const mods = instrumentModulators.slice(modsStart, modsEnd);
|
|
71
|
+
// check for global zone
|
|
72
|
+
if (gens.find(g => g.generatorType === generatorTypes.sampleID))
|
|
73
|
+
{
|
|
74
|
+
// regular zone
|
|
75
|
+
const zone = instrument.createZone();
|
|
76
|
+
zone.addGenerators(...gens);
|
|
77
|
+
zone.addModulators(...mods);
|
|
78
|
+
zone.getSample(samples);
|
|
79
|
+
}
|
|
80
|
+
else
|
|
81
|
+
{
|
|
82
|
+
// global zone
|
|
83
|
+
instrument.globalZone.addGenerators(...gens);
|
|
84
|
+
instrument.globalZone.addModulators(...mods);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { RiffChunk } from "../basic_soundfont/riff_chunk.js";
|
|
2
|
-
import { InstrumentZone } from "./zones.js";
|
|
3
2
|
import { readLittleEndian } from "../../utils/byte_functions/little_endian.js";
|
|
4
3
|
import { readBytesAsString } from "../../utils/byte_functions/string.js";
|
|
5
4
|
import { BasicInstrument } from "../basic_soundfont/basic_instrument.js";
|
|
6
5
|
|
|
6
|
+
import { InstrumentZone } from "./instrument_zones.js";
|
|
7
|
+
|
|
7
8
|
/**
|
|
8
9
|
* instrument.js
|
|
9
10
|
* purpose: parses soundfont instrument and stores them as a class
|
|
@@ -11,6 +12,15 @@ import { BasicInstrument } from "../basic_soundfont/basic_instrument.js";
|
|
|
11
12
|
|
|
12
13
|
export class Instrument extends BasicInstrument
|
|
13
14
|
{
|
|
15
|
+
/**
|
|
16
|
+
* @type {number}
|
|
17
|
+
*/
|
|
18
|
+
zoneStartIndex;
|
|
19
|
+
/**
|
|
20
|
+
* @type {number}
|
|
21
|
+
*/
|
|
22
|
+
zonesCount = 0;
|
|
23
|
+
|
|
14
24
|
/**
|
|
15
25
|
* Creates an instrument
|
|
16
26
|
* @param instrumentChunk {RiffChunk}
|
|
@@ -19,57 +29,43 @@ export class Instrument extends BasicInstrument
|
|
|
19
29
|
{
|
|
20
30
|
super();
|
|
21
31
|
this.instrumentName = readBytesAsString(instrumentChunk.chunkData, 20).trim();
|
|
22
|
-
this.
|
|
23
|
-
this.instrumentZonesAmount = 0;
|
|
32
|
+
this.zoneStartIndex = readLittleEndian(instrumentChunk.chunkData, 2);
|
|
24
33
|
}
|
|
25
34
|
|
|
26
35
|
/**
|
|
27
|
-
*
|
|
28
|
-
* @param amount {number}
|
|
29
|
-
* @param zones {InstrumentZone[]}
|
|
36
|
+
* @returns {InstrumentZone}
|
|
30
37
|
*/
|
|
31
|
-
|
|
38
|
+
createZone()
|
|
32
39
|
{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const zone = zones[i];
|
|
37
|
-
if (zone.hasSample())
|
|
38
|
-
{
|
|
39
|
-
this.addZones(zone);
|
|
40
|
-
}
|
|
41
|
-
else
|
|
42
|
-
{
|
|
43
|
-
// global!
|
|
44
|
-
this.globalZone.copyFrom(zone);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
40
|
+
const z = new InstrumentZone(this);
|
|
41
|
+
this.instrumentZones.push(z);
|
|
42
|
+
return z;
|
|
47
43
|
}
|
|
48
44
|
}
|
|
49
45
|
|
|
50
46
|
/**
|
|
51
47
|
* Reads the instruments
|
|
52
48
|
* @param instrumentChunk {RiffChunk}
|
|
53
|
-
* @param instrumentZones {InstrumentZone[]}
|
|
54
49
|
* @returns {Instrument[]}
|
|
55
50
|
*/
|
|
56
|
-
export function readInstruments(instrumentChunk
|
|
51
|
+
export function readInstruments(instrumentChunk)
|
|
57
52
|
{
|
|
53
|
+
/**
|
|
54
|
+
* @type {Instrument[]}
|
|
55
|
+
*/
|
|
58
56
|
let instruments = [];
|
|
59
57
|
while (instrumentChunk.chunkData.length > instrumentChunk.chunkData.currentIndex)
|
|
60
58
|
{
|
|
61
59
|
let instrument = new Instrument(instrumentChunk);
|
|
60
|
+
|
|
62
61
|
if (instruments.length > 0)
|
|
63
62
|
{
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
const previous = instruments[instruments.length - 1];
|
|
64
|
+
previous.zonesCount = instrument.zoneStartIndex - previous.zoneStartIndex;
|
|
66
65
|
}
|
|
67
66
|
instruments.push(instrument);
|
|
68
67
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
// remove EOI
|
|
72
|
-
instruments.pop();
|
|
73
|
-
}
|
|
68
|
+
// remove EOI
|
|
69
|
+
instruments.pop();
|
|
74
70
|
return instruments;
|
|
75
71
|
}
|
|
@@ -19,5 +19,7 @@ export function readModulators(modulatorChunk)
|
|
|
19
19
|
const transformType = readLittleEndian(dataArray, 2);
|
|
20
20
|
mods.push(new DecodedModulator(sourceEnum, secondarySourceEnum, destination, amount, transformType));
|
|
21
21
|
}
|
|
22
|
+
// remove terminal
|
|
23
|
+
mods.pop();
|
|
22
24
|
return mods;
|
|
23
25
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { readLittleEndian } from "../../utils/byte_functions/little_endian.js";
|
|
2
|
+
import { RiffChunk } from "../basic_soundfont/riff_chunk.js";
|
|
3
|
+
import { BasicPresetZone } from "../basic_soundfont/basic_preset_zone.js";
|
|
4
|
+
import { Generator } from "../basic_soundfont/generator.js";
|
|
5
|
+
import { Modulator } from "../basic_soundfont/modulator.js";
|
|
6
|
+
import { generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* preset_zones.js
|
|
10
|
+
* purpose: reads preset zones from soundfont and gets their respective samples and generators and modulators
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export class PresetZone extends BasicPresetZone
|
|
14
|
+
{
|
|
15
|
+
/**
|
|
16
|
+
* Creates a zone (preset)
|
|
17
|
+
* @param preset {BasicPreset}
|
|
18
|
+
*/
|
|
19
|
+
constructor(preset)
|
|
20
|
+
{
|
|
21
|
+
super(preset);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* grab the instrument
|
|
26
|
+
* @param instruments {BasicInstrument[]}
|
|
27
|
+
*/
|
|
28
|
+
getInstrument(instruments)
|
|
29
|
+
{
|
|
30
|
+
let instrumentID = this.generators.find(g => g.generatorType === generatorTypes.instrument);
|
|
31
|
+
if (instrumentID)
|
|
32
|
+
{
|
|
33
|
+
this.setInstrument(instruments[instrumentID.generatorValue]);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Reads the given preset zone read
|
|
40
|
+
* @param zonesChunk {RiffChunk}
|
|
41
|
+
* @param presetGens {Generator[]}
|
|
42
|
+
* @param instruments {BasicInstrument[]}
|
|
43
|
+
* @param presetMods {Modulator[]}
|
|
44
|
+
* @param presets {Preset[]}
|
|
45
|
+
*/
|
|
46
|
+
export function readPresetZones(zonesChunk, presetGens, presetMods, instruments, presets)
|
|
47
|
+
{
|
|
48
|
+
/**
|
|
49
|
+
* @type {number[]}
|
|
50
|
+
*/
|
|
51
|
+
const modStartIndexes = [];
|
|
52
|
+
/**
|
|
53
|
+
* @type {number[]}
|
|
54
|
+
*/
|
|
55
|
+
const genStartIndexes = [];
|
|
56
|
+
|
|
57
|
+
while (zonesChunk.chunkData.length > zonesChunk.chunkData.currentIndex)
|
|
58
|
+
{
|
|
59
|
+
genStartIndexes.push(readLittleEndian(zonesChunk.chunkData, 2));
|
|
60
|
+
modStartIndexes.push(readLittleEndian(zonesChunk.chunkData, 2));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let modIndex = 0;
|
|
64
|
+
let genIndex = 0;
|
|
65
|
+
for (const preset of presets)
|
|
66
|
+
{
|
|
67
|
+
for (let i = 0; i < preset.zonesCount; i++)
|
|
68
|
+
{
|
|
69
|
+
const gensStart = genStartIndexes[genIndex++];
|
|
70
|
+
const gensEnd = genStartIndexes[genIndex];
|
|
71
|
+
const gens = presetGens.slice(gensStart, gensEnd);
|
|
72
|
+
const modsStart = modStartIndexes[modIndex++];
|
|
73
|
+
const modsEnd = modStartIndexes[modIndex];
|
|
74
|
+
const mods = presetMods.slice(modsStart, modsEnd);
|
|
75
|
+
// check for global zone
|
|
76
|
+
if (gens.find(g => g.generatorType === generatorTypes.instrument) !== undefined)
|
|
77
|
+
{
|
|
78
|
+
// regular zone
|
|
79
|
+
const zone = preset.createZone();
|
|
80
|
+
zone.addGenerators(...gens);
|
|
81
|
+
zone.addModulators(...mods);
|
|
82
|
+
zone.getInstrument(instruments);
|
|
83
|
+
}
|
|
84
|
+
else
|
|
85
|
+
{
|
|
86
|
+
// global zone
|
|
87
|
+
preset.globalZone.addGenerators(...gens);
|
|
88
|
+
preset.globalZone.addModulators(...mods);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { RiffChunk } from "../basic_soundfont/riff_chunk.js";
|
|
2
|
-
import { PresetZone } from "./zones.js";
|
|
3
2
|
import { readLittleEndian } from "../../utils/byte_functions/little_endian.js";
|
|
4
3
|
import { readBytesAsString } from "../../utils/byte_functions/string.js";
|
|
5
4
|
import { BasicPreset } from "../basic_soundfont/basic_preset.js";
|
|
5
|
+
import { PresetZone } from "./preset_zones.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* parses soundfont presets, also includes function for getting the generators and samples from midi note and velocity
|
|
@@ -10,6 +10,16 @@ import { BasicPreset } from "../basic_soundfont/basic_preset.js";
|
|
|
10
10
|
|
|
11
11
|
export class Preset extends BasicPreset
|
|
12
12
|
{
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @type {number}
|
|
16
|
+
*/
|
|
17
|
+
zoneStartIndex;
|
|
18
|
+
/**
|
|
19
|
+
* @type {number}
|
|
20
|
+
*/
|
|
21
|
+
zonesCount = 0;
|
|
22
|
+
|
|
13
23
|
/**
|
|
14
24
|
* Creates a preset
|
|
15
25
|
* @param presetChunk {RiffChunk}
|
|
@@ -24,47 +34,32 @@ export class Preset extends BasicPreset
|
|
|
24
34
|
|
|
25
35
|
this.program = readLittleEndian(presetChunk.chunkData, 2);
|
|
26
36
|
this.bank = readLittleEndian(presetChunk.chunkData, 2);
|
|
27
|
-
this.
|
|
37
|
+
this.zoneStartIndex = readLittleEndian(presetChunk.chunkData, 2);
|
|
28
38
|
|
|
29
39
|
// read the dword
|
|
30
40
|
this.library = readLittleEndian(presetChunk.chunkData, 4);
|
|
31
41
|
this.genre = readLittleEndian(presetChunk.chunkData, 4);
|
|
32
42
|
this.morphology = readLittleEndian(presetChunk.chunkData, 4);
|
|
33
|
-
this.presetZonesAmount = 0;
|
|
34
43
|
}
|
|
35
44
|
|
|
36
45
|
/**
|
|
37
|
-
*
|
|
38
|
-
* @param amount {number}
|
|
39
|
-
* @param zones {PresetZone[]}
|
|
46
|
+
* @returns {PresetZone}
|
|
40
47
|
*/
|
|
41
|
-
|
|
48
|
+
createZone()
|
|
42
49
|
{
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
}
|
|
56
|
-
}
|
|
50
|
+
const z = new PresetZone(this);
|
|
51
|
+
this.presetZones.push(z);
|
|
52
|
+
return z;
|
|
57
53
|
}
|
|
58
54
|
}
|
|
59
55
|
|
|
60
56
|
/**
|
|
61
57
|
* Reads the presets
|
|
62
58
|
* @param presetChunk {RiffChunk}
|
|
63
|
-
* @param
|
|
64
|
-
* @param sf2 {BasicSoundBank}
|
|
59
|
+
* @param parent {BasicSoundBank}
|
|
65
60
|
* @returns {Preset[]}
|
|
66
61
|
*/
|
|
67
|
-
export function readPresets(presetChunk,
|
|
62
|
+
export function readPresets(presetChunk, parent)
|
|
68
63
|
{
|
|
69
64
|
/**
|
|
70
65
|
* @type {Preset[]}
|
|
@@ -72,18 +67,15 @@ export function readPresets(presetChunk, presetZones, sf2)
|
|
|
72
67
|
let presets = [];
|
|
73
68
|
while (presetChunk.chunkData.length > presetChunk.chunkData.currentIndex)
|
|
74
69
|
{
|
|
75
|
-
let preset = new Preset(presetChunk,
|
|
70
|
+
let preset = new Preset(presetChunk, parent);
|
|
76
71
|
if (presets.length > 0)
|
|
77
72
|
{
|
|
78
|
-
|
|
79
|
-
|
|
73
|
+
const previous = presets[presets.length - 1];
|
|
74
|
+
previous.zonesCount = preset.zoneStartIndex - previous.zoneStartIndex;
|
|
80
75
|
}
|
|
81
76
|
presets.push(preset);
|
|
82
77
|
}
|
|
83
78
|
// remove EOP
|
|
84
|
-
|
|
85
|
-
{
|
|
86
|
-
presets.pop();
|
|
87
|
-
}
|
|
79
|
+
presets.pop();
|
|
88
80
|
return presets;
|
|
89
81
|
}
|
|
@@ -205,7 +205,10 @@ export class SoundFontSample extends BasicSample
|
|
|
205
205
|
* read the sample data
|
|
206
206
|
* @type {Float32Array}
|
|
207
207
|
*/
|
|
208
|
-
let audioData = this.sampleDataArray.slice(
|
|
208
|
+
let audioData = /**@type {Float32Array}*/ this.sampleDataArray.slice(
|
|
209
|
+
this.sampleStartIndex / 2,
|
|
210
|
+
this.sampleEndIndex / 2
|
|
211
|
+
);
|
|
209
212
|
this.sampleData = audioData;
|
|
210
213
|
this.isSampleLoaded = true;
|
|
211
214
|
return audioData;
|
|
@@ -233,10 +236,7 @@ export function readSamples(sampleHeadersChunk, smplChunkData, isSmplDataRaw = t
|
|
|
233
236
|
index++;
|
|
234
237
|
}
|
|
235
238
|
// remove EOS
|
|
236
|
-
|
|
237
|
-
{
|
|
238
|
-
samples.pop();
|
|
239
|
-
}
|
|
239
|
+
samples.pop();
|
|
240
240
|
return samples;
|
|
241
241
|
}
|
|
242
242
|
|
|
@@ -2,7 +2,7 @@ import { IndexedByteArray } from "../../utils/indexed_array.js";
|
|
|
2
2
|
import { readSamples } from "./samples.js";
|
|
3
3
|
import { readLittleEndian } from "../../utils/byte_functions/little_endian.js";
|
|
4
4
|
import { readGenerators } from "./generators.js";
|
|
5
|
-
import {
|
|
5
|
+
import { readPresetZones } from "./preset_zones.js";
|
|
6
6
|
import { readPresets } from "./presets.js";
|
|
7
7
|
import { readInstruments } from "./instruments.js";
|
|
8
8
|
import { readModulators } from "./modulators.js";
|
|
@@ -14,6 +14,7 @@ import { stbvorbis } from "../../externals/stbvorbis_sync/stbvorbis_sync.min.js"
|
|
|
14
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
|
+
import { InstrumentZone, readInstrumentZones } from "./instrument_zones.js";
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* soundfont.js
|
|
@@ -22,6 +23,16 @@ import { Modulator } from "../basic_soundfont/modulator.js";
|
|
|
22
23
|
|
|
23
24
|
export class SoundFont2 extends BasicSoundBank
|
|
24
25
|
{
|
|
26
|
+
/**
|
|
27
|
+
* @type {Instrument[]}
|
|
28
|
+
*/
|
|
29
|
+
instruments = [];
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @type {Preset[]}
|
|
33
|
+
*/
|
|
34
|
+
presets = [];
|
|
35
|
+
|
|
25
36
|
/**
|
|
26
37
|
* Initializes a new SoundFont2 Parser and parses the given data array
|
|
27
38
|
* @param arrayBuffer {ArrayBuffer}
|
|
@@ -170,79 +181,80 @@ export class SoundFont2 extends BasicSoundBank
|
|
|
170
181
|
readBytesAsString(presetChunk.chunkData, 4);
|
|
171
182
|
|
|
172
183
|
// read the hydra chunks
|
|
173
|
-
const
|
|
174
|
-
this.verifyHeader(
|
|
184
|
+
const pHdrChunk = readRIFFChunk(presetChunk.chunkData);
|
|
185
|
+
this.verifyHeader(pHdrChunk, "phdr");
|
|
175
186
|
|
|
176
|
-
const
|
|
177
|
-
this.verifyHeader(
|
|
187
|
+
const pBagChunk = readRIFFChunk(presetChunk.chunkData);
|
|
188
|
+
this.verifyHeader(pBagChunk, "pbag");
|
|
178
189
|
|
|
179
|
-
const
|
|
180
|
-
this.verifyHeader(
|
|
190
|
+
const pModChunk = readRIFFChunk(presetChunk.chunkData);
|
|
191
|
+
this.verifyHeader(pModChunk, "pmod");
|
|
181
192
|
|
|
182
|
-
const
|
|
183
|
-
this.verifyHeader(
|
|
193
|
+
const pGenChunk = readRIFFChunk(presetChunk.chunkData);
|
|
194
|
+
this.verifyHeader(pGenChunk, "pgen");
|
|
184
195
|
|
|
185
|
-
const
|
|
186
|
-
this.verifyHeader(
|
|
196
|
+
const instChunk = readRIFFChunk(presetChunk.chunkData);
|
|
197
|
+
this.verifyHeader(instChunk, "inst");
|
|
187
198
|
|
|
188
|
-
const
|
|
189
|
-
this.verifyHeader(
|
|
199
|
+
const iBagChunk = readRIFFChunk(presetChunk.chunkData);
|
|
200
|
+
this.verifyHeader(iBagChunk, "ibag");
|
|
190
201
|
|
|
191
|
-
const
|
|
192
|
-
this.verifyHeader(
|
|
202
|
+
const iModChunk = readRIFFChunk(presetChunk.chunkData);
|
|
203
|
+
this.verifyHeader(iModChunk, "imod");
|
|
193
204
|
|
|
194
|
-
const
|
|
195
|
-
this.verifyHeader(
|
|
205
|
+
const iGenChunk = readRIFFChunk(presetChunk.chunkData);
|
|
206
|
+
this.verifyHeader(iGenChunk, "igen");
|
|
196
207
|
|
|
197
|
-
const
|
|
198
|
-
this.verifyHeader(
|
|
208
|
+
const sHdrChunk = readRIFFChunk(presetChunk.chunkData);
|
|
209
|
+
this.verifyHeader(sHdrChunk, "shdr");
|
|
199
210
|
|
|
200
211
|
/**
|
|
201
212
|
* read all the samples
|
|
202
213
|
* (the current index points to start of the smpl read)
|
|
203
214
|
*/
|
|
204
215
|
this.dataArray.currentIndex = this.sampleDataStartIndex;
|
|
205
|
-
this.samples.push(...readSamples(
|
|
216
|
+
this.samples.push(...readSamples(sHdrChunk, sampleData, !isSF2Pack));
|
|
206
217
|
|
|
207
218
|
/**
|
|
208
219
|
* read all the instrument generators
|
|
209
220
|
* @type {Generator[]}
|
|
210
221
|
*/
|
|
211
|
-
let instrumentGenerators = readGenerators(
|
|
222
|
+
let instrumentGenerators = readGenerators(iGenChunk);
|
|
212
223
|
|
|
213
224
|
/**
|
|
214
225
|
* read all the instrument modulators
|
|
215
226
|
* @type {Modulator[]}
|
|
216
227
|
*/
|
|
217
|
-
let instrumentModulators = readModulators(
|
|
228
|
+
let instrumentModulators = readModulators(iModChunk);
|
|
229
|
+
|
|
230
|
+
this.instruments = readInstruments(instChunk);
|
|
218
231
|
/**
|
|
219
|
-
* read all the instrument zones
|
|
232
|
+
* read all the instrument zones (and apply them)
|
|
220
233
|
* @type {InstrumentZone[]}
|
|
221
234
|
*/
|
|
222
|
-
|
|
223
|
-
|
|
235
|
+
readInstrumentZones(
|
|
236
|
+
iBagChunk,
|
|
224
237
|
instrumentGenerators,
|
|
225
238
|
instrumentModulators,
|
|
226
|
-
this.samples
|
|
239
|
+
this.samples,
|
|
240
|
+
this.instruments
|
|
227
241
|
);
|
|
228
242
|
|
|
229
|
-
this.instruments = readInstruments(presetInstrumentsChunk, instrumentZones);
|
|
230
|
-
|
|
231
243
|
/**
|
|
232
244
|
* read all the preset generators
|
|
233
245
|
* @type {Generator[]}
|
|
234
246
|
*/
|
|
235
|
-
let presetGenerators = readGenerators(
|
|
247
|
+
let presetGenerators = readGenerators(pGenChunk);
|
|
236
248
|
|
|
237
249
|
/**
|
|
238
250
|
* Read all the preset modulatorrs
|
|
239
251
|
* @type {Modulator[]}
|
|
240
252
|
*/
|
|
241
|
-
let presetModulators = readModulators(
|
|
253
|
+
let presetModulators = readModulators(pModChunk);
|
|
242
254
|
|
|
243
|
-
|
|
255
|
+
this.addPresets(...readPresets(pHdrChunk, this));
|
|
244
256
|
|
|
245
|
-
|
|
257
|
+
readPresetZones(pBagChunk, presetGenerators, presetModulators, this.instruments, this.presets);
|
|
246
258
|
this.flush();
|
|
247
259
|
SpessaSynthInfo(
|
|
248
260
|
`%cParsing finished! %c"${this.soundFontInfo["INAM"]}"%c has %c${this.presets.length} %cpresets,
|