spessasynth_core 3.26.29 → 3.26.31
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/README.md +0 -1
- package/package.json +1 -1
- package/src/midi/midi_tools/rmidi_writer.js +34 -35
- package/src/soundfont/basic_soundfont/basic_preset.js +1 -4
- package/src/soundfont/basic_soundfont/basic_sample.js +13 -3
- package/src/soundfont/basic_soundfont/basic_soundbank.js +9 -1
- package/src/soundfont/basic_soundfont/riff_chunk.js +78 -42
- package/src/soundfont/basic_soundfont/write_dls/art2.js +4 -4
- package/src/soundfont/basic_soundfont/write_dls/ins.js +14 -18
- package/src/soundfont/basic_soundfont/write_dls/lins.js +3 -6
- package/src/soundfont/basic_soundfont/write_dls/rgn2.js +8 -9
- package/src/soundfont/basic_soundfont/write_dls/wave.js +12 -35
- package/src/soundfont/basic_soundfont/write_dls/write_dls.js +18 -29
- package/src/soundfont/basic_soundfont/write_dls/wsmp.js +2 -2
- package/src/soundfont/basic_soundfont/write_dls/wvpl.js +3 -5
- package/src/soundfont/basic_soundfont/write_sf2/ibag.js +3 -11
- package/src/soundfont/basic_soundfont/write_sf2/igen.js +3 -11
- package/src/soundfont/basic_soundfont/write_sf2/imod.js +3 -11
- package/src/soundfont/basic_soundfont/write_sf2/inst.js +3 -12
- package/src/soundfont/basic_soundfont/write_sf2/pbag.js +3 -11
- package/src/soundfont/basic_soundfont/write_sf2/pgen.js +4 -11
- package/src/soundfont/basic_soundfont/write_sf2/phdr.js +3 -11
- package/src/soundfont/basic_soundfont/write_sf2/pmod.js +3 -11
- package/src/soundfont/basic_soundfont/write_sf2/sdta.js +56 -26
- package/src/soundfont/basic_soundfont/write_sf2/shdr.js +3 -11
- package/src/soundfont/basic_soundfont/write_sf2/write.js +23 -52
- package/src/soundfont/dls/dls_soundfont.js +1 -1
- package/src/soundfont/read_sf2/samples.js +20 -5
- package/src/soundfont/read_sf2/soundfont.js +1 -1
- package/src/utils/buffer_to_wav.js +12 -15
- package/src/utils/byte_functions/string.js +7 -2
- package/src/utils/indexed_array.js +0 -18
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
2
|
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
|
-
import {
|
|
3
|
+
import { writeRIFFChunkParts, writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
4
|
import { writeWavesample } from "./wsmp.js";
|
|
5
5
|
import { SpessaSynthInfo } from "../../../utils/loggin.js";
|
|
6
6
|
import { consoleColors } from "../../../utils/other.js";
|
|
@@ -19,7 +19,7 @@ export function writeDLSSample(sample)
|
|
|
19
19
|
writeDword(fmtData, sample.sampleRate * 2); // 16-bit samples
|
|
20
20
|
writeWord(fmtData, 2); // wBlockAlign
|
|
21
21
|
writeWord(fmtData, 16); // wBitsPerSample
|
|
22
|
-
const fmt =
|
|
22
|
+
const fmt = writeRIFFChunkRaw(
|
|
23
23
|
"fmt ",
|
|
24
24
|
fmtData
|
|
25
25
|
);
|
|
@@ -37,38 +37,16 @@ export function writeDLSSample(sample)
|
|
|
37
37
|
sample.sampleLoopEndIndex,
|
|
38
38
|
loop
|
|
39
39
|
);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
{
|
|
45
|
-
const data16 = new Int16Array(audio.length);
|
|
46
|
-
|
|
47
|
-
for (let i = 0; i < audio.length; i++)
|
|
48
|
-
{
|
|
49
|
-
// 32,767, as 32,768 may cause overflow (because vorbis can go above 1 sometimes)
|
|
50
|
-
data16[i] = audio[i] * 32767;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
data = writeRIFFOddSize(
|
|
55
|
-
"data",
|
|
56
|
-
new IndexedByteArray(data16.buffer)
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
else
|
|
60
|
-
{
|
|
61
|
-
data = writeRIFFOddSize(
|
|
62
|
-
"data",
|
|
63
|
-
sample.getRawData(false) // no vorbis allowed
|
|
64
|
-
);
|
|
65
|
-
}
|
|
40
|
+
let data = writeRIFFChunkRaw(
|
|
41
|
+
"data",
|
|
42
|
+
sample.getRawData(false) // no vorbis allowed
|
|
43
|
+
);
|
|
66
44
|
|
|
67
|
-
const inam =
|
|
45
|
+
const inam = writeRIFFChunkRaw(
|
|
68
46
|
"INAM",
|
|
69
47
|
getStringBytes(sample.sampleName, true)
|
|
70
48
|
);
|
|
71
|
-
const info =
|
|
49
|
+
const info = writeRIFFChunkRaw(
|
|
72
50
|
"INFO",
|
|
73
51
|
inam,
|
|
74
52
|
false,
|
|
@@ -80,15 +58,14 @@ export function writeDLSSample(sample)
|
|
|
80
58
|
consoleColors.value,
|
|
81
59
|
consoleColors.recognized
|
|
82
60
|
);
|
|
83
|
-
return
|
|
61
|
+
return writeRIFFChunkParts(
|
|
84
62
|
"wave",
|
|
85
|
-
|
|
63
|
+
[
|
|
86
64
|
fmt,
|
|
87
65
|
wsmp,
|
|
88
66
|
data,
|
|
89
67
|
info
|
|
90
|
-
]
|
|
91
|
-
false,
|
|
68
|
+
],
|
|
92
69
|
true
|
|
93
70
|
);
|
|
94
71
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { writeRIFFChunkParts, writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
2
2
|
import { writeDword } from "../../../utils/byte_functions/little_endian.js";
|
|
3
|
-
import {
|
|
3
|
+
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
4
4
|
import { writeLins } from "./lins.js";
|
|
5
|
-
import { getStringBytes
|
|
5
|
+
import { getStringBytes } from "../../../utils/byte_functions/string.js";
|
|
6
6
|
import { writeWavePool } from "./wvpl.js";
|
|
7
7
|
import { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd, SpessaSynthInfo } from "../../../utils/loggin.js";
|
|
8
8
|
import { consoleColors } from "../../../utils/other.js";
|
|
@@ -21,7 +21,7 @@ export function writeDLS()
|
|
|
21
21
|
// write colh
|
|
22
22
|
const colhNum = new IndexedByteArray(4);
|
|
23
23
|
writeDword(colhNum, this.presets.length);
|
|
24
|
-
const colh =
|
|
24
|
+
const colh = writeRIFFChunkRaw(
|
|
25
25
|
"colh",
|
|
26
26
|
colhNum
|
|
27
27
|
);
|
|
@@ -54,7 +54,7 @@ export function writeDLS()
|
|
|
54
54
|
{
|
|
55
55
|
writeDword(ptblData, offset);
|
|
56
56
|
}
|
|
57
|
-
const ptbl =
|
|
57
|
+
const ptbl = writeRIFFChunkRaw(
|
|
58
58
|
"ptbl",
|
|
59
59
|
ptblData
|
|
60
60
|
);
|
|
@@ -78,42 +78,31 @@ export function writeDLS()
|
|
|
78
78
|
continue;
|
|
79
79
|
}
|
|
80
80
|
infos.push(
|
|
81
|
-
|
|
81
|
+
writeRIFFChunkRaw(
|
|
82
82
|
info,
|
|
83
|
-
getStringBytes(data, true)
|
|
84
|
-
true
|
|
83
|
+
getStringBytes(data, true)
|
|
85
84
|
)
|
|
86
85
|
);
|
|
87
86
|
}
|
|
88
|
-
const info =
|
|
87
|
+
const info = writeRIFFChunkParts(
|
|
89
88
|
"INFO",
|
|
90
|
-
|
|
91
|
-
false,
|
|
89
|
+
infos,
|
|
92
90
|
true
|
|
93
91
|
);
|
|
94
|
-
|
|
95
|
-
const out = new IndexedByteArray(
|
|
96
|
-
colh.length
|
|
97
|
-
+ lins.length
|
|
98
|
-
+ ptbl.length
|
|
99
|
-
+ wvpl.length
|
|
100
|
-
+ info.length
|
|
101
|
-
+ 4);
|
|
102
|
-
writeStringAsBytes(out, "DLS ");
|
|
103
|
-
out.set(combineArrays([
|
|
104
|
-
colh,
|
|
105
|
-
lins,
|
|
106
|
-
ptbl,
|
|
107
|
-
wvpl,
|
|
108
|
-
info
|
|
109
|
-
]), 4);
|
|
110
92
|
SpessaSynthInfo(
|
|
111
93
|
"%cSaved succesfully!",
|
|
112
94
|
consoleColors.recognized
|
|
113
95
|
);
|
|
114
96
|
SpessaSynthGroupEnd();
|
|
115
|
-
return
|
|
97
|
+
return writeRIFFChunkParts(
|
|
116
98
|
"RIFF",
|
|
117
|
-
|
|
99
|
+
[
|
|
100
|
+
getStringBytes("DLS "),
|
|
101
|
+
colh,
|
|
102
|
+
lins,
|
|
103
|
+
ptbl,
|
|
104
|
+
wvpl,
|
|
105
|
+
info
|
|
106
|
+
]
|
|
118
107
|
);
|
|
119
108
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
2
2
|
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
3
|
-
import {
|
|
3
|
+
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
4
|
|
|
5
5
|
const WSMP_SIZE = 20;
|
|
6
6
|
|
|
@@ -71,7 +71,7 @@ export function writeWavesample(
|
|
|
71
71
|
writeDword(wsmpData, loopStart);
|
|
72
72
|
writeDword(wsmpData, loopSize);
|
|
73
73
|
}
|
|
74
|
-
return
|
|
74
|
+
return writeRIFFChunkRaw(
|
|
75
75
|
"wsmp",
|
|
76
76
|
wsmpData
|
|
77
77
|
);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { writeDLSSample } from "./wave.js";
|
|
2
|
-
import {
|
|
3
|
-
import { combineArrays } from "../../../utils/indexed_array.js";
|
|
2
|
+
import { writeRIFFChunkParts } from "../riff_chunk.js";
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* @this {BasicSoundBank}
|
|
@@ -21,10 +20,9 @@ export function writeWavePool()
|
|
|
21
20
|
return out;
|
|
22
21
|
});
|
|
23
22
|
return {
|
|
24
|
-
data:
|
|
23
|
+
data: writeRIFFChunkParts(
|
|
25
24
|
"wvpl",
|
|
26
|
-
|
|
27
|
-
false,
|
|
25
|
+
samples,
|
|
28
26
|
true
|
|
29
27
|
),
|
|
30
28
|
indexes: offsets
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
2
|
import { writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
|
-
import {
|
|
3
|
+
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
4
|
|
|
5
5
|
const BAG_SIZE = 4;
|
|
6
6
|
|
|
@@ -50,16 +50,8 @@ export function getIBAG()
|
|
|
50
50
|
writeWord(ibagData, modulatorIndex & 0xFFFF);
|
|
51
51
|
writeWord(xibagData, generatorIndex >> 16);
|
|
52
52
|
writeWord(xibagData, modulatorIndex >> 16);
|
|
53
|
-
const ibag =
|
|
54
|
-
|
|
55
|
-
ibagData.length,
|
|
56
|
-
ibagData
|
|
57
|
-
));
|
|
58
|
-
const xibag = writeRIFFChunk(new RiffChunk(
|
|
59
|
-
"ibag",
|
|
60
|
-
xibagData.length,
|
|
61
|
-
xibagData
|
|
62
|
-
));
|
|
53
|
+
const ibag = writeRIFFChunkRaw("ibag", ibagData);
|
|
54
|
+
const xibag = writeRIFFChunkRaw("ibag", xibagData);
|
|
63
55
|
return {
|
|
64
56
|
pdta: ibag,
|
|
65
57
|
xdta: xibag,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
2
2
|
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
3
|
-
import {
|
|
3
|
+
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
4
|
import { GEN_BYTE_SIZE, Generator } from "../generator.js";
|
|
5
5
|
import { generatorTypes } from "../generator_types.js";
|
|
6
6
|
|
|
@@ -81,16 +81,8 @@ export function getIGEN()
|
|
|
81
81
|
const xigenData = new IndexedByteArray(GEN_BYTE_SIZE);
|
|
82
82
|
writeDword(xigenData, 0);
|
|
83
83
|
|
|
84
|
-
const igen =
|
|
85
|
-
|
|
86
|
-
igenData.length,
|
|
87
|
-
igenData
|
|
88
|
-
));
|
|
89
|
-
const xigen = writeRIFFChunk(new RiffChunk(
|
|
90
|
-
"igen",
|
|
91
|
-
xigenData.length,
|
|
92
|
-
xigenData
|
|
93
|
-
));
|
|
84
|
+
const igen = writeRIFFChunkRaw("igen", igenData);
|
|
85
|
+
const xigen = writeRIFFChunkRaw("igen", xigenData);
|
|
94
86
|
return {
|
|
95
87
|
pdta: igen,
|
|
96
88
|
xdta: xigen,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
2
|
import { writeLittleEndian, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
|
-
import {
|
|
3
|
+
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
4
|
import { MOD_BYTE_SIZE } from "../modulator.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -52,16 +52,8 @@ export function getIMOD()
|
|
|
52
52
|
const ximodData = new IndexedByteArray(MOD_BYTE_SIZE);
|
|
53
53
|
writeLittleEndian(ximodData, 0, MOD_BYTE_SIZE);
|
|
54
54
|
|
|
55
|
-
const imod =
|
|
56
|
-
|
|
57
|
-
imodData.length,
|
|
58
|
-
imodData
|
|
59
|
-
));
|
|
60
|
-
const ximod = writeRIFFChunk(new RiffChunk(
|
|
61
|
-
"imod",
|
|
62
|
-
ximodData.length,
|
|
63
|
-
ximodData
|
|
64
|
-
));
|
|
55
|
+
const imod = writeRIFFChunkRaw("imod", imodData);
|
|
56
|
+
const ximod = writeRIFFChunkRaw("imod", ximodData);
|
|
65
57
|
return {
|
|
66
58
|
pdta: imod,
|
|
67
59
|
xdta: ximod,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
2
|
import { writeStringAsBytes } from "../../../utils/byte_functions/string.js";
|
|
3
3
|
import { writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
4
|
-
import {
|
|
4
|
+
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
5
5
|
|
|
6
6
|
const INST_SIZE = 22;
|
|
7
7
|
|
|
@@ -31,17 +31,8 @@ export function getINST()
|
|
|
31
31
|
writeWord(instData, instrumentStart & 0xFFFF);
|
|
32
32
|
writeWord(xinstData, instrumentStart >> 16);
|
|
33
33
|
|
|
34
|
-
const inst =
|
|
35
|
-
|
|
36
|
-
instData.length,
|
|
37
|
-
instData
|
|
38
|
-
));
|
|
39
|
-
|
|
40
|
-
const xinst = writeRIFFChunk(new RiffChunk(
|
|
41
|
-
"inst",
|
|
42
|
-
xinstData.length,
|
|
43
|
-
xinstData
|
|
44
|
-
));
|
|
34
|
+
const inst = writeRIFFChunkRaw("inst", instData);
|
|
35
|
+
const xinst = writeRIFFChunkRaw("inst", xinstData);
|
|
45
36
|
|
|
46
37
|
return {
|
|
47
38
|
pdta: inst,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
2
|
import { writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
|
-
import {
|
|
3
|
+
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
4
|
|
|
5
5
|
const BAG_SIZE = 4;
|
|
6
6
|
|
|
@@ -47,16 +47,8 @@ export function getPBAG()
|
|
|
47
47
|
writeWord(pbagData, modulatorIndex);
|
|
48
48
|
writeWord(xpbagData, generatorIndex);
|
|
49
49
|
writeWord(xpbagData, modulatorIndex);
|
|
50
|
-
const pbag =
|
|
51
|
-
|
|
52
|
-
pbagData.length,
|
|
53
|
-
pbagData
|
|
54
|
-
));
|
|
55
|
-
const xbag = writeRIFFChunk(new RiffChunk(
|
|
56
|
-
"pbag",
|
|
57
|
-
xpbagData.length,
|
|
58
|
-
xpbagData
|
|
59
|
-
));
|
|
50
|
+
const pbag = writeRIFFChunkRaw("pbag", pbagData);
|
|
51
|
+
const xbag = writeRIFFChunkRaw("pbag", xpbagData);
|
|
60
52
|
return {
|
|
61
53
|
pdta: pbag,
|
|
62
54
|
xdta: xbag,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
2
2
|
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
3
|
-
import {
|
|
3
|
+
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
4
|
|
|
5
5
|
import { GEN_BYTE_SIZE, Generator } from "../generator.js";
|
|
6
6
|
import { generatorTypes } from "../generator_types.js";
|
|
@@ -81,16 +81,9 @@ export function getPGEN()
|
|
|
81
81
|
const xpgenData = new IndexedByteArray(GEN_BYTE_SIZE);
|
|
82
82
|
writeDword(xpgenData, 0);
|
|
83
83
|
|
|
84
|
-
const pgen =
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
pgenData
|
|
88
|
-
));
|
|
89
|
-
const xpgen = writeRIFFChunk(new RiffChunk(
|
|
90
|
-
"pgen",
|
|
91
|
-
xpgenData.length,
|
|
92
|
-
xpgenData
|
|
93
|
-
));
|
|
84
|
+
const pgen = writeRIFFChunkRaw("pgen", pgenData);
|
|
85
|
+
|
|
86
|
+
const xpgen = writeRIFFChunkRaw("pgen", xpgenData);
|
|
94
87
|
return {
|
|
95
88
|
pdta: pgen,
|
|
96
89
|
xdta: xpgen,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
2
|
import { writeStringAsBytes } from "../../../utils/byte_functions/string.js";
|
|
3
3
|
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
4
|
-
import {
|
|
4
|
+
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
5
5
|
|
|
6
6
|
const PHDR_SIZE = 38;
|
|
7
7
|
|
|
@@ -49,17 +49,9 @@ export function getPHDR()
|
|
|
49
49
|
writeWord(xphdrData, presetStart >> 16);
|
|
50
50
|
xphdrData.currentIndex += 12;// library, genre, morphology
|
|
51
51
|
|
|
52
|
-
const phdr =
|
|
53
|
-
"phdr",
|
|
54
|
-
phdrData.length,
|
|
55
|
-
phdrData
|
|
56
|
-
));
|
|
52
|
+
const phdr = writeRIFFChunkRaw("phdr", phdrData);
|
|
57
53
|
|
|
58
|
-
const xphdr =
|
|
59
|
-
"phdr",
|
|
60
|
-
xphdrData.length,
|
|
61
|
-
xphdrData
|
|
62
|
-
));
|
|
54
|
+
const xphdr = writeRIFFChunkRaw("phdr", xphdrData);
|
|
63
55
|
|
|
64
56
|
return {
|
|
65
57
|
pdta: phdr,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
2
|
import { writeLittleEndian, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
|
-
import {
|
|
3
|
+
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
4
|
import { MOD_BYTE_SIZE } from "../modulator.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -52,16 +52,8 @@ export function getPMOD()
|
|
|
52
52
|
const xpmodData = new IndexedByteArray(MOD_BYTE_SIZE);
|
|
53
53
|
writeLittleEndian(xpmodData, 0, MOD_BYTE_SIZE);
|
|
54
54
|
|
|
55
|
-
const pmod =
|
|
56
|
-
|
|
57
|
-
pmodData.length,
|
|
58
|
-
pmodData
|
|
59
|
-
));
|
|
60
|
-
const xpmod = writeRIFFChunk(new RiffChunk(
|
|
61
|
-
"pmod",
|
|
62
|
-
xpmodData.length,
|
|
63
|
-
xpmodData
|
|
64
|
-
));
|
|
55
|
+
const pmod = writeRIFFChunkRaw("pmod", pmodData);
|
|
56
|
+
const xpmod = writeRIFFChunkRaw("pmod", xpmodData);
|
|
65
57
|
return {
|
|
66
58
|
pdta: pmod,
|
|
67
59
|
xdta: xpmod,
|
|
@@ -1,7 +1,25 @@
|
|
|
1
|
-
import { RiffChunk, writeRIFFChunk } from "../riff_chunk.js";
|
|
2
|
-
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
3
1
|
import { SpessaSynthInfo } from "../../../utils/loggin.js";
|
|
4
2
|
import { consoleColors } from "../../../utils/other.js";
|
|
3
|
+
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
4
|
+
import { writeStringAsBytes } from "../../../utils/byte_functions/string.js";
|
|
5
|
+
import { writeLittleEndian } from "../../../utils/byte_functions/little_endian.js";
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
Sdta structure:
|
|
9
|
+
|
|
10
|
+
LIST chunk
|
|
11
|
+
- "sdta" ASCII string
|
|
12
|
+
- smpl chunk
|
|
13
|
+
- - raw data
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// in bytes, from the start of sdta-LIST to the first actual sample
|
|
17
|
+
const SDTA_TO_DATA_OFFSET =
|
|
18
|
+
4 + // "LIST"
|
|
19
|
+
4 + // sdta size
|
|
20
|
+
4 + // "sdta"
|
|
21
|
+
4 + // "smpl"
|
|
22
|
+
4; // smpl size
|
|
5
23
|
|
|
6
24
|
/**
|
|
7
25
|
* @this {BasicSoundBank}
|
|
@@ -10,18 +28,20 @@ import { consoleColors } from "../../../utils/other.js";
|
|
|
10
28
|
* @param compress {boolean}
|
|
11
29
|
* @param quality {number}
|
|
12
30
|
* @param vorbisFunc {EncodeVorbisFunction}
|
|
13
|
-
* @returns {
|
|
31
|
+
* @returns {Uint8Array}
|
|
14
32
|
*/
|
|
15
33
|
export function getSDTA(smplStartOffsets, smplEndOffsets, compress, quality, vorbisFunc)
|
|
16
34
|
{
|
|
17
35
|
// write smpl: write int16 data of each sample linearly
|
|
18
36
|
// get size (calling getAudioData twice doesn't matter since it gets cached)
|
|
37
|
+
let smplChunkSize = 0;
|
|
19
38
|
const sampleDatas = this.samples.map((s, i) =>
|
|
20
39
|
{
|
|
21
40
|
if (compress)
|
|
22
41
|
{
|
|
23
42
|
s.compressSample(quality, vorbisFunc);
|
|
24
43
|
}
|
|
44
|
+
// raw data: either copy s16le or encoded vorbis or encode manually if overridden
|
|
25
45
|
const r = s.getRawData();
|
|
26
46
|
SpessaSynthInfo(
|
|
27
47
|
`%cEncoded sample %c${i}. ${s.sampleName}%c of %c${this.samples.length}%c. Compressed: %c${s.isCompressed}%c.`,
|
|
@@ -33,48 +53,58 @@ export function getSDTA(smplStartOffsets, smplEndOffsets, compress, quality, vor
|
|
|
33
53
|
s.isCompressed ? consoleColors.recognized : consoleColors.unrecognized,
|
|
34
54
|
consoleColors.info
|
|
35
55
|
);
|
|
56
|
+
/* 6.1 Sample Data Format in the smpl Sub-chunk
|
|
57
|
+
Each sample is followed by a minimum of forty-six zero
|
|
58
|
+
valued sample data points. These zero valued data points are necessary to guarantee that any reasonable upward pitch shift
|
|
59
|
+
using any reasonable interpolator can loop on zero data at the end of the sound.
|
|
60
|
+
This doesn't apply to sf3 tho
|
|
61
|
+
*/
|
|
62
|
+
smplChunkSize += r.length + (s.isCompressed ? 0 : 92); // 92 = 46 sample data points
|
|
36
63
|
return r;
|
|
37
64
|
});
|
|
38
|
-
|
|
65
|
+
|
|
66
|
+
if (smplChunkSize % 2 !== 0)
|
|
39
67
|
{
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
68
|
+
smplChunkSize++;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const sdta = new IndexedByteArray(smplChunkSize + SDTA_TO_DATA_OFFSET);
|
|
72
|
+
|
|
73
|
+
// avoid using writeRIFFChunk for performance
|
|
74
|
+
// sdta chunk
|
|
75
|
+
writeStringAsBytes(sdta, "LIST");
|
|
76
|
+
// "sdta" + full smpl length
|
|
77
|
+
writeLittleEndian(sdta, smplChunkSize + SDTA_TO_DATA_OFFSET - 8, 4);
|
|
78
|
+
writeStringAsBytes(sdta, "sdta");
|
|
79
|
+
writeStringAsBytes(sdta, "smpl");
|
|
80
|
+
writeLittleEndian(sdta, smplChunkSize, 4);
|
|
81
|
+
|
|
82
|
+
let offset = 0;
|
|
83
|
+
// write out
|
|
44
84
|
this.samples.forEach((sample, i) =>
|
|
45
85
|
{
|
|
46
86
|
const data = sampleDatas[i];
|
|
87
|
+
sdta.set(data, offset + SDTA_TO_DATA_OFFSET);
|
|
47
88
|
let startOffset;
|
|
48
89
|
let endOffset;
|
|
49
|
-
let jump = data.length;
|
|
50
90
|
if (sample.isCompressed)
|
|
51
91
|
{
|
|
52
92
|
// sf3 offset is in bytes
|
|
53
|
-
startOffset =
|
|
93
|
+
startOffset = offset;
|
|
54
94
|
endOffset = startOffset + data.length;
|
|
55
95
|
}
|
|
56
96
|
else
|
|
57
97
|
{
|
|
58
98
|
// sf2 in sample data points
|
|
59
|
-
startOffset =
|
|
60
|
-
endOffset = startOffset + data.length / 2;
|
|
61
|
-
|
|
99
|
+
startOffset = offset / 2; // inclusive
|
|
100
|
+
endOffset = startOffset + data.length / 2; // exclusive
|
|
101
|
+
offset += 92; // 46 sample data points
|
|
62
102
|
}
|
|
103
|
+
offset += data.length;
|
|
63
104
|
smplStartOffsets.push(startOffset);
|
|
64
|
-
|
|
65
|
-
smplData.currentIndex += jump;
|
|
105
|
+
|
|
66
106
|
smplEndOffsets.push(endOffset);
|
|
67
107
|
});
|
|
68
108
|
|
|
69
|
-
|
|
70
|
-
"smpl",
|
|
71
|
-
smplData.length,
|
|
72
|
-
smplData
|
|
73
|
-
), new IndexedByteArray([115, 100, 116, 97])); // `sdta`
|
|
74
|
-
|
|
75
|
-
return writeRIFFChunk(new RiffChunk(
|
|
76
|
-
"LIST",
|
|
77
|
-
smplChunk.length,
|
|
78
|
-
smplChunk
|
|
79
|
-
));
|
|
109
|
+
return sdta;
|
|
80
110
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
2
|
import { writeStringAsBytes } from "../../../utils/byte_functions/string.js";
|
|
3
3
|
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
4
|
-
import {
|
|
4
|
+
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
5
5
|
import { SF3_BIT_FLIT } from "../../read_sf2/samples.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -67,16 +67,8 @@ export function getSHDR(smplStartOffsets, smplEndOffsets)
|
|
|
67
67
|
// write EOS and zero everything else
|
|
68
68
|
writeStringAsBytes(shdrData, "EOS", sampleLength);
|
|
69
69
|
writeStringAsBytes(xshdrData, "EOS", sampleLength);
|
|
70
|
-
const shdr =
|
|
71
|
-
|
|
72
|
-
shdrData.length,
|
|
73
|
-
shdrData
|
|
74
|
-
));
|
|
75
|
-
const xshdr = writeRIFFChunk(new RiffChunk(
|
|
76
|
-
"shdr",
|
|
77
|
-
xshdrData.length,
|
|
78
|
-
xshdrData
|
|
79
|
-
));
|
|
70
|
+
const shdr = writeRIFFChunkRaw("shdr", shdrData);
|
|
71
|
+
const xshdr = writeRIFFChunkRaw("shdr", xshdrData);
|
|
80
72
|
return {
|
|
81
73
|
pdta: shdr,
|
|
82
74
|
xdta: xshdr,
|