8000 The Global Scope Update 2.0: The End · spessasus/SpessaSynth@b7f9e38 · GitHub
[go: up one dir, main page]

Skip to content

Commit b7f9e38

Browse files
committed
The Global Scope Update 2.0: The End
completed the sequencer added audio exporting
1 parent 6113855 commit b7f9e38

37 files changed

+1139
-920
lines changed

index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ <h1 id="title" translate-path='locale.demoTitleMessage'>SpessaSynth: Online Demo
3434
<label id="file_upload" for='midi_file_input' translate-path='locale.midiUploadButton'>Upload your MIDI files</label>
3535
<input type="file" accept=".mid" id="midi_file_input" multiple><br/>
3636

37+
<label for='export_file_input' translate-path='locale.midiRenderButton'>Export audio</label>
38+
<input type='file' accept='.mid' id='export_file_input'>
39+
3740
<label id="sf_upload"> <p translate-path='locale.demoSoundfontUploadButton'>Upload the soundfont</p>
3841
<input type="file" accept=".sf2,.sf3" id="sf_file_input"><br/>
3942
</label>

src/spessasynth_lib/midi_handler/midi_handler.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Synthetizer } from '../synthetizer/synthetizer.js'
22
import { consoleColors } from '../utils/other.js';
3+
import { SpessaSynthInfo, SpessaSynthWarn } from '../utils/loggin.js'
34

