spessoplayer 0.7.8-beta → 0.8.0-beta
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/COMMAND-LINE-OPTIONS.md +42 -13
- package/audioBuffer.mjs +46 -58
- package/cli.mjs +137 -101
- package/fileWriter_worker.mjs +35 -0
- package/install.mjs +27 -18
- package/main.mjs +165 -1050
- package/mainFunctions.mjs +1068 -0
- package/package.json +8 -1
- package/prepublish.mjs +11 -0
- package/typedefs.mjs +156 -0
- package/uninstall.mjs +25 -12
- package/utils/classes.mjs +53 -5
- package/utils/install_uninstall.mjs +35 -1
- package/utils/utils.mjs +157 -34
- package/tests/checkCliArguments.mjs +0 -100
package/COMMAND-LINE-OPTIONS.md
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
### spessoplayer [options] \<midi\> \<soundfont\> [outFile]
|
|
4
4
|
|
|
5
|
-
### --volume, /volume,
|
|
5
|
+
### --volume, /volume,
|
|
6
|
+
#### -v, /v:
|
|
6
7
|
Volume to set (*default: 100%*)
|
|
7
8
|
|
|
8
9
|
Available formats:
|
|
@@ -10,33 +11,40 @@
|
|
|
10
11
|
- **percentages** (*example 70%*);
|
|
11
12
|
- **decimals** (*example 0.9*);
|
|
12
13
|
|
|
13
|
-
### --reverb-volume, /reverb-volume,
|
|
14
|
+
### --reverb-volume, /reverb-volume,
|
|
15
|
+
#### -rvb, /rvb:
|
|
14
16
|
Volume to set for reverb (*default: none*)
|
|
15
|
-
|
|
17
|
+
|
|
16
18
|
Same formats as volume
|
|
17
19
|
|
|
18
|
-
### --effects, /effects,
|
|
20
|
+
### --effects, /effects,
|
|
21
|
+
#### -e, /e:
|
|
19
22
|
Adds any effects that SoX provides (*e.g "reverb,fade 1"*)
|
|
20
23
|
|
|
21
|
-
### --loop, /loop,
|
|
24
|
+
### --loop, /loop,
|
|
25
|
+
#### -l, /l:
|
|
22
26
|
Loop x amount of times (*default: 0*)
|
|
23
27
|
|
|
24
28
|
<sub>(It might be slow with bigger numbers)</sub>
|
|
25
29
|
|
|
26
|
-
### --loop-start, /loop-start,
|
|
30
|
+
### --loop-start, /loop-start,
|
|
31
|
+
#### -ls, /ls:
|
|
27
32
|
When the loop starts
|
|
28
33
|
|
|
29
|
-
### --loop-end, /loop-end,
|
|
34
|
+
### --loop-end, /loop-end,
|
|
35
|
+
#### -le, /le:
|
|
30
36
|
When the loop ends
|
|
31
37
|
|
|
32
|
-
### --sample-rate, /sample-rate,
|
|
38
|
+
### --sample-rate, /sample-rate,
|
|
39
|
+
#### -r, /r:
|
|
33
40
|
Sample rate to use (*default: 48000*)
|
|
34
41
|
|
|
35
42
|
<sub>(It might be slow with bigger numbers for players like mpv)</sub>
|
|
36
43
|
|
|
37
44
|
<sub>(Some players might downsize it to a smaller frequency)</sub>
|
|
38
45
|
|
|
39
|
-
### --format, /format,
|
|
46
|
+
### --format, /format,
|
|
47
|
+
#### -f, /f:
|
|
40
48
|
Format to use for stdout (*default: wav*)
|
|
41
49
|
|
|
42
50
|
Available formats:
|
|
@@ -45,16 +53,37 @@ Available formats:
|
|
|
45
53
|
- **flac**;
|
|
46
54
|
- **pcm (s32le)**;
|
|
47
55
|
|
|
48
|
-
### --
|
|
56
|
+
### --ask, /ask, --confirm, /confirm,
|
|
57
|
+
#### -a, /a, -c, /c:
|
|
58
|
+
Asks for confirmation before proceeding
|
|
59
|
+
|
|
60
|
+
### --no-table, /no-table,
|
|
61
|
+
#### -nt, /nt:
|
|
62
|
+
When asking for confirmation,
|
|
63
|
+
it'll show the information in a JSON-like format instead of a table
|
|
64
|
+
|
|
65
|
+
### --dry-run, /dry-run, --test, /test, --null, /null,
|
|
66
|
+
#### -dr, /dr, -t, /t, -0, /0:
|
|
67
|
+
Runs the program as normal but
|
|
68
|
+
it'll write to /dev/null on unix and \\.\nul on windows.
|
|
69
|
+
|
|
70
|
+
Mainly used for testing purposes but
|
|
71
|
+
can be useful when trying to debug with log options
|
|
72
|
+
|
|
73
|
+
### --verbose, /verbose,
|
|
74
|
+
#### -v, /v:
|
|
49
75
|
Sets the verbosity (*default: 2*)
|
|
50
76
|
|
|
51
|
-
### --log-file, /log-file,
|
|
77
|
+
### --log-file, /log-file,
|
|
78
|
+
#### -lf, /lf:
|
|
52
79
|
Sets path to the log file (*default: ./spesso.log*)
|
|
53
80
|
<sub>(Meanwhile it writes to file, it also prints to stderr)</sub>
|
|
54
81
|
|
|
55
|
-
### --help, /help,
|
|
82
|
+
### --help, /help,
|
|
83
|
+
#### -h, /h, /?:
|
|
56
84
|
Shows this help message
|
|
57
85
|
|
|
58
|
-
### --version, /version
|
|
86
|
+
### --version, /version
|
|
87
|
+
#### -V, /V:
|
|
59
88
|
Shows the installed version
|
|
60
89
|
|
package/audioBuffer.mjs
CHANGED
|
@@ -25,16 +25,11 @@ import {
|
|
|
25
25
|
} from "spessasynth_core"
|
|
26
26
|
// This section is identical to what's inside spessasynth_core but not being exported, that's why it's here
|
|
27
27
|
function fillWithDefaults(obj, defObj) {
|
|
28
|
-
return {
|
|
29
|
-
...defObj,
|
|
30
|
-
...obj ?? {}
|
|
31
|
-
};
|
|
28
|
+
return { ...defObj, ...obj ?? {} };
|
|
32
29
|
}
|
|
33
30
|
function writeBinaryStringIndexed(outArray, string, padLength = 0) {
|
|
34
31
|
if (padLength > 0) {
|
|
35
|
-
if (string.length > padLength)
|
|
36
|
-
string = string.slice(0, padLength);
|
|
37
|
-
}
|
|
32
|
+
if (string.length > padLength) string = string.slice(0, padLength)
|
|
38
33
|
}
|
|
39
34
|
for (let i = 0; i < string.length; i++) {
|
|
40
35
|
outArray[outArray.currentIndex++] = string.charCodeAt(i);
|
|
@@ -52,7 +47,7 @@ function writeLittleEndianIndexed(dataArray, number, byteTarget) {
|
|
|
52
47
|
}
|
|
53
48
|
}
|
|
54
49
|
function writeDword(dataArray, dword) {
|
|
55
|
-
writeLittleEndianIndexed(dataArray, dword, 4)
|
|
50
|
+
writeLittleEndianIndexed(dataArray, dword, 4)
|
|
56
51
|
}
|
|
57
52
|
function writeRIFFChunkParts(header, chunks, isList = false) {
|
|
58
53
|
let dataOffset = 8;
|
|
@@ -65,31 +60,26 @@ function writeRIFFChunkParts(header, chunks, isList = false) {
|
|
|
65
60
|
headerWritten = "LIST";
|
|
66
61
|
}
|
|
67
62
|
let finalSize = dataOffset + dataLength;
|
|
68
|
-
if (finalSize % 2 !== 0)
|
|
69
|
-
|
|
70
|
-
}
|
|
63
|
+
if (finalSize % 2 !== 0) finalSize++
|
|
64
|
+
|
|
71
65
|
const outArray = new IndexedByteArray(finalSize);
|
|
72
66
|
writeBinaryStringIndexed(outArray, headerWritten);
|
|
73
67
|
writeDword(outArray, writtenSize);
|
|
74
|
-
if (isList)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
outArray.set(c, dataOffset);
|
|
68
|
+
if (isList) writeBinaryStringIndexed(outArray, header);
|
|
69
|
+
|
|
70
|
+
chunks.forEach(c => {
|
|
71
|
+
outArray.set(c, dataOffset)
|
|
79
72
|
dataOffset += c.length;
|
|
80
|
-
})
|
|
73
|
+
})
|
|
81
74
|
return outArray;
|
|
82
75
|
}
|
|
83
76
|
function writeRIFFChunkRaw(header, data, addZeroByte = false, isList = false) {
|
|
84
|
-
if (header.length !== 4) {
|
|
85
|
-
throw new Error(`Invalid header length: ${header}`);
|
|
86
|
-
}
|
|
77
|
+
if (header.length !== 4) throw new Error(`Invalid header length: ${header}`)
|
|
87
78
|
let dataStartOffset = 8;
|
|
88
79
|
let headerWritten = header;
|
|
89
80
|
let dataLength = data.length;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
81
|
+
|
|
82
|
+
if (addZeroByte) dataLength++
|
|
93
83
|
let writtenSize = dataLength;
|
|
94
84
|
if (isList) {
|
|
95
85
|
dataStartOffset += 4;
|
|
@@ -97,29 +87,27 @@ function writeRIFFChunkRaw(header, data, addZeroByte = false, isList = false) {
|
|
|
97
87
|
headerWritten = "LIST";
|
|
98
88
|
}
|
|
99
89
|
let finalSize = dataStartOffset + dataLength;
|
|
100
|
-
if (finalSize % 2 !== 0)
|
|
101
|
-
|
|
102
|
-
}
|
|
90
|
+
if (finalSize % 2 !== 0) finalSize++
|
|
91
|
+
|
|
103
92
|
const outArray = new IndexedByteArray(finalSize);
|
|
104
93
|
writeBinaryStringIndexed(outArray, headerWritten);
|
|
105
94
|
writeDword(outArray, writtenSize);
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
95
|
+
|
|
96
|
+
if (isList) writeBinaryStringIndexed(outArray, header);
|
|
109
97
|
outArray.set(data, dataStartOffset);
|
|
110
98
|
return outArray;
|
|
111
99
|
}
|
|
112
100
|
|
|
113
101
|
/**
|
|
114
102
|
* WAV Header Generator
|
|
115
|
-
* @param {
|
|
116
|
-
* @param {Number}
|
|
117
|
-
* @param {Number} audioData.numChannels - How many channels the audio has
|
|
118
|
-
* @param {Number} sampleRate - Sample rate of the audio
|
|
103
|
+
* @param {module:typeDefinitions~getWavHeaderObjectParameters} audioData - An object that contains infos about the audio
|
|
104
|
+
* @param {Number} [sampleRate=48000] - Sample rate of the audio
|
|
119
105
|
* @param {Object} [options=DEFAULT_WAV_WRITE_OPTIONS] - Optional, adds loop timestamps and more
|
|
120
106
|
* @returns {Uint8Array} the wav header
|
|
121
107
|
*/
|
|
122
|
-
function getWavHeader({ length, numChannels },
|
|
108
|
+
function getWavHeader({ length, numChannels },
|
|
109
|
+
sampleRate = 48000, options = DEFAULT_WAV_WRITE_OPTIONS
|
|
110
|
+
) {
|
|
123
111
|
const bytesPerSample = 2;
|
|
124
112
|
const fullOptions = fillWithDefaults(options, DEFAULT_WAV_WRITE_OPTIONS);
|
|
125
113
|
const loop = fullOptions.loop;
|
|
@@ -162,6 +150,7 @@ function getWavHeader({ length, numChannels }, sampleRate, options = DEFAULT_WAV
|
|
|
162
150
|
if (cueOn) {
|
|
163
151
|
const loopStartSamples = Math.floor(loop.start * sampleRate);
|
|
164
152
|
const loopEndSamples = Math.floor(loop.end * sampleRate);
|
|
153
|
+
|
|
165
154
|
const cueStart = new IndexedByteArray(24);
|
|
166
155
|
writeLittleEndianIndexed(cueStart, 0, 4);
|
|
167
156
|
writeLittleEndianIndexed(cueStart, 0, 4);
|
|
@@ -169,6 +158,7 @@ function getWavHeader({ length, numChannels }, sampleRate, options = DEFAULT_WAV
|
|
|
169
158
|
writeLittleEndianIndexed(cueStart, 0, 4);
|
|
170
159
|
writeLittleEndianIndexed(cueStart, 0, 4);
|
|
171
160
|
writeLittleEndianIndexed(cueStart, loopStartSamples, 4);
|
|
161
|
+
|
|
172
162
|
const cueEnd = new IndexedByteArray(24);
|
|
173
163
|
writeLittleEndianIndexed(cueEnd, 1, 4);
|
|
174
164
|
writeLittleEndianIndexed(cueEnd, 0, 4);
|
|
@@ -176,6 +166,7 @@ function getWavHeader({ length, numChannels }, sampleRate, options = DEFAULT_WAV
|
|
|
176
166
|
writeLittleEndianIndexed(cueEnd, 0, 4);
|
|
177
167
|
writeLittleEndianIndexed(cueEnd, 0, 4);
|
|
178
168
|
writeLittleEndianIndexed(cueEnd, loopEndSamples, 4);
|
|
169
|
+
|
|
179
170
|
cueChunk = writeRIFFChunkParts("cue ", [
|
|
180
171
|
new IndexedByteArray([2, 0, 0, 0]),
|
|
181
172
|
// Cue points count
|
|
@@ -196,7 +187,7 @@ function getWavHeader({ length, numChannels }, sampleRate, options = DEFAULT_WAV
|
|
|
196
187
|
fileSize >> 24 & 255
|
|
197
188
|
]),
|
|
198
189
|
4
|
|
199
|
-
)
|
|
190
|
+
)
|
|
200
191
|
header.set([87, 65, 86, 69], 8); // "WAVE"
|
|
201
192
|
header.set([102, 109, 116, 32], 12); // "fmt "
|
|
202
193
|
header.set([16, 0, 0, 0], 16); // BlocSize
|
|
@@ -210,7 +201,7 @@ function getWavHeader({ length, numChannels }, sampleRate, options = DEFAULT_WAV
|
|
|
210
201
|
sampleRate >> 24 & 255
|
|
211
202
|
]),
|
|
212
203
|
24
|
|
213
|
-
)
|
|
204
|
+
)
|
|
214
205
|
const byteRate = sampleRate * numChannels * bytesPerSample;
|
|
215
206
|
header.set(
|
|
216
207
|
new Uint8Array([
|
|
@@ -220,7 +211,7 @@ function getWavHeader({ length, numChannels }, sampleRate, options = DEFAULT_WAV
|
|
|
220
211
|
byteRate >> 24 & 255
|
|
221
212
|
]),
|
|
222
213
|
28
|
|
223
|
-
)
|
|
214
|
+
)
|
|
224
215
|
header.set([numChannels * bytesPerSample, 0], 32); // BytePerBloc
|
|
225
216
|
header.set([16, 0], 34); // BitsPerSample
|
|
226
217
|
header.set([100, 97, 116, 97], 36); // "data"
|
|
@@ -232,37 +223,34 @@ function getWavHeader({ length, numChannels }, sampleRate, options = DEFAULT_WAV
|
|
|
232
223
|
dataSize >> 24 & 255
|
|
233
224
|
]),
|
|
234
225
|
40
|
|
235
|
-
)
|
|
226
|
+
)
|
|
236
227
|
return header;
|
|
237
228
|
}
|
|
238
229
|
|
|
239
230
|
/**
|
|
240
|
-
* Translates to PCM data
|
|
231
|
+
* Translates to audible PCM data
|
|
241
232
|
* @param {Array} audioData - An array that contains the audio buffers
|
|
242
|
-
* @param {Number} sampleRate - Sample rate of the audio
|
|
243
233
|
* @param {Object} options - Optional, adds loop timestamps and more
|
|
244
234
|
* @returns {Uint8Array} the translated data
|
|
245
235
|
*/
|
|
246
|
-
function getData(audioData,
|
|
247
|
-
const length = audioData[0].length
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
const bytesPerSample = 2;
|
|
236
|
+
function getData(audioData, options = DEFAULT_WAV_WRITE_OPTIONS) {
|
|
237
|
+
const length = audioData[0].length,
|
|
238
|
+
numChannels = audioData.length,
|
|
239
|
+
fullOptions = fillWithDefaults(options, DEFAULT_WAV_WRITE_OPTIONS),
|
|
240
|
+
bytesPerSample = 2;
|
|
252
241
|
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
242
|
+
const fileSize = length * numChannels * bytesPerSample,
|
|
243
|
+
Data = new Uint8Array(fileSize);
|
|
244
|
+
|
|
245
|
+
let offset = 0,
|
|
246
|
+
multiplier = 32767;
|
|
258
247
|
// Volume
|
|
259
|
-
let multiplier = 32767;
|
|
260
248
|
/*if (fullOptions.normalizeAudio) {
|
|
261
249
|
const numSamples = audioData[0].length;
|
|
262
250
|
let maxAbsValue = 0;
|
|
263
251
|
for (let ch = 0; ch < numChannels; ch++) {
|
|
264
252
|
const data = audioData[ch];
|
|
265
|
-
|
|
253
|
+
|
|
266
254
|
for (let i = 0; i < numSamples; i++) {
|
|
267
255
|
const sample = Math.abs(data[i]);
|
|
268
256
|
if (sample > maxAbsValue) {
|
|
@@ -270,22 +258,22 @@ function getData(audioData, sampleRate, options = DEFAULT_WAV_WRITE_OPTIONS) {
|
|
|
270
258
|
}
|
|
271
259
|
}
|
|
272
260
|
}
|
|
273
|
-
multiplier = maxAbsValue > 0
|
|
274
|
-
? 32767 / maxAbsValue
|
|
261
|
+
multiplier = maxAbsValue > 0
|
|
262
|
+
? 32767 / maxAbsValue
|
|
275
263
|
: 1;
|
|
276
264
|
}*/
|
|
277
265
|
for (let i = 0; i < length; i++) {
|
|
278
|
-
|
|
266
|
+
for (const d of audioData) {
|
|
279
267
|
const sample = Math.min(32767, Math.max(-32768, d[i] * multiplier));
|
|
280
268
|
Data[offset++] = sample & 255;
|
|
281
269
|
Data[offset++] = sample >> 8 & 255;
|
|
282
|
-
}
|
|
270
|
+
}
|
|
283
271
|
}
|
|
284
272
|
return Data;
|
|
285
273
|
}
|
|
286
274
|
|
|
287
275
|
|
|
288
|
-
export {
|
|
276
|
+
export {
|
|
289
277
|
getWavHeader,
|
|
290
278
|
getData
|
|
291
279
|
}
|