spessasynth_lib 3.11.2 → 3.12.2
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 +148 -69
- package/package.json +1 -1
- package/soundfont/read/riff_chunk.js +19 -0
- 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
|
+
|
|
32
|
+
/**
|
|
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
|
+
|
|
26
45
|
/**
|
|
27
|
-
*
|
|
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}`,
|
|
@@ -40,6 +60,7 @@ export function writeRMIDI(soundfontBinary, mid, soundfont, bankOffset = 0, enco
|
|
|
40
60
|
consoleColors.value,
|
|
41
61
|
consoleColors.info,
|
|
42
62
|
consoleColors.value);
|
|
63
|
+
SpessaSynthInfo("metadata", metadata);
|
|
43
64
|
// add offset to bank. See wiki About-RMIDI
|
|
44
65
|
// also fix presets that don't exists since midiplayer6 doesn't seem to default to 0 when nonextistent...
|
|
45
66
|
let system = "gm";
|
|
@@ -156,7 +177,7 @@ export function writeRMIDI(soundfontBinary, mid, soundfont, bankOffset = 0, enco
|
|
|
156
177
|
// check if this preset exists for program and bank
|
|
157
178
|
const realBank = lastBankChanges[chNum]?.messageData[1] - mid.bankOffset; // make sure to take the previous bank offset into account
|
|
158
179
|
const bank = drums[chNum] ? 128 : realBank;
|
|
159
|
-
if(
|
|
180
|
+
if(lastBankChanges[chNum] === undefined)
|
|
160
181
|
{
|
|
161
182
|
return;
|
|
162
183
|
}
|
|
@@ -259,81 +280,139 @@ export function writeRMIDI(soundfontBinary, mid, soundfont, bankOffset = 0, enco
|
|
|
259
280
|
const newMid = new IndexedByteArray(writeMIDIFile(mid).buffer);
|
|
260
281
|
|
|
261
282
|
// infodata for RMID
|
|
262
|
-
|
|
283
|
+
/**
|
|
284
|
+
* @type {Uint8Array[]}
|
|
285
|
+
*/
|
|
286
|
+
const infoContent = [getStringBytes("INFO")];
|
|
287
|
+
const encoder = new TextEncoder();
|
|
288
|
+
// software
|
|
289
|
+
infoContent.push(
|
|
290
|
+
writeRIFFOddSize(RMIDINFOChunks.software, encoder.encode("SpessaSynth"))
|
|
291
|
+
);
|
|
292
|
+
// name
|
|
293
|
+
if(metadata.name !== undefined)
|
|
294
|
+
{
|
|
295
|
+
|
|
296
|
+
infoContent.push(
|
|
297
|
+
writeRIFFOddSize(RMIDINFOChunks.name, encoder.encode(metadata.name))
|
|
298
|
+
);
|
|
299
|
+
encoding = FORCED_ENCODING;
|
|
300
|
+
}
|
|
301
|
+
else
|
|
302
|
+
{
|
|
303
|
+
infoContent.push(
|
|
304
|
+
writeRIFFOddSize(RMIDINFOChunks.name, mid.rawMidiName)
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
// creation date
|
|
308
|
+
if(metadata.creationDate !== undefined)
|
|
309
|
+
{
|
|
310
|
+
encoding = FORCED_ENCODING;
|
|
311
|
+
infoContent.push(
|
|
312
|
+
writeRIFFOddSize(RMIDINFOChunks.creationDate, encoder.encode(metadata.creationDate))
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
else
|
|
316
|
+
{
|
|
317
|
+
const today = new Date().toLocaleString(undefined, {
|
|
318
|
+
weekday: "long",
|
|
319
|
+
year: 'numeric',
|
|
320
|
+
month: "long",
|
|
321
|
+
day: "numeric",
|
|
322
|
+
hour: "numeric",
|
|
323
|
+
minute: "numeric"
|
|
324
|
+
});
|
|
325
|
+
infoContent.push(
|
|
326
|
+
writeRIFFOddSize(RMIDINFOChunks.creationDate, getStringBytes(today))
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
// comment
|
|
330
|
+
if(metadata.comment !== undefined)
|
|
331
|
+
{
|
|
332
|
+
encoding = FORCED_ENCODING;
|
|
333
|
+
infoContent.push(
|
|
334
|
+
writeRIFFOddSize(RMIDINFOChunks.comment, encoder.encode(metadata.comment))
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
// engineer
|
|
338
|
+
if(metadata.engineer !== undefined)
|
|
339
|
+
{
|
|
340
|
+
infoContent.push(
|
|
341
|
+
writeRIFFOddSize(RMIDINFOChunks.engineer, encoder.encode(metadata.engineer))
|
|
342
|
+
)
|
|
343
|
+
}
|
|
344
|
+
// album
|
|
345
|
+
if(metadata.album !== undefined)
|
|
346
|
+
{
|
|
347
|
+
encoding = FORCED_ENCODING;
|
|
348
|
+
infoContent.push(
|
|
349
|
+
writeRIFFOddSize(RMIDINFOChunks.album, encoder.encode(metadata.album))
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
// artist
|
|
353
|
+
if(metadata.artist !== undefined)
|
|
354
|
+
{
|
|
355
|
+
encoding = FORCED_ENCODING;
|
|
356
|
+
infoContent.push(
|
|
357
|
+
writeRIFFOddSize(RMIDINFOChunks.artist, encoder.encode(metadata.artist))
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
// genre
|
|
361
|
+
if(metadata.genre !== undefined)
|
|
362
|
+
{
|
|
363
|
+
encoding = FORCED_ENCODING;
|
|
364
|
+
infoContent.push(
|
|
365
|
+
writeRIFFOddSize(RMIDINFOChunks.genre, encoder.encode(metadata.genre))
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
// picture
|
|
369
|
+
if(metadata.picture !== undefined)
|
|
370
|
+
{
|
|
371
|
+
infoContent.push(
|
|
372
|
+
writeRIFFOddSize(RMIDINFOChunks.picture, new Uint8Array(metadata.picture))
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
// copyright
|
|
376
|
+
if(metadata.copyright !== undefined)
|
|
377
|
+
{
|
|
378
|
+
encoding = FORCED_ENCODING;
|
|
379
|
+
infoContent.push(
|
|
380
|
+
writeRIFFOddSize(RMIDINFOChunks.copyright, encoder.encode(metadata.copyright))
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
else
|
|
384
|
+
{
|
|
385
|
+
// use midi copyright if possible
|
|
386
|
+
const copyright = mid.copyright.length > 0 ? mid.copyright : DEFAULT_COPYRIGHT;
|
|
387
|
+
infoContent.push(
|
|
388
|
+
writeRIFFOddSize(RMIDINFOChunks.copyright, getStringBytes(copyright))
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// bank offset
|
|
263
393
|
const DBNK = new IndexedByteArray(2);
|
|
264
394
|
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
|
-
]);
|
|
395
|
+
infoContent.push(writeRIFFOddSize(RMIDINFOChunks.bankOffset, DBNK));
|
|
396
|
+
// encoding
|
|
397
|
+
infoContent.push(writeRIFFOddSize(RMIDINFOChunks.encoding, getStringBytes(encoding)));
|
|
398
|
+
const infodata = combineArrays(infoContent);
|
|
317
399
|
|
|
318
400
|
const rmiddata = combineArrays([
|
|
319
|
-
|
|
320
|
-
|
|
401
|
+
getStringBytes("RMID"),
|
|
402
|
+
writeRIFFOddSize(
|
|
321
403
|
"data",
|
|
322
|
-
newMid.length, // "data", size, midi binary
|
|
323
404
|
newMid
|
|
324
|
-
)
|
|
325
|
-
|
|
405
|
+
),
|
|
406
|
+
writeRIFFOddSize(
|
|
326
407
|
"LIST",
|
|
327
|
-
infodata.length,
|
|
328
408
|
infodata
|
|
329
|
-
)
|
|
409
|
+
),
|
|
330
410
|
soundfontBinary
|
|
331
411
|
]);
|
|
332
412
|
SpessaSynthInfo("%cFinished!", consoleColors.info)
|
|
333
413
|
SpessaSynthGroupEnd();
|
|
334
|
-
return
|
|
414
|
+
return writeRIFFOddSize(
|
|
335
415
|
"RIFF",
|
|
336
|
-
rmiddata.length,
|
|
337
416
|
rmiddata
|
|
338
|
-
)
|
|
417
|
+
);
|
|
339
418
|
}
|
package/package.json
CHANGED
|
@@ -86,4 +86,23 @@ export function writeRIFFChunk(chunk, prepend = undefined)
|
|
|
86
86
|
// write data
|
|
87
87
|
array.set(chunk.chunkData, array.currentIndex);
|
|
88
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;
|
|
89
108
|
}
|