spessoplayer 0.7.6-beta → 0.7.8-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/audioBuffer.mjs +4 -1
- package/cli.mjs +241 -202
- package/main.mjs +133 -103
- package/package.json +5 -2
- package/tests/checkCliArguments.mjs +100 -0
- package/utils/classes.mjs +177 -0
- package/utils/install_uninstall.mjs +21 -24
- package/utils/utils.mjs +321 -243
package/audioBuffer.mjs
CHANGED
|
@@ -51,6 +51,9 @@ function writeLittleEndianIndexed(dataArray, number, byteTarget) {
|
|
|
51
51
|
dataArray[dataArray.currentIndex++] = number >> i * 8 & 255;
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
+
function writeDword(dataArray, dword) {
|
|
55
|
+
writeLittleEndianIndexed(dataArray, dword, 4);
|
|
56
|
+
}
|
|
54
57
|
function writeRIFFChunkParts(header, chunks, isList = false) {
|
|
55
58
|
let dataOffset = 8;
|
|
56
59
|
let headerWritten = header;
|
|
@@ -113,7 +116,7 @@ function writeRIFFChunkRaw(header, data, addZeroByte = false, isList = false) {
|
|
|
113
116
|
* @param {Number} audioData.length - Audio length in samples, essentially the sample count
|
|
114
117
|
* @param {Number} audioData.numChannels - How many channels the audio has
|
|
115
118
|
* @param {Number} sampleRate - Sample rate of the audio
|
|
116
|
-
* @param {Object} options - Optional, adds loop timestamps and more
|
|
119
|
+
* @param {Object} [options=DEFAULT_WAV_WRITE_OPTIONS] - Optional, adds loop timestamps and more
|
|
117
120
|
* @returns {Uint8Array} the wav header
|
|
118
121
|
*/
|
|
119
122
|
function getWavHeader({ length, numChannels }, sampleRate, options = DEFAULT_WAV_WRITE_OPTIONS) {
|
package/cli.mjs
CHANGED
|
@@ -22,6 +22,16 @@
|
|
|
22
22
|
import { join, basename, parse } from "path"
|
|
23
23
|
import { log, Options } from "./utils/utils.mjs"
|
|
24
24
|
|
|
25
|
+
/** @type {(Promise<String[]>|String[])} */
|
|
26
|
+
let argvWithoutFileExts = new Promise(resolve => {
|
|
27
|
+
const newArguments = [...new Set(process.argv.slice(2)).values()],
|
|
28
|
+
newArgumentsLength = newArguments.length;
|
|
29
|
+
for (let i = 0; i < newArgumentsLength; i++) {
|
|
30
|
+
const parsedElement = parse(newArguments[i]);
|
|
31
|
+
newArguments[i] = join(parsedElement.dir, parsedElement.name);
|
|
32
|
+
}
|
|
33
|
+
resolve(newArguments)
|
|
34
|
+
});
|
|
25
35
|
const regexes = {
|
|
26
36
|
help: /^(?:--help|\/help|-h|\/h|\/\?)$/,
|
|
27
37
|
version: /^(?:--version|\/version|-V|\/V)$/,
|
|
@@ -121,6 +131,11 @@ const testFunctions = {
|
|
|
121
131
|
logFile: i => regexes.logFile.test(i)
|
|
122
132
|
};
|
|
123
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Retrieves the first 20 bytes of a file
|
|
136
|
+
* @param {String} path path of file
|
|
137
|
+
* @return {Promise<String>} - first 20 bytes of file
|
|
138
|
+
*/
|
|
124
139
|
async function get20BytesFromFile(path) {
|
|
125
140
|
let fileMagicNumber;
|
|
126
141
|
await new Promise(resolve => {
|
|
@@ -136,15 +151,21 @@ async function get20BytesFromFile(path) {
|
|
|
136
151
|
})
|
|
137
152
|
return fileMagicNumber;
|
|
138
153
|
}
|
|
154
|
+
const setFilePromises = [];
|
|
139
155
|
/**
|
|
140
156
|
* Sets necessary variables in Options class for main.mjs
|
|
141
|
-
* @param {
|
|
157
|
+
* @param {String[]} args - The process.argv to analyse
|
|
142
158
|
* @throws {ReferenceError} - if the next argument doesn't exist
|
|
143
159
|
*/
|
|
144
160
|
const actUpOnPassedArgs = async (args) => {
|
|
145
161
|
let lastParam,
|
|
146
162
|
lastIndex;
|
|
147
163
|
let newArguments = args.slice(2);
|
|
164
|
+
const newArgumentsSet = new Set(newArguments),
|
|
165
|
+
noDuplicates = [...newArgumentsSet.values()],
|
|
166
|
+
/** @type {Map<String, (String|Symbol)>} */
|
|
167
|
+
doneFileList = new Map(newArgumentsSet.entries()),
|
|
168
|
+
doneSymbol = Symbol("ALREADY_DONE");
|
|
148
169
|
if (newArguments.length === 0) {
|
|
149
170
|
await help()
|
|
150
171
|
process.exit()
|
|
@@ -198,8 +219,12 @@ const actUpOnPassedArgs = async (args) => {
|
|
|
198
219
|
log(1, performance.now().toFixed(2), `Using variable DEBUG_FILE_SPESSO=${process.env["DEBUG_FILE_SPESSO"]}`)
|
|
199
220
|
}
|
|
200
221
|
|
|
201
|
-
|
|
202
|
-
|
|
222
|
+
function clearLastVariables() {
|
|
223
|
+
lastParam = undefined,
|
|
224
|
+
lastIndex = undefined;
|
|
225
|
+
}
|
|
226
|
+
let indexOfSetFile = 0,
|
|
227
|
+
lastAutomaticFile;
|
|
203
228
|
for (const arg of newArguments) {
|
|
204
229
|
switch (arg) {
|
|
205
230
|
case regexes.wav.test(arg) && arg: {
|
|
@@ -309,13 +334,25 @@ const actUpOnPassedArgs = async (args) => {
|
|
|
309
334
|
case (lastParam === "input" || lastParam === undefined)
|
|
310
335
|
&& regexes.fileCheck.test(basename(arg))
|
|
311
336
|
&& arg: {
|
|
337
|
+
if (doneFileList.get(arg) === doneSymbol) {
|
|
338
|
+
if (lastParam === "input") clearLastVariables()
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
doneFileList.set(arg, doneSymbol)
|
|
342
|
+
|
|
343
|
+
if (!global.fs) {
|
|
344
|
+
const fs = await import("node:fs");
|
|
345
|
+
global.fs = fs;
|
|
346
|
+
}
|
|
312
347
|
setFilePromises.push(
|
|
313
348
|
setFile({
|
|
314
|
-
|
|
315
|
-
|
|
349
|
+
indexOfSetFile: indexOfSetFile++,
|
|
350
|
+
lastParam, lastIndex, lastAutomaticFile,
|
|
351
|
+
newArguments: noDuplicates, arg
|
|
316
352
|
})
|
|
317
353
|
)
|
|
318
|
-
if (lastParam
|
|
354
|
+
if (!lastParam) lastAutomaticFile = arg;
|
|
355
|
+
if (lastParam === "input") clearLastVariables()
|
|
319
356
|
break;
|
|
320
357
|
}
|
|
321
358
|
|
|
@@ -323,35 +360,35 @@ const actUpOnPassedArgs = async (args) => {
|
|
|
323
360
|
switch (lastParam) {
|
|
324
361
|
case "loop":
|
|
325
362
|
setLoop(arg, lastIndex)
|
|
326
|
-
|
|
363
|
+
clearLastVariables()
|
|
327
364
|
break;
|
|
328
365
|
case "loop-start":
|
|
329
366
|
setLoopStart(arg, lastIndex)
|
|
330
|
-
|
|
367
|
+
clearLastVariables()
|
|
331
368
|
break;
|
|
332
369
|
case "loop-end":
|
|
333
370
|
setLoopEnd(arg, lastIndex)
|
|
334
|
-
|
|
371
|
+
clearLastVariables()
|
|
335
372
|
break;
|
|
336
373
|
case "sample-rate":
|
|
337
374
|
setSampleRate(arg, lastIndex, newArguments)
|
|
338
|
-
|
|
375
|
+
clearLastVariables()
|
|
339
376
|
break;
|
|
340
377
|
case "format":
|
|
341
|
-
setFormat(arg
|
|
342
|
-
|
|
378
|
+
setFormat(arg)
|
|
379
|
+
clearLastVariables()
|
|
343
380
|
break;
|
|
344
381
|
case "volume":
|
|
345
382
|
setVolume(arg, lastIndex)
|
|
346
|
-
|
|
383
|
+
clearLastVariables()
|
|
347
384
|
break;
|
|
348
385
|
case "reverb":
|
|
349
|
-
|
|
350
|
-
|
|
386
|
+
setReverb(arg, lastIndex)
|
|
387
|
+
clearLastVariables()
|
|
351
388
|
break;
|
|
352
389
|
case "effects":
|
|
353
|
-
|
|
354
|
-
|
|
390
|
+
setEffects(arg, lastIndex)
|
|
391
|
+
clearLastVariables()
|
|
355
392
|
break;
|
|
356
393
|
|
|
357
394
|
default:
|
|
@@ -366,17 +403,21 @@ const actUpOnPassedArgs = async (args) => {
|
|
|
366
403
|
}
|
|
367
404
|
}
|
|
368
405
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
406
|
+
/*
|
|
407
|
+
Adds files to the list asynchronously/in parallel
|
|
408
|
+
by chaining each function to the previous one
|
|
409
|
+
so that they stay syncronized and up to date.
|
|
410
|
+
|
|
411
|
+
This means there's no performance loss because of
|
|
412
|
+
the async nature of them and it remains in
|
|
413
|
+
a sequential order regardless of execution timings.
|
|
414
|
+
|
|
415
|
+
(e.g. sort order is the same like in process.argv
|
|
416
|
+
because each returned Promise waits before
|
|
417
|
+
actually adding the file)
|
|
418
|
+
*/
|
|
419
|
+
await Promise.all(await Promise.all(setFilePromises))
|
|
420
|
+
if (!Object.keys(Options.all.files ?? []).length) {
|
|
380
421
|
console.error(`${red}Missing required files${normal}`);
|
|
381
422
|
process.exit(1)
|
|
382
423
|
}
|
|
@@ -385,163 +426,165 @@ const actUpOnPassedArgs = async (args) => {
|
|
|
385
426
|
/**
|
|
386
427
|
* Sets a supported file inside a group in Options class
|
|
387
428
|
* @param {Object} passedVariables - variables injected with this object
|
|
429
|
+
* @param {Number} passedVariables.indexOfSetFile - index of the current function inside setFilePromises
|
|
388
430
|
* @param {String} passedVariables.lastParam - last parameter that has been used last time
|
|
389
|
-
* @param {
|
|
390
|
-
* @param {String} passedVariables.
|
|
431
|
+
* @param {Object} passedVariables.lastIndex - last index object
|
|
432
|
+
* @param {String} [passedVariables.lastIndex.index] - last index that has been set last time
|
|
433
|
+
* @param {String} passedVariables.lastAutomaticFile - last file that has been set automatically
|
|
434
|
+
* @param {String[]} passedVariables.newArguments - arguments passed from the terminal
|
|
391
435
|
* @param {String} passedVariables.arg - argument passed to this function that is also a file path
|
|
392
|
-
* @return {
|
|
393
|
-
* true if it needs to break,
|
|
394
|
-
* false if it needs to fallthrough the switch
|
|
395
|
-
* (See "case regexes.fileCheck.test(basename(arg)) && arg")
|
|
436
|
+
* @return {Promise<Promise|undefined>}
|
|
396
437
|
*/
|
|
397
438
|
const setFile = async ({
|
|
398
|
-
|
|
439
|
+
indexOfSetFile,
|
|
440
|
+
lastParam, lastIndex, lastAutomaticFile,
|
|
399
441
|
newArguments, arg
|
|
400
442
|
}) => {
|
|
401
|
-
|
|
443
|
+
/**
|
|
444
|
+
* Checks for the same basename as the path given inside process.argv
|
|
445
|
+
* @param {String} path - full file path to compare with another one
|
|
446
|
+
* @inner
|
|
447
|
+
* @private
|
|
448
|
+
* @memberof module:cli
|
|
449
|
+
* @return {Boolean} - whether or not it has found a similar file inside process.argv
|
|
450
|
+
*/
|
|
451
|
+
function checkForIdenticalName(path) {
|
|
452
|
+
const indexOfPath = newArguments.indexOf(path);
|
|
402
453
|
const pathUpToName = join(parse(path).dir, parse(path).name);
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
454
|
+
const noExtNewArguments = [...argvWithoutFileExts];
|
|
455
|
+
|
|
456
|
+
delete noExtNewArguments[indexOfPath]
|
|
457
|
+
return noExtNewArguments.includes(pathUpToName);
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Returns either a new Promise or attaches a .then Promise to an older one
|
|
461
|
+
* @param {Function} func function to run within a Promise
|
|
462
|
+
* @inner
|
|
463
|
+
* @private
|
|
464
|
+
* @memberof module:cli
|
|
465
|
+
* @return {(Promise|undefined)} - a new Promise that'll fulfill when the given function returns
|
|
466
|
+
*/
|
|
467
|
+
function createPromise(func) {
|
|
468
|
+
const lastSetFilePromise = setFilePromises[indexOfSetFile-1];
|
|
469
|
+
return (!lastSetFilePromise)
|
|
470
|
+
? func()
|
|
471
|
+
: lastSetFilePromise.then(() => func());
|
|
472
|
+
}
|
|
473
|
+
if (lastParam !== undefined && lastParam !== "input") return;
|
|
418
474
|
|
|
419
|
-
if (!global.fs) {
|
|
420
|
-
const fs = await import("node:fs");
|
|
421
|
-
global.fs = fs;
|
|
422
|
-
}
|
|
423
475
|
const fileMagicNumber = await get20BytesFromFile(arg);
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
&& !lastIndex?.index && !lastParam) {
|
|
438
|
-
Options.files(index, arg);
|
|
439
|
-
log(1, performance.now().toFixed(2), `Set midi file to "${arg}" at index ${index}`)
|
|
440
|
-
return true;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
for (const infos of indexesAndKeys) {
|
|
444
|
-
let index, setOfFiles;
|
|
445
|
-
if (infos) {
|
|
446
|
-
[index, setOfFiles] = infos;
|
|
447
|
-
} else continue;
|
|
448
|
-
|
|
449
|
-
if (index === indexesAndKeys.length-1
|
|
450
|
-
&& inputIndex !== index) {
|
|
451
|
-
if (checkForIdenticalNames(arg)
|
|
452
|
-
&& !lastIndex?.index && !lastParam) {
|
|
453
|
-
Options.files(indexesAndKeys.length, arg)
|
|
454
|
-
log(1, performance.now().toFixed(2), `Set midi file to "${arg}" at index ${indexesAndKeys.length}`)
|
|
455
|
-
return true;
|
|
456
|
-
}
|
|
457
|
-
Options.files(inputIndex, arg)
|
|
458
|
-
log(1, performance.now().toFixed(2), `Set midi file to "${arg}" at index ${inputIndex}`)
|
|
459
|
-
return true;
|
|
460
|
-
}
|
|
461
|
-
if (index !== inputIndex) continue;
|
|
462
|
-
|
|
463
|
-
if (checkForIdenticalNames(arg)
|
|
464
|
-
&& !lastIndex?.index && !lastParam) {
|
|
465
|
-
Options.files(indexesAndKeys.length, arg)
|
|
466
|
-
log(1, performance.now().toFixed(2), `Set midi file to "${arg}" at index ${indexesAndKeys.length}`)
|
|
467
|
-
return true;
|
|
468
|
-
}
|
|
469
|
-
Options.files(index, arg);
|
|
470
|
-
log(1, performance.now().toFixed(2), `Set midi file to "${arg}" at index ${index}`)
|
|
471
|
-
return true;
|
|
472
|
-
}
|
|
476
|
+
let typeOfFile;
|
|
477
|
+
switch (true) {
|
|
478
|
+
case fileMagicNumber.includes("MThd"):
|
|
479
|
+
typeOfFile = true;
|
|
480
|
+
break;
|
|
481
|
+
case fileMagicNumber.includes("sfbk"):
|
|
482
|
+
case fileMagicNumber.includes("DLS"):
|
|
483
|
+
typeOfFile = false;
|
|
484
|
+
break;
|
|
485
|
+
|
|
486
|
+
default:
|
|
487
|
+
// Incompatible file
|
|
488
|
+
return;
|
|
473
489
|
}
|
|
474
|
-
// -- End of MIDI files --
|
|
475
490
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
} else continue;
|
|
486
|
-
|
|
487
|
-
if (setOfFiles instanceof Set
|
|
488
|
-
&& doesSetHave(setOfFiles, arg, false)
|
|
489
|
-
&& !lastIndex?.index && !lastParam) {
|
|
490
|
-
Options.files(index, arg, true);
|
|
491
|
-
log(1, performance.now().toFixed(2), `Set soundfont file to "${arg}" at index ${index}`)
|
|
492
|
-
return true;
|
|
493
|
-
}
|
|
491
|
+
const inputIndex = Number(lastIndex?.index ?? 0);
|
|
492
|
+
const logMessages = {
|
|
493
|
+
getMessage(type, arg, index) {
|
|
494
|
+
return (type)
|
|
495
|
+
? `Set midi file to "${arg}" at index ${index}`
|
|
496
|
+
: `Set soundfont file to "${arg}" at index ${index}`;
|
|
497
|
+
},
|
|
498
|
+
getReplacedSoundfont(original, newOne, index) {
|
|
499
|
+
return `Replaced soundfont file from "${original}" to "${newOne}" at index ${index}`;
|
|
494
500
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
if (
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
}
|
|
509
|
-
Options.files(inputIndex, arg, true);
|
|
510
|
-
log(1, performance.now().toFixed(2), `Set soundfont file to "${arg}" at index ${inputIndex}`)
|
|
511
|
-
return true;
|
|
501
|
+
};
|
|
502
|
+
if (lastIndex?.index || lastParam) {
|
|
503
|
+
return createPromise(async () => {
|
|
504
|
+
let needsToBeReplaced = false;
|
|
505
|
+
|
|
506
|
+
// Replaces the last soundfont it can reach if it needs to
|
|
507
|
+
if (!typeOfFile) {
|
|
508
|
+
const setOfFiles = Options.all.files[inputIndex];
|
|
509
|
+
const fileMagicNumber = (setOfFiles instanceof Set)
|
|
510
|
+
? await get20BytesFromFile(setOfFiles.getIndex(0))
|
|
511
|
+
: [];
|
|
512
|
+
if (fileMagicNumber.includes("sfbk")
|
|
513
|
+
|| fileMagicNumber.includes("DLS")) needsToBeReplaced = true;
|
|
512
514
|
}
|
|
513
|
-
|
|
515
|
+
Options.files(inputIndex, arg, !typeOfFile, needsToBeReplaced)
|
|
516
|
+
log(1,
|
|
517
|
+
performance.now().toFixed(2),
|
|
518
|
+
logMessages.getMessage(typeOfFile, arg, inputIndex)
|
|
519
|
+
)
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// --- Automatic addition of files section ---
|
|
524
|
+
return createPromise(async () => {
|
|
525
|
+
/*
|
|
526
|
+
⏳ if one group inside Options.all
|
|
527
|
+
has the same basename as arg,
|
|
528
|
+
then it adds arg to that group
|
|
529
|
+
❌ Otherwise it runs the next check below it
|
|
530
|
+
(e.g. index 2 and he needs to add to that,
|
|
531
|
+
that's why it's seperated otherwise it creates
|
|
532
|
+
a new Set when it already exists)
|
|
533
|
+
*/
|
|
534
|
+
const pathUpToName = join(parse(arg).dir, parse(arg).name);
|
|
535
|
+
const foundIndex = Options.searchAddedFile(pathUpToName, typeOfFile);
|
|
536
|
+
if (typeof foundIndex === "number") {
|
|
537
|
+
Options.files(foundIndex, arg, !typeOfFile);
|
|
538
|
+
log(1,
|
|
539
|
+
performance.now().toFixed(2),
|
|
540
|
+
logMessages.getMessage(typeOfFile, arg, foundIndex)
|
|
541
|
+
)
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
if (argvWithoutFileExts instanceof Promise) argvWithoutFileExts = await argvWithoutFileExts;
|
|
545
|
+
// Creates new Sets for identical basename files
|
|
546
|
+
if (checkForIdenticalName(arg)) {
|
|
547
|
+
const amountOfGroups = Options.amountOfGroups;
|
|
548
|
+
Options.files(amountOfGroups, arg, !typeOfFile)
|
|
549
|
+
log(1,
|
|
550
|
+
performance.now().toFixed(2),
|
|
551
|
+
logMessages.getMessage(typeOfFile, arg, amountOfGroups)
|
|
552
|
+
)
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
// It just adds to the last Set it can reach
|
|
556
|
+
let lastKnownGroupIndex = Options.lastKnownGroupIndex ?? 0;
|
|
557
|
+
// or maybe to the last automatic group
|
|
558
|
+
// if a file has been added automatically last time
|
|
559
|
+
if (lastAutomaticFile) automaticFileCheck: {
|
|
560
|
+
const pathUpToName = join(parse(lastAutomaticFile).dir, parse(lastAutomaticFile).name);
|
|
561
|
+
const indexOfGroup = Options.searchAddedFile(pathUpToName);
|
|
562
|
+
if (typeof indexOfGroup !== "number") break automaticFileCheck;
|
|
514
563
|
|
|
515
|
-
if (
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
return true;
|
|
520
|
-
}
|
|
521
|
-
const fileMagicNumber = (setOfFiles instanceof Set)
|
|
522
|
-
? await get20BytesFromFile(setOfFiles.getIndex(0))
|
|
523
|
-
: [];
|
|
524
|
-
if (fileMagicNumber.includes("sfbk")
|
|
525
|
-
|| fileMagicNumber.includes("DLS")) {
|
|
526
|
-
log(1, performance.now().toFixed(2), `Replaced soundfont file from "${setOfFiles.getIndex(0)}" to "${arg}" at index ${index}`)
|
|
527
|
-
Options.files(index, arg, true, true);
|
|
528
|
-
return true;
|
|
564
|
+
if (Options.isAutomaticBasenameGroup(argvWithoutFileExts, indexOfGroup)) {
|
|
565
|
+
lastKnownGroupIndex++
|
|
566
|
+
} else {
|
|
567
|
+
lastKnownGroupIndex = indexOfGroup;
|
|
529
568
|
}
|
|
530
|
-
Options.files(index, arg, true);
|
|
531
|
-
log(1, performance.now().toFixed(2), `Set soundfont file to "${arg}" at index ${index}`)
|
|
532
|
-
return true;
|
|
533
569
|
}
|
|
534
|
-
|
|
535
|
-
|
|
570
|
+
Options.files(lastKnownGroupIndex, arg, !typeOfFile);
|
|
571
|
+
log(1,
|
|
572
|
+
performance.now().toFixed(2),
|
|
573
|
+
logMessages.getMessage(typeOfFile, arg, lastKnownGroupIndex)
|
|
574
|
+
)
|
|
575
|
+
});
|
|
576
|
+
// --- END of automatic addition of files section ---
|
|
536
577
|
}
|
|
537
578
|
/**
|
|
538
|
-
* Sets the Options.
|
|
579
|
+
* Sets the Options.loopAmount variable
|
|
539
580
|
* @param {String} arg - the loop amount
|
|
581
|
+
* @param {Object} lastIndex - last index object
|
|
582
|
+
* @param {String} [lastIndex.index] - last index that has been set last time
|
|
540
583
|
*/
|
|
541
584
|
const setLoop = (arg, lastIndex) => {
|
|
542
585
|
if (typeof Number(arg) === "number"
|
|
543
586
|
&& !regexes.infinity.test(arg)) {
|
|
544
|
-
Options.
|
|
587
|
+
Options.loopAmount(Number(lastIndex?.index), Number(arg));
|
|
545
588
|
log(1, performance.now().toFixed(2), `Set loop amount to ${Number(arg)} at ${lastIndex?.index} index`)
|
|
546
589
|
return;
|
|
547
590
|
}
|
|
@@ -555,6 +598,8 @@ const setLoop = (arg, lastIndex) => {
|
|
|
555
598
|
/**
|
|
556
599
|
* Sets the Options.loopStart variable
|
|
557
600
|
* @param {String} arg - the start of the loop in seconds or in HH:MM:SS:ms format
|
|
601
|
+
* @param {Object} lastIndex - last index object
|
|
602
|
+
* @param {String} [lastIndex.index] - last index that has been set last time
|
|
558
603
|
*/
|
|
559
604
|
const setLoopStart = (arg, lastIndex) => {
|
|
560
605
|
if (typeof Number(arg) === "number"
|
|
@@ -575,6 +620,8 @@ const setLoopStart = (arg, lastIndex) => {
|
|
|
575
620
|
/**
|
|
576
621
|
* Sets the Options.loopEnd variable
|
|
577
622
|
* @param {String} arg - the end of the loop in seconds or in HH:MM:SS:ms format
|
|
623
|
+
* @param {Object} lastIndex - last index object
|
|
624
|
+
* @param {String} [lastIndex.index] - last index that has been set last time
|
|
578
625
|
*/
|
|
579
626
|
const setLoopEnd = (arg, lastIndex) => {
|
|
580
627
|
if (typeof Number(arg) === "number"
|
|
@@ -595,6 +642,9 @@ const setLoopEnd = (arg, lastIndex) => {
|
|
|
595
642
|
/**
|
|
596
643
|
* Sets the Options.sampleRate variable
|
|
597
644
|
* @param {String} arg - the sample rate to set
|
|
645
|
+
* @param {Object} lastIndex - last index object
|
|
646
|
+
* @param {String} [lastIndex.index] - last index that has been set last time
|
|
647
|
+
* @param {String[]} newArguments - process.argv without 2 starting indexes
|
|
598
648
|
*/
|
|
599
649
|
const setSampleRate = (arg, lastIndex, newArguments) => {
|
|
600
650
|
if (typeof Number(arg) === "number" && !arg.startsWith("-")) {
|
|
@@ -612,7 +662,7 @@ const setSampleRate = (arg, lastIndex, newArguments) => {
|
|
|
612
662
|
}
|
|
613
663
|
/**
|
|
614
664
|
* Simply changes how the program should log
|
|
615
|
-
* @param {
|
|
665
|
+
* @param {String} arg - the level of how much it should log
|
|
616
666
|
*/
|
|
617
667
|
const setVerboseLevel = async (arg) => {
|
|
618
668
|
const isFromUser = arg !== undefined;
|
|
@@ -661,11 +711,12 @@ const setFormat = arg => {
|
|
|
661
711
|
process.exit(1);
|
|
662
712
|
}
|
|
663
713
|
/**
|
|
664
|
-
*
|
|
714
|
+
* Applies effects from the user's string passed through --effects
|
|
665
715
|
* @param {String} arg - the comma-separeted string to parse
|
|
666
|
-
* @
|
|
716
|
+
* @param {Object} lastIndex - last index object
|
|
717
|
+
* @param {String} [lastIndex.index] - last index that has been set last time
|
|
667
718
|
*/
|
|
668
|
-
const
|
|
719
|
+
const setEffects = (arg, lastIndex) => {
|
|
669
720
|
const regexListOfEffects = (
|
|
670
721
|
"allpass|band|bandpass|bandreject|bass|bend|biquad" +
|
|
671
722
|
"|chorus|channels|compand|contrast|dcshift|deemph|delay" +
|
|
@@ -707,14 +758,9 @@ const getEffects = (arg, lastIndex) => {
|
|
|
707
758
|
process.exit(1);
|
|
708
759
|
}
|
|
709
760
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
} else {
|
|
714
|
-
Options.effects(Number(lastIndex?.index), list);
|
|
715
|
-
}
|
|
716
|
-
log(1, performance.now().toFixed(2), `Set list of SoX effects as ${list} at ${lastIndex?.index} index`)
|
|
717
|
-
};
|
|
761
|
+
Options.effects(Number(lastIndex?.index), list);
|
|
762
|
+
log(1, performance.now().toFixed(2), `Set list of SoX effects as ${global.effects}`)
|
|
763
|
+
return;
|
|
718
764
|
}
|
|
719
765
|
console.error(`${normalRed}The string for SoX effects you passed is not usable${normal}`);
|
|
720
766
|
process.exit(1);
|
|
@@ -722,6 +768,8 @@ const getEffects = (arg, lastIndex) => {
|
|
|
722
768
|
/**
|
|
723
769
|
* Sets the Options.volume variable for the masterGain
|
|
724
770
|
* @param {String} arg - the volume in either percentage, decibels or decimals
|
|
771
|
+
* @param {Object} lastIndex - last index object
|
|
772
|
+
* @param {String} [lastIndex.index] - last index that has been set last time
|
|
725
773
|
*/
|
|
726
774
|
const setVolume = (arg, lastIndex) => {
|
|
727
775
|
if (regexes.areDecibels.test(arg)) {
|
|
@@ -746,41 +794,32 @@ const setVolume = (arg, lastIndex) => {
|
|
|
746
794
|
process.exit(1);
|
|
747
795
|
}
|
|
748
796
|
/**
|
|
749
|
-
*
|
|
797
|
+
* Sets the Options.reverb variable
|
|
750
798
|
* @param {String} arg - the volume in either percentage, decibels or decimals
|
|
751
|
-
* @param {Object} lastIndex -
|
|
752
|
-
* @
|
|
799
|
+
* @param {Object} lastIndex - last index object
|
|
800
|
+
* @param {String} [lastIndex.index] - last index that has been set last time
|
|
753
801
|
*/
|
|
754
|
-
const
|
|
755
|
-
let valueToSet;
|
|
802
|
+
const setReverb = (arg, lastIndex) => {
|
|
756
803
|
if (regexes.areDecibels.test(arg)) {
|
|
757
804
|
const dBNumber = Number(arg.match(regexes.decibelNumber)[1]);
|
|
758
|
-
|
|
805
|
+
Options.reverbVolume(Number(lastIndex?.index), dBNumber);
|
|
806
|
+
Options.effects(Number(lastIndex?.index), []);
|
|
807
|
+
log(1, performance.now().toFixed(2), `Set reverb volume to ${Options.all.reverbVolume.find(i => i === dBNumber)} and effects variable to ${lastIndex?.index}`)
|
|
759
808
|
return;
|
|
760
809
|
}
|
|
761
810
|
if (regexes.isPercentage.test(arg)) {
|
|
762
811
|
const percentage = Number(arg.match(regexes.percentageNumber)[1]);
|
|
763
812
|
const toDB = 10 * 10**(percentage/100);
|
|
764
|
-
|
|
813
|
+
Options.reverbVolume(Number(lastIndex?.index), toDB);
|
|
814
|
+
Options.effects(Number(lastIndex?.index), []);
|
|
815
|
+
log(1, performance.now().toFixed(2), `Set reverb volume to ${Options.all.reverbVolume.find(i => i === toDB)} and effects variable to ${lastIndex?.index}`)
|
|
765
816
|
return;
|
|
766
817
|
}
|
|
767
818
|
if (typeof Number(arg) === "number" && !arg.startsWith("-")) {
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
return isStdout => {
|
|
773
|
-
if (isStdout) {
|
|
774
|
-
Options.reverbVolumeStdout = valueToSet;
|
|
775
|
-
} else {
|
|
776
|
-
Options.reverbVolume(Number(lastIndex?.index), valueToSet)
|
|
777
|
-
}
|
|
778
|
-
Options.effects(Number(lastIndex?.index), [])
|
|
779
|
-
log(1,
|
|
780
|
-
performance.now().toFixed(2),
|
|
781
|
-
`Set reverb volume to ${valueToSet} at ${lastIndex?.index} index and effects variable to []`)
|
|
782
|
-
return;
|
|
783
|
-
};
|
|
819
|
+
Options.reverbVolume(Number(lastIndex?.index), Number(arg));
|
|
820
|
+
Options.effects(Number(lastIndex?.index), []);
|
|
821
|
+
log(1, performance.now().toFixed(2), `Set reverb volume to ${Options.all.reverbVolume.find(i => i === Number(arg))} and effects variable to ${lastIndex?.index}`)
|
|
822
|
+
return;
|
|
784
823
|
}
|
|
785
824
|
console.error(`${normalRed}Passed something that wasn't a valid number/dB/percentage${normal}`)
|
|
786
825
|
process.exit(1);
|
|
@@ -790,7 +829,7 @@ const getReverb = (arg, lastIndex) => {
|
|
|
790
829
|
* @param {String} arg - Path to the log file
|
|
791
830
|
*/
|
|
792
831
|
const setLogFilePath = arg => {
|
|
793
|
-
Options.logFilePath
|
|
832
|
+
Options.logFilePath = arg ?? "./spesso.log";
|
|
794
833
|
log(1, performance.now().toFixed(2), `Set log file path to ${arg ?? "./spesso.log"}`)
|
|
795
834
|
}
|
|
796
835
|
/**
|
|
@@ -816,8 +855,8 @@ const uninstall = async () => {
|
|
|
816
855
|
}
|
|
817
856
|
/**
|
|
818
857
|
* Shows the help text
|
|
819
|
-
* @param {Object} errorObject - an object containing additional info that should be printed alongside help
|
|
820
|
-
* @param {String} errorObject.errorText - error text that should be printed before helpText
|
|
858
|
+
* @param {Object} [errorObject=""] - an object containing additional info that should be printed alongside help
|
|
859
|
+
* @param {String} [errorObject.errorText] - error text that should be printed before helpText
|
|
821
860
|
*/
|
|
822
861
|
const help = async ({ errorText } = "") => {
|
|
823
862
|
const optionalIndex = `${normal}[${dimGray}n${normal}]`;
|
|
@@ -890,10 +929,10 @@ const help = async ({ errorText } = "") => {
|
|
|
890
929
|
`
|
|
891
930
|
if (process.env.PAGER) {
|
|
892
931
|
const { spawnSync } = await import("child_process");
|
|
893
|
-
const PAGERCommand = process.env.PAGER.split(" ").slice(0, 1),
|
|
932
|
+
const PAGERCommand = process.env.PAGER.split(" ").slice(0, 1)[0],
|
|
894
933
|
PAGERArguments = process.env.PAGER.split(" ").slice(1);
|
|
895
934
|
spawnSync(
|
|
896
|
-
|
|
935
|
+
PAGERCommand,
|
|
897
936
|
[...PAGERArguments],
|
|
898
937
|
{
|
|
899
938
|
stdio: ["pipe", "inherit", "inherit"],
|