spessasynth_lib 3.9.21 → 3.9.22
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/externals/libvorbis/OggVorbisEncoder.min.d.ts +3 -0
- package/@types/sequencer/sequencer.d.ts +23 -13
- package/@types/sequencer/worklet_sequencer/sequencer_message.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +1 -1
- package/sequencer/sequencer.js +44 -1
- package/sequencer/worklet_sequencer/events.js +5 -0
- package/sequencer/worklet_sequencer/sequencer_message.js +3 -1
- package/sequencer/worklet_sequencer/song_control.js +0 -1
- package/sequencer/worklet_sequencer/worklet_sequencer.js +23 -2
- package/synthetizer/worklet_processor.min.js +2 -2
- package/synthetizer/worklet_processor.min.js.map +0 -7
|
@@ -1,22 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* sequencer.js
|
|
3
|
-
* purpose: plays back the midi file decoded by midi_loader.js, including support for multi-channel midis (adding channels when more than 1 midi port is detected)
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* @typedef MidFile {Object}
|
|
7
|
-
* @property {ArrayBuffer} binary - the binary data of the file.
|
|
8
|
-
* @property {string|undefined} altName - the alternative name for the file
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* @typedef {MIDI|MidFile} MIDIFile
|
|
12
|
-
*/
|
|
13
1
|
export class Sequencer {
|
|
14
2
|
/**
|
|
15
3
|
* Creates a new Midi sequencer for playing back MIDI files
|
|
16
4
|
* @param midiBinaries {MIDIFile[]} List of the buffers of the MIDI files
|
|
17
5
|
* @param synth {Synthetizer} synth to send events to
|
|
6
|
+
* @param options {SequencerOptions} the sequencer's options
|
|
18
7
|
*/
|
|
19
|
-
constructor(midiBinaries: MIDIFile[], synth: Synthetizer);
|
|
8
|
+
constructor(midiBinaries: MIDIFile[], synth: Synthetizer, options?: SequencerOptions);
|
|
20
9
|
ignoreEvents: boolean;
|
|
21
10
|
synth: Synthetizer;
|
|
22
11
|
highResTimeOffset: number;
|
|
@@ -47,6 +36,21 @@ export class Sequencer {
|
|
|
47
36
|
* @type {number}
|
|
48
37
|
*/
|
|
49
38
|
duration: number;
|
|
39
|
+
/**
|
|
40
|
+
* @type {boolean}
|
|
41
|
+
* @private
|
|
42
|
+
*/
|
|
43
|
+
private _skipToFirstNoteOn;
|
|
44
|
+
/**
|
|
45
|
+
* Indicates if the sequencer should skip to first note on
|
|
46
|
+
* @param val {boolean}
|
|
47
|
+
*/
|
|
48
|
+
set skipToFirstNoteOn(val: boolean);
|
|
49
|
+
/**
|
|
50
|
+
* Indicates if the sequencer should skip to first note on
|
|
51
|
+
* @return {boolean}
|
|
52
|
+
*/
|
|
53
|
+
get skipToFirstNoteOn(): boolean;
|
|
50
54
|
resetMIDIOut(): void;
|
|
51
55
|
set loop(value: boolean);
|
|
52
56
|
get loop(): boolean;
|
|
@@ -186,6 +190,12 @@ export type MidFile = {
|
|
|
186
190
|
altName: string | undefined;
|
|
187
191
|
};
|
|
188
192
|
export type MIDIFile = MIDI | MidFile;
|
|
193
|
+
export type SequencerOptions = {
|
|
194
|
+
/**
|
|
195
|
+
* - if true, the sequencer will skip to the first note
|
|
196
|
+
*/
|
|
197
|
+
skipToFirstNoteOn: boolean;
|
|
198
|
+
};
|
|
189
199
|
import { Synthetizer } from '../synthetizer/synthetizer.js';
|
|
190
200
|
import { MidiData } from '../midi_parser/midi_data.js';
|
|
191
201
|
import { MIDI } from '../midi_parser/midi_loader.js';
|
|
@@ -13,6 +13,7 @@ export namespace WorkletSequencerMessageType {
|
|
|
13
13
|
let setLoop: number;
|
|
14
14
|
let changeSong: number;
|
|
15
15
|
let getMIDI: number;
|
|
16
|
+
let setSkipToFirstNote: number;
|
|
16
17
|
}
|
|
17
18
|
export type WorkletSequencerReturnMessageType = number;
|
|
18
19
|
export namespace WorkletSequencerReturnMessageType {
|
package/index.js
CHANGED
|
@@ -26,6 +26,7 @@ import { NON_CC_INDEX_OFFSET } from './synthetizer/worklet_system/worklet_utilit
|
|
|
26
26
|
import { modulatorSources } from './soundfont/read/modulators.js';
|
|
27
27
|
import { ALL_CHANNELS_OR_DIFFERENT_ACTION } from './synthetizer/worklet_system/message_protocol/worklet_message.js';
|
|
28
28
|
import { trimSoundfont } from './soundfont/write/soundfont_trimmer.js';
|
|
29
|
+
import { OggVorbisEncoder } from './externals/libvorbis/OggVorbisEncoder.min.js';
|
|
29
30
|
import { WORKLET_URL_ABSOLUTE } from './synthetizer/worklet_url.js'
|
|
30
31
|
|
|
31
32
|
// Export modules
|
package/package.json
CHANGED
package/sequencer/sequencer.js
CHANGED
|
@@ -24,14 +24,26 @@ import { DUMMY_MIDI_DATA, MidiData } from '../midi_parser/midi_data.js'
|
|
|
24
24
|
* @typedef {MIDI|MidFile} MIDIFile
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {Object} SequencerOptions
|
|
29
|
+
* @property {boolean} skipToFirstNoteOn - if true, the sequencer will skip to the first note
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @type {SequencerOptions}
|
|
34
|
+
*/
|
|
35
|
+
const DEFAULT_OPTIONS = {
|
|
36
|
+
skipToFirstNoteOn: true,
|
|
37
|
+
}
|
|
27
38
|
export class Sequencer
|
|
28
39
|
{
|
|
29
40
|
/**
|
|
30
41
|
* Creates a new Midi sequencer for playing back MIDI files
|
|
31
42
|
* @param midiBinaries {MIDIFile[]} List of the buffers of the MIDI files
|
|
32
43
|
* @param synth {Synthetizer} synth to send events to
|
|
44
|
+
* @param options {SequencerOptions} the sequencer's options
|
|
33
45
|
*/
|
|
34
|
-
constructor(midiBinaries, synth)
|
|
46
|
+
constructor(midiBinaries, synth, options = DEFAULT_OPTIONS)
|
|
35
47
|
{
|
|
36
48
|
this.ignoreEvents = false;
|
|
37
49
|
this.synth = synth;
|
|
@@ -73,11 +85,42 @@ export class Sequencer
|
|
|
73
85
|
|
|
74
86
|
this.synth.sequencerCallbackFunction = this._handleMessage.bind(this);
|
|
75
87
|
|
|
88
|
+
/**
|
|
89
|
+
* @type {boolean}
|
|
90
|
+
* @private
|
|
91
|
+
*/
|
|
92
|
+
this._skipToFirstNoteOn = options?.skipToFirstNoteOn ?? true;
|
|
93
|
+
|
|
94
|
+
if(this._skipToFirstNoteOn === false)
|
|
95
|
+
{
|
|
96
|
+
// setter sends message
|
|
97
|
+
this._sendMessage(WorkletSequencerMessageType.setSkipToFirstNote, false);
|
|
98
|
+
}
|
|
99
|
+
|
|
76
100
|
this.loadNewSongList(midiBinaries);
|
|
77
101
|
|
|
78
102
|
window.addEventListener("beforeunload", this.resetMIDIOut.bind(this))
|
|
79
103
|
}
|
|
80
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Indicates if the sequencer should skip to first note on
|
|
107
|
+
* @return {boolean}
|
|
108
|
+
*/
|
|
109
|
+
get skipToFirstNoteOn()
|
|
110
|
+
{
|
|
111
|
+
return this._skipToFirstNoteOn;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Indicates if the sequencer should skip to first note on
|
|
116
|
+
* @param val {boolean}
|
|
117
|
+
*/
|
|
118
|
+
set skipToFirstNoteOn(val)
|
|
119
|
+
{
|
|
120
|
+
this._skipToFirstNoteOn = val;
|
|
121
|
+
this._sendMessage(WorkletSequencerMessageType.setSkipToFirstNote, this._skipToFirstNoteOn);
|
|
122
|
+
}
|
|
123
|
+
|
|
81
124
|
resetMIDIOut()
|
|
82
125
|
{
|
|
83
126
|
if(!this.MIDIout)
|
|
@@ -58,6 +58,11 @@ export function processMessage(messageType, messageData)
|
|
|
58
58
|
|
|
59
59
|
case WorkletSequencerMessageType.getMIDI:
|
|
60
60
|
this.post(WorkletSequencerReturnMessageType.getMIDI, this.midiData);
|
|
61
|
+
break;
|
|
62
|
+
|
|
63
|
+
case WorkletSequencerMessageType.setSkipToFirstNote:
|
|
64
|
+
this._skipToFirstNoteOn = messageData;
|
|
65
|
+
break;
|
|
61
66
|
}
|
|
62
67
|
}
|
|
63
68
|
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* @property {number} setLoop - 7 -> loop<boolean>
|
|
11
11
|
* @property {number} changeSong - 8 -> goForwards<boolean> if true, next song, if false, previous
|
|
12
12
|
* @property {number} getMIDI - 9 -> (no data)
|
|
13
|
+
* @property {number} setSkipToFirstNote -10 -> skipToFirstNoteOn<boolean>
|
|
13
14
|
*/
|
|
14
15
|
export const WorkletSequencerMessageType = {
|
|
15
16
|
loadNewSongList: 0,
|
|
@@ -21,7 +22,8 @@ export const WorkletSequencerMessageType = {
|
|
|
21
22
|
setPlaybackRate: 6,
|
|
22
23
|
setLoop: 7,
|
|
23
24
|
changeSong: 8,
|
|
24
|
-
getMIDI: 9
|
|
25
|
+
getMIDI: 9,
|
|
26
|
+
setSkipToFirstNote: 10
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
/**
|
|
@@ -88,6 +88,12 @@ class WorkletSequencer
|
|
|
88
88
|
* @type {Object<number, number>}
|
|
89
89
|
*/
|
|
90
90
|
this.midiPortChannelOffsets = {};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @type {boolean}
|
|
94
|
+
* @private
|
|
95
|
+
*/
|
|
96
|
+
this._skipToFirstNoteOn = true;
|
|
91
97
|
}
|
|
92
98
|
|
|
93
99
|
/**
|
|
@@ -113,12 +119,27 @@ class WorkletSequencer
|
|
|
113
119
|
|
|
114
120
|
set currentTime(time)
|
|
115
121
|
{
|
|
116
|
-
if(time
|
|
122
|
+
if(time > this.duration || time < 0)
|
|
117
123
|
{
|
|
118
124
|
// time is 0
|
|
119
|
-
|
|
125
|
+
if(this._skipToFirstNoteOn)
|
|
126
|
+
{
|
|
127
|
+
this.setTimeTicks(this.midiData.firstNoteOn - 1);
|
|
128
|
+
}
|
|
129
|
+
else
|
|
130
|
+
{
|
|
131
|
+
this.setTimeTicks(0);
|
|
132
|
+
}
|
|
120
133
|
return;
|
|
121
134
|
}
|
|
135
|
+
if(this._skipToFirstNoteOn)
|
|
136
|
+
{
|
|
137
|
+
if(time < this.firstNoteTime)
|
|
138
|
+
{
|
|
139
|
+
this.setTimeTicks(this.midiData.firstNoteOn - 1);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
122
143
|
this.stop();
|
|
123
144
|
this.playingNotes = [];
|
|
124
145
|
this.pausedTime = undefined;
|