spessasynth_lib 3.11.1 → 3.12.0
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/@types/midi_parser/rmidi_writer.d.ts +57 -2
- package/@types/soundfont/read/riff_chunk.d.ts +6 -0
- package/@types/utils/buffer_to_wav.d.ts +20 -0
- package/midi_parser/midi_loader.js +16 -7
- package/midi_parser/rmidi_writer.js +144 -69
- package/package.json +1 -1
- package/soundfont/read/riff_chunk.js +23 -1
- package/synthetizer/worklet_processor.min.js +6 -6
- package/utils/buffer_to_wav.js +8 -1
|
@@ -1,16 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* @typedef {Object} RMIDMetadata
|
|
3
|
+
* @property {string|undefined} name - the name of the file
|
|
4
|
+
* @property {string|undefined} engineer - the engineer who worked on the file
|
|
5
|
+
* @property {string|undefined} artist - the artist
|
|
6
|
+
* @property {string|undefined} album - the album
|
|
7
|
+
* @property {string|undefined} genre - the genre of the song
|
|
8
|
+
* @property {ArrayBuffer|undefined} picture - the image for the file (album cover)
|
|
9
|
+
* @property {string|undefined} comment - the coment of the file
|
|
10
|
+
* @property {string|undefined} creationDate - the creation date of the file
|
|
11
|
+
* @property {string|undefined} copyright - the copyright of the file
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Writes an RMIDI file
|
|
3
15
|
* @param soundfontBinary {Uint8Array}
|
|
4
16
|
* @param mid {MIDI}
|
|
5
17
|
* @param soundfont {SoundFont2}
|
|
6
18
|
* @param bankOffset {number} the bank offset for RMIDI
|
|
7
19
|
* @param encoding {string} the encoding of the RMIDI info chunk
|
|
20
|
+
* @param metadata {RMIDMetadata} the metadata of the file. Optional. If provided, the encoding is forced to utf-8/
|
|
8
21
|
* @returns {IndexedByteArray}
|
|
9
22
|
*/
|
|
10
|
-
export function writeRMIDI(soundfontBinary: Uint8Array, mid: MIDI, soundfont: SoundFont2, bankOffset?: number, encoding?: string): IndexedByteArray;
|
|
23
|
+
export function writeRMIDI(soundfontBinary: Uint8Array, mid: MIDI, soundfont: SoundFont2, bankOffset?: number, encoding?: string, metadata?: RMIDMetadata): IndexedByteArray;
|
|
11
24
|
export type RMIDINFOChunks = string;
|
|
12
25
|
export namespace RMIDINFOChunks {
|
|
13
26
|
let name: string;
|
|
27
|
+
let album: string;
|
|
28
|
+
let artist: string;
|
|
29
|
+
let genre: string;
|
|
30
|
+
let picture: string;
|
|
14
31
|
let copyright: string;
|
|
15
32
|
let creationDate: string;
|
|
16
33
|
let comment: string;
|
|
@@ -19,4 +36,42 @@ export namespace RMIDINFOChunks {
|
|
|
19
36
|
let encoding: string;
|
|
20
37
|
let bankOffset: string;
|
|
21
38
|
}
|
|
39
|
+
export type RMIDMetadata = {
|
|
40
|
+
/**
|
|
41
|
+
* - the name of the file
|
|
42
|
+
*/
|
|
43
|
+
name: string | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* - the engineer who worked on the file
|
|
46
|
+
*/
|
|
47
|
+
engineer: string | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* - the artist
|
|
50
|
+
*/
|
|
51
|
+
artist: string | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* - the album
|
|
54
|
+
*/
|
|
55
|
+
album: string | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* - the genre of the song
|
|
58
|
+
*/
|
|
59
|
+
genre: string | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* - the image for the file (album cover)
|
|
62
|
+
*/
|
|
63
|
+
picture: ArrayBuffer | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* - the coment of the file
|
|
66
|
+
*/
|
|
67
|
+
comment: string | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* - the creation date of the file
|
|
70
|
+
*/
|
|
71
|
+
creationDate: string | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* - the copyright of the file
|
|
74
|
+
*/
|
|
75
|
+
copyright: string | undefined;
|
|
76
|
+
};
|
|
22
77
|
import { IndexedByteArray } from '../utils/indexed_array.js';
|
|
@@ -11,6 +11,12 @@ export function readRIFFChunk(dataArray: IndexedByteArray, readData?: boolean, f
|
|
|
11
11
|
* @returns {IndexedByteArray}
|
|
12
12
|
*/
|
|
13
13
|
export function writeRIFFChunk(chunk: RiffChunk, prepend?: IndexedByteArray): IndexedByteArray;
|
|
14
|
+
/**
|
|
15
|
+
* @param header {string}
|
|
16
|
+
* @param data {Uint8Array}
|
|
17
|
+
* @returns {IndexedByteArray}
|
|
18
|
+
*/
|
|
19
|
+
export function writeRIFFOddSize(header: string, data: Uint8Array): IndexedByteArray;
|
|
14
20
|
/**
|
|
15
21
|
* riff_chunk.js
|
|
16
22
|
* reads a riff read and stores it as a class
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} WaveMetadata
|
|
3
|
+
* @property {string} title - the song's title
|
|
4
|
+
* @property {string} album - the song's album
|
|
5
|
+
* @property {string} genre - the song's genre
|
|
6
|
+
*/
|
|
1
7
|
/**
|
|
2
8
|
*
|
|
3
9
|
* @param audioBuffer {AudioBuffer}
|
|
@@ -6,3 +12,17 @@
|
|
|
6
12
|
* @returns {Blob}
|
|
7
13
|
*/
|
|
8
14
|
export function audioBufferToWav(audioBuffer: AudioBuffer, normalizeAudio?: boolean, channelOffset?: number): Blob;
|
|
15
|
+
export type WaveMetadata = {
|
|
16
|
+
/**
|
|
17
|
+
* - the song's title
|
|
18
|
+
*/
|
|
19
|
+
title: string;
|
|
20
|
+
/**
|
|
21
|
+
* - the song's album
|
|
22
|
+
*/
|
|
23
|
+
album: string;
|
|
24
|
+
/**
|
|
25
|
+
* - the song's genre
|
|
26
|
+
*/
|
|
27
|
+
genre: string;
|
|
28
|
+
};
|
|
@@ -47,6 +47,7 @@ class MIDI{
|
|
|
47
47
|
* @type {string}
|
|
48
48
|
*/
|
|
49
49
|
this.copyright = "";
|
|
50
|
+
let copyrightDetected = false;
|
|
50
51
|
|
|
51
52
|
/**
|
|
52
53
|
* The MIDI name
|
|
@@ -55,6 +56,7 @@ class MIDI{
|
|
|
55
56
|
this.midiName = "";
|
|
56
57
|
|
|
57
58
|
this.rawMidiName = new Uint8Array(0);
|
|
59
|
+
let nameDetected = false;
|
|
58
60
|
|
|
59
61
|
const initialString = readBytesAsString(binaryData, 4);
|
|
60
62
|
binaryData.currentIndex -= 4;
|
|
@@ -106,12 +108,14 @@ class MIDI{
|
|
|
106
108
|
}
|
|
107
109
|
if(this.RMIDInfo['ICOP'])
|
|
108
110
|
{
|
|
109
|
-
|
|
111
|
+
copyrightDetected = true;
|
|
112
|
+
this.copyright = readBytesAsString(this.RMIDInfo['ICOP'], this.RMIDInfo['ICOP'].length);
|
|
110
113
|
}
|
|
111
114
|
if(this.RMIDInfo['INAM'])
|
|
112
115
|
{
|
|
113
116
|
this.rawMidiName = this.RMIDInfo[RMIDINFOChunks.name];
|
|
114
|
-
this.midiName = readBytesAsString(this.rawMidiName,
|
|
117
|
+
this.midiName = readBytesAsString(this.rawMidiName, this.rawMidiName.length, undefined, false);
|
|
118
|
+
nameDetected = true;
|
|
115
119
|
}
|
|
116
120
|
this.bankOffset = 1; // defaults to 1
|
|
117
121
|
if(this.RMIDInfo[RMIDINFOChunks.bankOffset])
|
|
@@ -346,7 +350,10 @@ class MIDI{
|
|
|
346
350
|
break;
|
|
347
351
|
|
|
348
352
|
case messageTypes.copyright:
|
|
349
|
-
|
|
353
|
+
if(!copyrightDetected)
|
|
354
|
+
{
|
|
355
|
+
this.copyright += readBytesAsString(eventData, eventData.length, undefined, false) + "\n";
|
|
356
|
+
}
|
|
350
357
|
break;
|
|
351
358
|
|
|
352
359
|
case messageTypes.lyric:
|
|
@@ -432,8 +439,10 @@ class MIDI{
|
|
|
432
439
|
loopStart = this.firstNoteOn;
|
|
433
440
|
loopEnd = this.lastVoiceEventTick;
|
|
434
441
|
}
|
|
435
|
-
else
|
|
436
|
-
|
|
442
|
+
else
|
|
443
|
+
{
|
|
444
|
+
if (loopStart === null)
|
|
445
|
+
{
|
|
437
446
|
loopStart = this.firstNoteOn;
|
|
438
447
|
}
|
|
439
448
|
|
|
@@ -470,7 +479,7 @@ class MIDI{
|
|
|
470
479
|
this.loop = {start: loopStart, end: loopEnd};
|
|
471
480
|
|
|
472
481
|
// midi name
|
|
473
|
-
if(
|
|
482
|
+
if(!nameDetected)
|
|
474
483
|
{
|
|
475
484
|
if (this.tracks.length > 1)
|
|
476
485
|
{
|
|
@@ -479,7 +488,7 @@ class MIDI{
|
|
|
479
488
|
this.tracks[0].find(
|
|
480
489
|
message => message.messageStatusByte >= messageTypes.noteOn
|
|
481
490
|
&&
|
|
482
|
-
message.messageStatusByte < messageTypes.
|
|
491
|
+
message.messageStatusByte < messageTypes.polyPressure
|
|
483
492
|
) === undefined
|
|
484
493
|
)
|
|
485
494
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { combineArrays, IndexedByteArray } from '../utils/indexed_array.js'
|
|
2
2
|
import { writeMIDIFile } from './midi_writer.js'
|
|
3
|
-
import {
|
|
3
|
+
import { writeRIFFOddSize } from '../soundfont/read/riff_chunk.js'
|
|
4
4
|
import { getStringBytes } from '../utils/byte_functions/string.js'
|
|
5
5
|
import { messageTypes, midiControllers, MidiMessage } from './midi_message.js'
|
|
6
6
|
import { DEFAULT_PERCUSSION } from '../synthetizer/synthetizer.js'
|
|
@@ -8,14 +8,17 @@ import { getGsOn } from './midi_editor.js'
|
|
|
8
8
|
import { SpessaSynthGroup, SpessaSynthGroupEnd, SpessaSynthInfo } from '../utils/loggin.js'
|
|
9
9
|
import { consoleColors } from '../utils/other.js'
|
|
10
10
|
import { writeLittleEndian } from '../utils/byte_functions/little_endian.js'
|
|
11
|
-
|
|
12
11
|
/**
|
|
13
12
|
* @enum {string}
|
|
14
13
|
*/
|
|
15
14
|
export const RMIDINFOChunks = {
|
|
16
15
|
name: "INAM",
|
|
16
|
+
album: "IPRD",
|
|
17
|
+
artist: "IART",
|
|
18
|
+
genre: "IGNR",
|
|
19
|
+
picture: "IPIC",
|
|
17
20
|
copyright: "ICOP",
|
|
18
|
-
creationDate: "
|
|
21
|
+
creationDate: "ICRD",
|
|
19
22
|
comment: "ICMT",
|
|
20
23
|
engineer: "IENG",
|
|
21
24
|
software: "ISFT",
|
|
@@ -23,16 +26,33 @@ export const RMIDINFOChunks = {
|
|
|
23
26
|
bankOffset: "DBNK"
|
|
24
27
|
}
|
|
25
28
|
|
|
29
|
+
const FORCED_ENCODING = "utf-8";
|
|
30
|
+
const DEFAULT_COPYRIGHT = "Created by SpessaSynth";
|
|
31
|
+
|
|
26
32
|
/**
|
|
27
|
-
*
|
|
33
|
+
* @typedef {Object} RMIDMetadata
|
|
34
|
+
* @property {string|undefined} name - the name of the file
|
|
35
|
+
* @property {string|undefined} engineer - the engineer who worked on the file
|
|
36
|
+
* @property {string|undefined} artist - the artist
|
|
37
|
+
* @property {string|undefined} album - the album
|
|
38
|
+
* @property {string|undefined} genre - the genre of the song
|
|
39
|
+
* @property {ArrayBuffer|undefined} picture - the image for the file (album cover)
|
|
40
|
+
* @property {string|undefined} comment - the coment of the file
|
|
41
|
+
* @property {string|undefined} creationDate - the creation date of the file
|
|
42
|
+
* @property {string|undefined} copyright - the copyright of the file
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Writes an RMIDI file
|
|
28
47
|
* @param soundfontBinary {Uint8Array}
|
|
29
48
|
* @param mid {MIDI}
|
|
30
49
|
* @param soundfont {SoundFont2}
|
|
31
50
|
* @param bankOffset {number} the bank offset for RMIDI
|
|
32
51
|
* @param encoding {string} the encoding of the RMIDI info chunk
|
|
52
|
+
* @param metadata {RMIDMetadata} the metadata of the file. Optional. If provided, the encoding is forced to utf-8/
|
|
33
53
|
* @returns {IndexedByteArray}
|
|
34
54
|
*/
|
|
35
|
-
export function writeRMIDI(soundfontBinary, mid, soundfont, bankOffset = 0, encoding = "Shift_JIS")
|
|
55
|
+
export function writeRMIDI(soundfontBinary, mid, soundfont, bankOffset = 0, encoding = "Shift_JIS", metadata = {})
|
|
36
56
|
{
|
|
37
57
|
SpessaSynthGroup("%cWriting the RMIDI File...", consoleColors.info);
|
|
38
58
|
SpessaSynthInfo(`%cConfiguration: Bank offset: %c${bankOffset}%c, encoding: %c${encoding}`,
|
|
@@ -156,7 +176,7 @@ export function writeRMIDI(soundfontBinary, mid, soundfont, bankOffset = 0, enco
|
|
|
156
176
|
// check if this preset exists for program and bank
|
|
157
177
|
const realBank = lastBankChanges[chNum]?.messageData[1] - mid.bankOffset; // make sure to take the previous bank offset into account
|
|
158
178
|
const bank = drums[chNum] ? 128 : realBank;
|
|
159
|
-
if(
|
|
179
|
+
if(lastBankChanges[chNum] === undefined)
|
|
160
180
|
{
|
|
161
181
|
return;
|
|
162
182
|
}
|
|
@@ -259,81 +279,136 @@ export function writeRMIDI(soundfontBinary, mid, soundfont, bankOffset = 0, enco
|
|
|
259
279
|
const newMid = new IndexedByteArray(writeMIDIFile(mid).buffer);
|
|
260
280
|
|
|
261
281
|
// infodata for RMID
|
|
262
|
-
|
|
282
|
+
/**
|
|
283
|
+
* @type {Uint8Array[]}
|
|
284
|
+
*/
|
|
285
|
+
const infoContent = [getStringBytes("INFO")];
|
|
286
|
+
const encoder = new TextEncoder();
|
|
287
|
+
|
|
288
|
+
// name
|
|
289
|
+
if(metadata.name !== undefined)
|
|
290
|
+
{
|
|
291
|
+
|
|
292
|
+
infoContent.push(
|
|
293
|
+
writeRIFFOddSize(RMIDINFOChunks.name, encoder.encode(metadata.name))
|
|
294
|
+
);
|
|
295
|
+
encoding = FORCED_ENCODING;
|
|
296
|
+
}
|
|
297
|
+
else
|
|
298
|
+
{
|
|
299
|
+
infoContent.push(
|
|
300
|
+
writeRIFFOddSize(RMIDINFOChunks.name, mid.rawMidiName)
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
// creation date
|
|
304
|
+
if(metadata.creationDate !== undefined)
|
|
305
|
+
{
|
|
306
|
+
encoding = FORCED_ENCODING;
|
|
307
|
+
infoContent.push(
|
|
308
|
+
writeRIFFOddSize(RMIDINFOChunks.creationDate, encoder.encode(metadata.creationDate))
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
else
|
|
312
|
+
{
|
|
313
|
+
const today = new Date().toLocaleString(undefined, {
|
|
314
|
+
weekday: "long",
|
|
315
|
+
year: 'numeric',
|
|
316
|
+
month: "long",
|
|
317
|
+
day: "numeric",
|
|
318
|
+
hour: "numeric",
|
|
319
|
+
minute: "numeric"
|
|
320
|
+
});
|
|
321
|
+
infoContent.push(
|
|
322
|
+
writeRIFFOddSize(RMIDINFOChunks.creationDate, getStringBytes(today))
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
// comment
|
|
326
|
+
if(metadata.comment !== undefined)
|
|
327
|
+
{
|
|
328
|
+
encoding = FORCED_ENCODING;
|
|
329
|
+
infoContent.push(
|
|
330
|
+
writeRIFFOddSize(RMIDINFOChunks.comment, encoder.encode(metadata.comment))
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
// engineer
|
|
334
|
+
if(metadata.engineer !== undefined)
|
|
335
|
+
{
|
|
336
|
+
infoContent.push(
|
|
337
|
+
writeRIFFOddSize(RMIDINFOChunks.engineer, encoder.encode(metadata.engineer))
|
|
338
|
+
)
|
|
339
|
+
}
|
|
340
|
+
// album
|
|
341
|
+
if(metadata.album !== undefined)
|
|
342
|
+
{
|
|
343
|
+
encoding = FORCED_ENCODING;
|
|
344
|
+
infoContent.push(
|
|
345
|
+
writeRIFFOddSize(RMIDINFOChunks.album, encoder.encode(metadata.album))
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
// artist
|
|
349
|
+
if(metadata.artist !== undefined)
|
|
350
|
+
{
|
|
351
|
+
encoding = FORCED_ENCODING;
|
|
352
|
+
infoContent.push(
|
|
353
|
+
writeRIFFOddSize(RMIDINFOChunks.artist, encoder.encode(metadata.artist))
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
// genre
|
|
357
|
+
if(metadata.genre !== undefined)
|
|
358
|
+
{
|
|
359
|
+
encoding = FORCED_ENCODING;
|
|
360
|
+
infoContent.push(
|
|
361
|
+
writeRIFFOddSize(RMIDINFOChunks.genre, encoder.encode(metadata.genre))
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
// picture
|
|
365
|
+
if(metadata.picture !== undefined)
|
|
366
|
+
{
|
|
367
|
+
infoContent.push(
|
|
368
|
+
writeRIFFOddSize(RMIDINFOChunks.picture, new Uint8Array(metadata.picture))
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
// copyright
|
|
372
|
+
if(metadata.copyright !== undefined)
|
|
373
|
+
{
|
|
374
|
+
encoding = FORCED_ENCODING;
|
|
375
|
+
infoContent.push(
|
|
376
|
+
writeRIFFOddSize(RMIDINFOChunks.copyright, encoder.encode(metadata.copyright))
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
else
|
|
380
|
+
{
|
|
381
|
+
// use midi copyright if possible
|
|
382
|
+
const copyright = mid.copyright.length > 0 ? mid.copyright : DEFAULT_COPYRIGHT;
|
|
383
|
+
infoContent.push(
|
|
384
|
+
writeRIFFOddSize(RMIDINFOChunks.copyright, getStringBytes(copyright))
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// bank offset
|
|
263
389
|
const DBNK = new IndexedByteArray(2);
|
|
264
390
|
writeLittleEndian(DBNK, bankOffset, 2);
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
new RiffChunk(
|
|
270
|
-
RMIDINFOChunks.copyright,
|
|
271
|
-
ICOP.length,
|
|
272
|
-
ICOP
|
|
273
|
-
),
|
|
274
|
-
new IndexedByteArray([73, 78, 70, 79]) // "INFO"
|
|
275
|
-
),
|
|
276
|
-
// inam: name
|
|
277
|
-
writeRIFFChunk(
|
|
278
|
-
new RiffChunk(
|
|
279
|
-
RMIDINFOChunks.name,
|
|
280
|
-
mid.rawMidiName.length,
|
|
281
|
-
new IndexedByteArray(mid.rawMidiName.buffer)
|
|
282
|
-
),
|
|
283
|
-
),
|
|
284
|
-
// icrd: creation date
|
|
285
|
-
writeRIFFChunk(
|
|
286
|
-
new RiffChunk(
|
|
287
|
-
RMIDINFOChunks.creationDate,
|
|
288
|
-
today.length,
|
|
289
|
-
getStringBytes(today)
|
|
290
|
-
)
|
|
291
|
-
),
|
|
292
|
-
// isft: software used
|
|
293
|
-
writeRIFFChunk(
|
|
294
|
-
new RiffChunk(
|
|
295
|
-
RMIDINFOChunks.software,
|
|
296
|
-
11,
|
|
297
|
-
getStringBytes("SpessaSynth"),
|
|
298
|
-
)
|
|
299
|
-
),
|
|
300
|
-
// ienc: encoding for the info chunk
|
|
301
|
-
writeRIFFChunk(
|
|
302
|
-
new RiffChunk(
|
|
303
|
-
RMIDINFOChunks.encoding,
|
|
304
|
-
encoding.length,
|
|
305
|
-
getStringBytes(encoding)
|
|
306
|
-
)
|
|
307
|
-
),
|
|
308
|
-
// dbnk: bank offset
|
|
309
|
-
writeRIFFChunk(
|
|
310
|
-
new RiffChunk(
|
|
311
|
-
RMIDINFOChunks.bankOffset,
|
|
312
|
-
2,
|
|
313
|
-
DBNK
|
|
314
|
-
)
|
|
315
|
-
)
|
|
316
|
-
]);
|
|
391
|
+
infoContent.push(writeRIFFOddSize(RMIDINFOChunks.bankOffset, DBNK));
|
|
392
|
+
// encoding
|
|
393
|
+
infoContent.push(writeRIFFOddSize(RMIDINFOChunks.encoding, getStringBytes(encoding)));
|
|
394
|
+
const infodata = combineArrays(infoContent);
|
|
317
395
|
|
|
318
396
|
const rmiddata = combineArrays([
|
|
319
|
-
|
|
320
|
-
|
|
397
|
+
getStringBytes("RMID"),
|
|
398
|
+
writeRIFFOddSize(
|
|
321
399
|
"data",
|
|
322
|
-
newMid.length, // "data", size, midi binary
|
|
323
400
|
newMid
|
|
324
|
-
)
|
|
325
|
-
|
|
401
|
+
),
|
|
402
|
+
writeRIFFOddSize(
|
|
326
403
|
"LIST",
|
|
327
|
-
infodata.length,
|
|
328
404
|
infodata
|
|
329
|
-
)
|
|
405
|
+
),
|
|
330
406
|
soundfontBinary
|
|
331
407
|
]);
|
|
332
408
|
SpessaSynthInfo("%cFinished!", consoleColors.info)
|
|
333
409
|
SpessaSynthGroupEnd();
|
|
334
|
-
return
|
|
410
|
+
return writeRIFFOddSize(
|
|
335
411
|
"RIFF",
|
|
336
|
-
rmiddata.length,
|
|
337
412
|
rmiddata
|
|
338
|
-
)
|
|
413
|
+
);
|
|
339
414
|
}
|
package/package.json
CHANGED
|
@@ -47,7 +47,10 @@ export function readRIFFChunk(dataArray, readData = true, forceShift = false) {
|
|
|
47
47
|
|
|
48
48
|
if(size % 2 !== 0)
|
|
49
49
|
{
|
|
50
|
-
dataArray.currentIndex
|
|
50
|
+
if(dataArray[dataArray.currentIndex] === 0)
|
|
51
|
+
{
|
|
52
|
+
dataArray.currentIndex++;
|
|
53
|
+
}
|
|
51
54
|
}
|
|
52
55
|
|
|
53
56
|
return new RiffChunk(header, size, chunkData)
|
|
@@ -83,4 +86,23 @@ export function writeRIFFChunk(chunk, prepend = undefined)
|
|
|
83
86
|
// write data
|
|
84
87
|
array.set(chunk.chunkData, array.currentIndex);
|
|
85
88
|
return array;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @param header {string}
|
|
93
|
+
* @param data {Uint8Array}
|
|
94
|
+
* @returns {IndexedByteArray}
|
|
95
|
+
*/
|
|
96
|
+
export function writeRIFFOddSize(header, data)
|
|
97
|
+
{
|
|
98
|
+
let finalSize = 8 + data.length;
|
|
99
|
+
if(finalSize % 2 !== 0)
|
|
100
|
+
{
|
|
101
|
+
finalSize++;
|
|
102
|
+
}
|
|
103
|
+
const outArray = new IndexedByteArray(finalSize);
|
|
104
|
+
writeStringAsBytes(outArray, header);
|
|
105
|
+
writeDword(outArray, data.length);
|
|
106
|
+
outArray.set(data, 8);
|
|
107
|
+
return outArray;
|
|
86
108
|
}
|