45
/**
56
* midi_handler.js
@@ -29,10 +30,10 @@ export class MIDIDeviceHandler
2930
const response = await navigator.requestMIDIAccess({ sysex: true, software: true });
3031
this.inputs = response.inputs;
3132
this.outputs = response.outputs;
32-
console.log("%cMIDI handler created!", consoleColors.recognized);
33+
SpessaSynthInfo("%cMIDI handler created!", consoleColors.recognized);
3334
}
3435
catch (e) {
35-
console.warn(`Could not get MIDI Devices:`, e);
36+
SpessaSynthWarn(`Could not get MIDI Devices:`, e);
3637
this.inputs = [];
3738
this.outputs = [];
3839
}
@@ -53,7 +54,7 @@ export class MIDIDeviceHandler
5354
{
5455
this.selectedOutput = output;
5556
seq.connectMidiOutput(output);
56-
console.log(`%cPlaying MIDI to %c${output.name}`,
57+
SpessaSynthInfo(`%cPlaying MIDI to %c${output.name}`,
5758
consoleColors.info,
5859
consoleColors.recognized);
5960
}
@@ -66,7 +67,7 @@ export class MIDIDeviceHandler
6667
{
6768
this.selectedOutput = NO_INPUT;
6869
seq.connectMidiOutput(undefined);
69-
console.log("%cDisconnected from MIDI out.",
70+
SpessaSynthInfo("%cDisconnected from MIDI out.",
7071
consoleColors.info);
7172
}
7273

@@ -81,7 +82,7 @@ export class MIDIDeviceHandler
8182
input.onmidimessage = event => {
8283
synth.sendMessage(event.data);
8384
}
84-
console.log(`%cListening for messages on %c${input.name}`,
85+
SpessaSynthInfo(`%cListening for messages on %c${input.name}`,
8586
consoleColors.info,
8687
consoleColors.recognized);
8788
}
@@ -93,7 +94,7 @@ export class MIDIDeviceHandler
9394
{
9495
this.selectedInput = NO_INPUT;
9596
input.onmidimessage = undefined;
96-
console.log(`%cDisconnected from %c${input.name}`,
97+
SpessaSynthInfo(`%cDisconnected from %c${input.name}`,
9798
consoleColors.info,
9899
consoleColors.recognized);
99100
}

src/spessasynth_lib/midi_handler/web_midi_link.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Synthetizer } from '../synthetizer/synthetizer.js'
22
import { consoleColors } from '../utils/other.js'
3+
import { SpessaSynthInfo } from '../utils/loggin.js'
34

45
/**
56
* web_midi_link.js
@@ -35,6 +36,6 @@ export class WebMidiLinkHandler
3536
synth.sendMessage(midiData);
3637
});
3738

38-
console.log("%cWeb MIDI Link handler created!", consoleColors.recognized);
39+
SpessaSynthInfo("%cWeb MIDI Link handler created!", consoleColors.recognized);
3940
}
4041
}

src/spessasynth_lib/midi_parser/midi_loader.js

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
readVariableLengthQuantity
88
} from "../utils/byte_functions.js";
99
import { arrayToHexString, consoleColors, formatTitle } from '../utils/other.js'
10+
import { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd, SpessaSynthInfo } from '../utils/loggin.js'
1011

1112
/**
1213
* midi_loader.js
@@ -19,7 +20,7 @@ export class MIDI{
1920
* @param fileName {string} optional, replaces the decoded title if empty
2021
*/
2122
constructor(arrayBuffer, fileName="") {
22-
console.groupCollapsed(`%cParsing MIDI File...`, consoleColors.info);
23+
SpessaSynthGroupCollapsed(`%cParsing MIDI File...`, consoleColors.info);
2324

2425
const fileByteArray = new ShiftableByteArray(arrayBuffer);
2526
const headerChunk = this.readMIDIChunk(fileByteArray);
@@ -233,14 +234,14 @@ export class MIDI{
233234
{
234235
const decoded = decoder.decode(messageData.slice(7, messageData.length - 3)) + "\n";
235236
this.copyright += decoded;
236-
console.info(`%cDecoded Roland SC message! %c${decoded}`,
237+
SpessaSynthInfo(`%cDecoded Roland SC message! %c${decoded}`,
237238
consoleColors.recognized,
238239
consoleColors.value)
239240
}
240241
}
241242
}
242243
this.tracks.push(track);
243-
console.info(`%cParsed %c${this.tracks.length}%c / %c${this.tracksAmount}`,
244+
SpessaSynthInfo(`%cParsed %c${this.tracks.length}%c / %c${this.tracksAmount}`,
244245
consoleColors.info,
245246
consoleColors.value,
246247
consoleColors.info,
@@ -260,10 +261,10 @@ export class MIDI{
260261
}
261262
this.firstNoteOn = Math.min(...firstNoteOns);
262263

263-
console.info(`%cMIDI file parsed. Total tick time: %c${this.lastVoiceEventTick}`,
264+
SpessaSynthInfo(`%cMIDI file parsed. Total tick time: %c${this.lastVoiceEventTick}`,
264265
consoleColors.info,
265266
consoleColors.recognized);
266-
console.groupEnd();
267+
SpessaSynthGroupEnd();
267268

268269
if(loopStart !== null && loopEnd === null)
269270
{
@@ -327,6 +328,12 @@ export class MIDI{
327328

328329
// reverse the tempo changes
329330
this.tempoChanges.reverse();
331+
332+
/**
333+
* The total playback time, in seconds
334+
* @type {number}
335+
*/
336+
this.duration = this._ticksToSeconds(this.lastVoiceEventTick);
330337
}
331338

332339
/**
@@ -347,4 +354,24 @@ export class MIDI{
347354
fileByteArray.currentIndex += chunk.size;
348355
return chunk;
349356
}
357+
358+
359+
/**
360+
* Coverts ticks to time in seconds
361+
* @param ticks {number}
362+
* @returns {number}
363+
* @private
364+
*/
365+
_ticksToSeconds(ticks)
366+
{
367+
if (ticks <= 0) {
368+
return 0;
369+
}
370+
371+
// find the last tempo change that has occured
372+
let tempo = this.tempoChanges.find(v => v.ticks < ticks);
373+
374+
let timeSinceLastTempo = ticks - tempo.ticks;
375+
return this._ticksToSeconds(ticks - timeSinceLastTempo) + (timeSinceLastTempo * 60) / (tempo.tempo * this.timeDivision);
376+
}
350377
}
Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,23 @@
11
## This is the sequencer's folder.
2-
The code here is responsible for playing back the parsed MIDI sequence with the synthesizer.
2+
The code here is responsible for playing back the parsed MIDI sequence with the synthesizer.
3+
4+
### Message protocol:
5+
#### Message structure
6+
```js
7+
const message = {
8+
messageType: number, // WorkletSequencerMessageType
9+
messageData: any // any
10+
}
11+
```
12+
13+
#### To worklet
14+
Sequencer uses `Synthetizer`'s `post` method to post a message with `messageData` set to `workletMessageType.sequencerSpecific`.
15+
The `messageData` is set to the sequencer's message.
16+
17+
#### From worklet
18+
`WorkletSequencer` uses `SpessaSynthProcessor`'s post to send a message with `messageData` set to `returnMessageType.sequencerSpecific`.
19+
The `messageData` is set to the sequencer's return message.
20+
21+
22+
### Process tick
23+
`processTick` is called every time the `process` method is called via `SpessaSynthProcessor.processTickCallback`.

0 commit comments

Comments
 (0)
0