spessasynth_core 3.27.7 → 4.0.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/README.md +188 -116
- package/dist/index.d.ts +4057 -0
- package/dist/index.js +17188 -0
- package/dist/index.js.map +1 -0
- package/package.json +23 -6
- package/index.js +0 -132
- package/src/externals/README.md +0 -6
- package/src/externals/fflate/LICENSE +0 -21
- package/src/externals/fflate/fflate.min.js +0 -1
- package/src/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +0 -12
- package/src/externals/stbvorbis_sync/LICENSE +0 -202
- package/src/externals/stbvorbis_sync/NOTICE +0 -6
- package/src/externals/stbvorbis_sync/stbvorbis_sync.min.js +0 -1
- package/src/midi/README.md +0 -32
- package/src/midi/basic_midi.js +0 -587
- package/src/midi/midi_builder.js +0 -203
- package/src/midi/midi_loader.js +0 -321
- package/src/midi/midi_message.js +0 -254
- package/src/midi/midi_sequence.js +0 -230
- package/src/midi/midi_tools/get_note_times.js +0 -154
- package/src/midi/midi_tools/midi_editor.js +0 -611
- package/src/midi/midi_tools/midi_writer.js +0 -105
- package/src/midi/midi_tools/rmidi_writer.js +0 -566
- package/src/midi/midi_tools/used_keys_loaded.js +0 -256
- package/src/midi/xmf_loader.js +0 -454
- package/src/sequencer/README.md +0 -9
- package/src/sequencer/events.js +0 -81
- package/src/sequencer/play.js +0 -362
- package/src/sequencer/process_event.js +0 -165
- package/src/sequencer/process_tick.js +0 -104
- package/src/sequencer/sequencer_engine.js +0 -372
- package/src/sequencer/song_control.js +0 -196
- package/src/soundfont/README.md +0 -11
- package/src/soundfont/basic_soundfont/basic_global_zone.js +0 -6
- package/src/soundfont/basic_soundfont/basic_instrument.js +0 -115
- package/src/soundfont/basic_soundfont/basic_instrument_zone.js +0 -45
- package/src/soundfont/basic_soundfont/basic_preset.js +0 -313
- package/src/soundfont/basic_soundfont/basic_preset_zone.js +0 -39
- package/src/soundfont/basic_soundfont/basic_sample.js +0 -477
- package/src/soundfont/basic_soundfont/basic_soundbank.js +0 -740
- package/src/soundfont/basic_soundfont/basic_zone.js +0 -145
- package/src/soundfont/basic_soundfont/generator.js +0 -76
- package/src/soundfont/basic_soundfont/generator_types.js +0 -151
- package/src/soundfont/basic_soundfont/modulator.js +0 -581
- package/src/soundfont/basic_soundfont/riff_chunk.js +0 -195
- package/src/soundfont/basic_soundfont/write_dls/art2.js +0 -174
- package/src/soundfont/basic_soundfont/write_dls/articulator.js +0 -49
- package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +0 -374
- package/src/soundfont/basic_soundfont/write_dls/ins.js +0 -85
- package/src/soundfont/basic_soundfont/write_dls/lins.js +0 -15
- package/src/soundfont/basic_soundfont/write_dls/modulator_converter.js +0 -330
- package/src/soundfont/basic_soundfont/write_dls/rgn2.js +0 -120
- package/src/soundfont/basic_soundfont/write_dls/wave.js +0 -71
- package/src/soundfont/basic_soundfont/write_dls/write_dls.js +0 -124
- package/src/soundfont/basic_soundfont/write_dls/wsmp.js +0 -78
- package/src/soundfont/basic_soundfont/write_dls/wvpl.js +0 -35
- package/src/soundfont/basic_soundfont/write_sf2/ibag.js +0 -60
- package/src/soundfont/basic_soundfont/write_sf2/igen.js +0 -91
- package/src/soundfont/basic_soundfont/write_sf2/imod.js +0 -62
- package/src/soundfont/basic_soundfont/write_sf2/inst.js +0 -42
- package/src/soundfont/basic_soundfont/write_sf2/pbag.js +0 -57
- package/src/soundfont/basic_soundfont/write_sf2/pgen.js +0 -92
- package/src/soundfont/basic_soundfont/write_sf2/phdr.js +0 -61
- package/src/soundfont/basic_soundfont/write_sf2/pmod.js +0 -62
- package/src/soundfont/basic_soundfont/write_sf2/sdta.js +0 -131
- package/src/soundfont/basic_soundfont/write_sf2/shdr.js +0 -77
- package/src/soundfont/basic_soundfont/write_sf2/write.js +0 -287
- package/src/soundfont/dls/articulator_converter.js +0 -402
- package/src/soundfont/dls/dls_destinations.js +0 -38
- package/src/soundfont/dls/dls_instrument.js +0 -20
- package/src/soundfont/dls/dls_preset.js +0 -43
- package/src/soundfont/dls/dls_sample.js +0 -238
- package/src/soundfont/dls/dls_soundfont.js +0 -183
- package/src/soundfont/dls/dls_sources.js +0 -63
- package/src/soundfont/dls/dls_zone.js +0 -89
- package/src/soundfont/dls/read_articulation.js +0 -300
- package/src/soundfont/dls/read_instrument.js +0 -118
- package/src/soundfont/dls/read_instrument_list.js +0 -17
- package/src/soundfont/dls/read_lart.js +0 -35
- package/src/soundfont/dls/read_region.js +0 -157
- package/src/soundfont/dls/read_samples.js +0 -154
- package/src/soundfont/load_soundfont.js +0 -21
- package/src/soundfont/read_sf2/generators.js +0 -43
- package/src/soundfont/read_sf2/instrument_zones.js +0 -75
- package/src/soundfont/read_sf2/instruments.js +0 -71
- package/src/soundfont/read_sf2/modulators.js +0 -25
- package/src/soundfont/read_sf2/preset_zones.js +0 -79
- package/src/soundfont/read_sf2/presets.js +0 -80
- package/src/soundfont/read_sf2/samples.js +0 -317
- package/src/soundfont/read_sf2/soundfont.js +0 -452
- package/src/soundfont/read_sf2/zones.js +0 -28
- package/src/synthetizer/README.md +0 -7
- package/src/synthetizer/audio_engine/README.md +0 -9
- package/src/synthetizer/audio_engine/engine_components/compute_modulator.js +0 -289
- package/src/synthetizer/audio_engine/engine_components/controller_tables.js +0 -90
- package/src/synthetizer/audio_engine/engine_components/dynamic_modulator_system.js +0 -95
- package/src/synthetizer/audio_engine/engine_components/enums.js +0 -18
- package/src/synthetizer/audio_engine/engine_components/key_modifier_manager.js +0 -151
- package/src/synthetizer/audio_engine/engine_components/lfo.js +0 -26
- package/src/synthetizer/audio_engine/engine_components/lowpass_filter.js +0 -282
- package/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js +0 -551
- package/src/synthetizer/audio_engine/engine_components/modulation_envelope.js +0 -181
- package/src/synthetizer/audio_engine/engine_components/modulator_curves.js +0 -89
- package/src/synthetizer/audio_engine/engine_components/soundfont_manager.js +0 -265
- package/src/synthetizer/audio_engine/engine_components/stereo_panner.js +0 -124
- package/src/synthetizer/audio_engine/engine_components/unit_converter.js +0 -73
- package/src/synthetizer/audio_engine/engine_components/voice.js +0 -525
- package/src/synthetizer/audio_engine/engine_components/volume_envelope.js +0 -402
- package/src/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +0 -274
- package/src/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +0 -159
- package/src/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +0 -48
- package/src/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +0 -254
- package/src/synthetizer/audio_engine/engine_methods/create_midi_channel.js +0 -20
- package/src/synthetizer/audio_engine/engine_methods/data_entry/awe32.js +0 -198
- package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +0 -281
- package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +0 -109
- package/src/synthetizer/audio_engine/engine_methods/mute_channel.js +0 -17
- package/src/synthetizer/audio_engine/engine_methods/note_on.js +0 -214
- package/src/synthetizer/audio_engine/engine_methods/portamento_time.js +0 -92
- package/src/synthetizer/audio_engine/engine_methods/program_change.js +0 -35
- package/src/synthetizer/audio_engine/engine_methods/render_voice.js +0 -214
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/embedded_sound_bank.js +0 -42
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +0 -0
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/update_preset_list.js +0 -19
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +0 -23
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +0 -56
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +0 -16
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +0 -30
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +0 -63
- package/src/synthetizer/audio_engine/engine_methods/system_exclusive.js +0 -1058
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +0 -23
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +0 -31
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +0 -29
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +0 -15
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +0 -27
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +0 -19
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +0 -27
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +0 -15
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +0 -34
- package/src/synthetizer/audio_engine/main_processor.js +0 -813
- package/src/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +0 -16
- package/src/synthetizer/audio_engine/snapshot/channel_snapshot.js +0 -175
- package/src/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +0 -116
- package/src/synthetizer/audio_engine/synth_processor_options.js +0 -18
- package/src/synthetizer/synth_constants.js +0 -26
- package/src/utils/README.md +0 -8
- package/src/utils/buffer_to_wav.js +0 -197
- package/src/utils/byte_functions/big_endian.js +0 -32
- package/src/utils/byte_functions/little_endian.js +0 -77
- package/src/utils/byte_functions/string.js +0 -92
- package/src/utils/byte_functions/variable_length_quantity.js +0 -42
- package/src/utils/fill_with_defaults.js +0 -21
- package/src/utils/indexed_array.js +0 -34
- package/src/utils/loggin.js +0 -71
- package/src/utils/other.js +0 -92
- package/src/utils/sysex_detector.js +0 -58
- package/src/utils/xg_hacks.js +0 -193
|
@@ -1,477 +0,0 @@
|
|
|
1
|
-
import { SpessaSynthWarn } from "../../utils/loggin.js";
|
|
2
|
-
import { IndexedByteArray } from "../../utils/indexed_array.js";
|
|
3
|
-
import { stbvorbis } from "../../externals/stbvorbis_sync/stbvorbis_sync.min.js";
|
|
4
|
-
|
|
5
|
-
// should be reasonable for most cases
|
|
6
|
-
const RESAMPLE_RATE = 48000;
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @typedef {1|2|4|8|32769|32770|32772|32776} sampleTypes
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @enum {sampleTypes}
|
|
14
|
-
*/
|
|
15
|
-
export const sampleTypes = {
|
|
16
|
-
monoSample: 1,
|
|
17
|
-
rightSample: 2,
|
|
18
|
-
leftSample: 4,
|
|
19
|
-
linkedSample: 8,
|
|
20
|
-
romMonoSample: 32769,
|
|
21
|
-
romRightSample: 32770,
|
|
22
|
-
romLeftSample: 32772,
|
|
23
|
-
romLinkedSample: 32776
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @typedef {function} SampleEncodingFunction
|
|
28
|
-
* @async
|
|
29
|
-
* @param audioData {Float32Array}
|
|
30
|
-
* @param sampleRate {number}
|
|
31
|
-
* @returns {Promise<Uint8Array>}
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
export class BasicSample
|
|
35
|
-
{
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* The sample's name
|
|
39
|
-
* @type {string}
|
|
40
|
-
*/
|
|
41
|
-
sampleName;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Sample rate in Hz
|
|
45
|
-
* @type {number}
|
|
46
|
-
*/
|
|
47
|
-
sampleRate;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Original pitch of the sample as a MIDI note number
|
|
51
|
-
* @type {number}
|
|
52
|
-
*/
|
|
53
|
-
samplePitch;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Pitch correction, in cents. Can be negative
|
|
57
|
-
* @type {number}
|
|
58
|
-
*/
|
|
59
|
-
samplePitchCorrection;
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Linked sample, unused if mono
|
|
63
|
-
* @type {BasicSample|undefined}
|
|
64
|
-
*/
|
|
65
|
-
linkedSample;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* The type of the sample
|
|
69
|
-
* @type {sampleTypes}
|
|
70
|
-
*/
|
|
71
|
-
sampleType;
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Relative to the start of the sample in sample points
|
|
75
|
-
* @type {number}
|
|
76
|
-
*/
|
|
77
|
-
sampleLoopStartIndex;
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Relative to the start of the sample in sample points
|
|
81
|
-
* @type {number}
|
|
82
|
-
*/
|
|
83
|
-
sampleLoopEndIndex;
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Indicates if the sample is compressed using vorbis SF3
|
|
87
|
-
* @type {boolean}
|
|
88
|
-
*/
|
|
89
|
-
isCompressed = false;
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* The compressed sample data if the sample has been compressed
|
|
93
|
-
* @type {Uint8Array|undefined}
|
|
94
|
-
*/
|
|
95
|
-
compressedData = undefined;
|
|
96
|
-
/**
|
|
97
|
-
* Sample's linked instruments (the instruments that use it)
|
|
98
|
-
* note that duplicates are allowed since one instrument can use the same sample multople times
|
|
99
|
-
* @type {BasicInstrument[]}
|
|
100
|
-
*/
|
|
101
|
-
linkedInstruments = [];
|
|
102
|
-
/**
|
|
103
|
-
* The sample's audio data
|
|
104
|
-
* @type {Float32Array|undefined}
|
|
105
|
-
*/
|
|
106
|
-
sampleData = undefined;
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Indicates if the data was overriden, so it cannot be copied back unchanged
|
|
110
|
-
* @type {boolean}
|
|
111
|
-
*/
|
|
112
|
-
dataOverriden = true;
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* The basic representation of a sample
|
|
116
|
-
* @param sampleName {string} The sample's name
|
|
117
|
-
* @param sampleRate {number} The sample's rate in Hz
|
|
118
|
-
* @param samplePitch {number} The sample's pitch as a MIDI note number
|
|
119
|
-
* @param samplePitchCorrection {number} The sample's pitch correction in cents
|
|
120
|
-
* @param sampleType {sampleTypes} The sample's type, an enum that can indicate SF3
|
|
121
|
-
* @param loopStart {number} The sample's loop start relative to the sample start in sample points
|
|
122
|
-
* @param loopEnd {number} The sample's loop end relative to the sample start in sample points
|
|
123
|
-
*/
|
|
124
|
-
constructor(
|
|
125
|
-
sampleName,
|
|
126
|
-
sampleRate,
|
|
127
|
-
samplePitch,
|
|
128
|
-
samplePitchCorrection,
|
|
129
|
-
sampleType,
|
|
130
|
-
loopStart,
|
|
131
|
-
loopEnd
|
|
132
|
-
)
|
|
133
|
-
{
|
|
134
|
-
this.sampleName = sampleName;
|
|
135
|
-
this.sampleRate = sampleRate;
|
|
136
|
-
this.samplePitch = samplePitch;
|
|
137
|
-
this.samplePitchCorrection = samplePitchCorrection;
|
|
138
|
-
this.sampleLoopStartIndex = loopStart;
|
|
139
|
-
this.sampleLoopEndIndex = loopEnd;
|
|
140
|
-
this.sampleType = sampleType;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* If the sample is linked to another sample
|
|
145
|
-
* @returns {boolean}
|
|
146
|
-
*/
|
|
147
|
-
get isLinked()
|
|
148
|
-
{
|
|
149
|
-
return this.sampleType === sampleTypes.rightSample ||
|
|
150
|
-
this.sampleType === sampleTypes.leftSample ||
|
|
151
|
-
this.sampleType === sampleTypes.linkedSample;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* The sample's use count
|
|
156
|
-
* @type {number}
|
|
157
|
-
*/
|
|
158
|
-
get useCount()
|
|
159
|
-
{
|
|
160
|
-
return this.linkedInstruments.length;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Get raw data for writing the file
|
|
165
|
-
* @param allowVorbis {boolean}
|
|
166
|
-
* @return {Uint8Array} either s16 or vorbis data
|
|
167
|
-
* @virtual
|
|
168
|
-
*/
|
|
169
|
-
getRawData(allowVorbis)
|
|
170
|
-
{
|
|
171
|
-
if (this.isCompressed && allowVorbis && !this.dataOverriden)
|
|
172
|
-
{
|
|
173
|
-
return this.compressedData;
|
|
174
|
-
}
|
|
175
|
-
return this.encodeS16LE();
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
resampleData(newSampleRate)
|
|
179
|
-
{
|
|
180
|
-
let audioData = this.getAudioData();
|
|
181
|
-
const ratio = newSampleRate / this.sampleRate;
|
|
182
|
-
const resampled = new Float32Array(Math.floor(audioData.length * ratio));
|
|
183
|
-
for (let i = 0; i < resampled.length; i++)
|
|
184
|
-
{
|
|
185
|
-
resampled[i] = audioData[Math.floor(i * (1 / ratio))];
|
|
186
|
-
}
|
|
187
|
-
audioData = resampled;
|
|
188
|
-
this.sampleRate = newSampleRate;
|
|
189
|
-
// adjust loop points
|
|
190
|
-
this.sampleLoopStartIndex = Math.floor(this.sampleLoopStartIndex * ratio);
|
|
191
|
-
this.sampleLoopEndIndex = Math.floor(this.sampleLoopEndIndex * ratio);
|
|
192
|
-
this.sampleData = audioData;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* @param encodeVorbis {SampleEncodingFunction}
|
|
197
|
-
*/
|
|
198
|
-
async compressSample(encodeVorbis)
|
|
199
|
-
{
|
|
200
|
-
// no need to compress
|
|
201
|
-
if (this.isCompressed)
|
|
202
|
-
{
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
// compress, always mono!
|
|
206
|
-
try
|
|
207
|
-
{
|
|
208
|
-
// if the sample rate is too low or too high, resample
|
|
209
|
-
let audioData = this.getAudioData();
|
|
210
|
-
if (this.sampleRate < 8000 || this.sampleRate > 96000)
|
|
211
|
-
{
|
|
212
|
-
this.resampleData(RESAMPLE_RATE);
|
|
213
|
-
audioData = this.getAudioData();
|
|
214
|
-
}
|
|
215
|
-
const compressed = await encodeVorbis(audioData, this.sampleRate);
|
|
216
|
-
this.setCompressedData(compressed);
|
|
217
|
-
}
|
|
218
|
-
catch (e)
|
|
219
|
-
{
|
|
220
|
-
SpessaSynthWarn(`Failed to compress ${this.sampleName}. Leaving as uncompressed!`, e);
|
|
221
|
-
delete this.compressedData;
|
|
222
|
-
// flag as uncompressed
|
|
223
|
-
this.isCompressed = false;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* @param type {sampleTypes|number}
|
|
230
|
-
*/
|
|
231
|
-
setSampleType(type)
|
|
232
|
-
{
|
|
233
|
-
this.sampleType = type;
|
|
234
|
-
if (!this.isLinked)
|
|
235
|
-
{
|
|
236
|
-
// unlink the other sample
|
|
237
|
-
if (this.linkedSample)
|
|
238
|
-
{
|
|
239
|
-
this.linkedSample.linkedSample = undefined;
|
|
240
|
-
this.linkedSample.sampleType = type;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
this.linkedSample = undefined;
|
|
244
|
-
}
|
|
245
|
-
if ((type & 0x8000) > 0)
|
|
246
|
-
{
|
|
247
|
-
throw new Error("ROM samples are not supported.");
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
deleteSample()
|
|
253
|
-
{
|
|
254
|
-
if (this.useCount > 0)
|
|
255
|
-
{
|
|
256
|
-
throw new Error(`Cannot delete sample used by: ${this.linkedInstruments.map(i => i.instrumentName)}.`);
|
|
257
|
-
}
|
|
258
|
-
this.unlinkSample();
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// noinspection JSUnusedGlobalSymbols
|
|
262
|
-
/**
|
|
263
|
-
* Unlinks a sample link
|
|
264
|
-
*/
|
|
265
|
-
unlinkSample()
|
|
266
|
-
{
|
|
267
|
-
this.setSampleType(sampleTypes.monoSample);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// noinspection JSUnusedGlobalSymbols
|
|
271
|
-
/**
|
|
272
|
-
* Links a stereo sample
|
|
273
|
-
* @param sample {BasicSample} the sample to link to
|
|
274
|
-
* @param type {sampleTypes} either left, right or linked
|
|
275
|
-
*/
|
|
276
|
-
setLinkedSample(sample, type)
|
|
277
|
-
{
|
|
278
|
-
// sanity check
|
|
279
|
-
if (sample.linkedSample)
|
|
280
|
-
{
|
|
281
|
-
throw new Error(`${sample.sampleName} is linked tp ${sample.linkedSample.sampleName}. Unlink it first.`);
|
|
282
|
-
}
|
|
283
|
-
this.linkedSample = sample;
|
|
284
|
-
sample.linkedSample = this;
|
|
285
|
-
if (type === sampleTypes.leftSample)
|
|
286
|
-
{
|
|
287
|
-
this.setSampleType(sampleTypes.leftSample);
|
|
288
|
-
sample.setSampleType(sampleTypes.rightSample);
|
|
289
|
-
}
|
|
290
|
-
else if (type === sampleTypes.rightSample)
|
|
291
|
-
{
|
|
292
|
-
this.setSampleType(sampleTypes.rightSample);
|
|
293
|
-
sample.setSampleType(sampleTypes.leftSample);
|
|
294
|
-
}
|
|
295
|
-
else if (type === sampleTypes.linkedSample)
|
|
296
|
-
{
|
|
297
|
-
this.setSampleType(sampleTypes.linkedSample);
|
|
298
|
-
sample.setSampleType(sampleTypes.linkedSample);
|
|
299
|
-
}
|
|
300
|
-
else
|
|
301
|
-
{
|
|
302
|
-
throw new Error("Invalid sample type: " + type);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* @param instrument {BasicInstrument}
|
|
308
|
-
*/
|
|
309
|
-
linkTo(instrument)
|
|
310
|
-
{
|
|
311
|
-
this.linkedInstruments.push(instrument);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
/**
|
|
315
|
-
* @param instrument {BasicInstrument}
|
|
316
|
-
*/
|
|
317
|
-
unlinkFrom(instrument)
|
|
318
|
-
{
|
|
319
|
-
const index = this.linkedInstruments.indexOf(instrument);
|
|
320
|
-
if (index < 0)
|
|
321
|
-
{
|
|
322
|
-
SpessaSynthWarn(`Cannot unlink ${instrument.instrumentName} from ${this.sampleName}: not linked.`);
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
this.linkedInstruments.splice(index, 1);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
/**
|
|
330
|
-
* @private
|
|
331
|
-
* Decode binary vorbis into a float32 pcm
|
|
332
|
-
* @returns {Float32Array}
|
|
333
|
-
*/
|
|
334
|
-
decodeVorbis()
|
|
335
|
-
{
|
|
336
|
-
if (this.sampleData)
|
|
337
|
-
{
|
|
338
|
-
return this.sampleData;
|
|
339
|
-
}
|
|
340
|
-
// get the compressed byte stream
|
|
341
|
-
// reset array and being decoding
|
|
342
|
-
try
|
|
343
|
-
{
|
|
344
|
-
/**
|
|
345
|
-
* @type {{data: Float32Array[], error: (string|null), sampleRate: number, eof: boolean}}
|
|
346
|
-
*/
|
|
347
|
-
const vorbis = stbvorbis.decode(this.compressedData);
|
|
348
|
-
const decoded = vorbis.data[0];
|
|
349
|
-
if (decoded === undefined)
|
|
350
|
-
{
|
|
351
|
-
SpessaSynthWarn(`Error decoding sample ${this.sampleName}: Vorbis decode returned undefined.`);
|
|
352
|
-
return new Float32Array(0);
|
|
353
|
-
}
|
|
354
|
-
// clip
|
|
355
|
-
// because vorbis can go above 1 sometimes
|
|
356
|
-
for (let i = 0; i < decoded.length; i++)
|
|
357
|
-
{
|
|
358
|
-
// magic number is 32,767 / 32,768
|
|
359
|
-
decoded[i] = Math.max(-1, Math.min(decoded[i], 0.999969482421875));
|
|
360
|
-
}
|
|
361
|
-
return decoded;
|
|
362
|
-
}
|
|
363
|
-
catch (e)
|
|
364
|
-
{
|
|
365
|
-
// do not error out, fill with silence
|
|
366
|
-
SpessaSynthWarn(`Error decoding sample ${this.sampleName}: ${e}`);
|
|
367
|
-
return new Float32Array(this.sampleLoopEndIndex + 1);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
* Get the float32 audio data.
|
|
373
|
-
* Note that this either decodes the compressed data or passes the ready sampleData.
|
|
374
|
-
* If neither are set then it will throw an error!
|
|
375
|
-
* @returns {Float32Array}
|
|
376
|
-
*/
|
|
377
|
-
getAudioData()
|
|
378
|
-
{
|
|
379
|
-
if (this.sampleData)
|
|
380
|
-
{
|
|
381
|
-
return this.sampleData;
|
|
382
|
-
}
|
|
383
|
-
if (this.isCompressed)
|
|
384
|
-
{
|
|
385
|
-
// SF3
|
|
386
|
-
// if compressed, decode
|
|
387
|
-
this.sampleData = this.decodeVorbis();
|
|
388
|
-
return this.sampleData;
|
|
389
|
-
}
|
|
390
|
-
throw new Error("Sample data is undefined for a BasicSample instance.");
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
/**
|
|
394
|
-
* Encodes s16le sample
|
|
395
|
-
* @return {IndexedByteArray}
|
|
396
|
-
*/
|
|
397
|
-
encodeS16LE()
|
|
398
|
-
{
|
|
399
|
-
const data = this.getAudioData();
|
|
400
|
-
const data16 = new Int16Array(data.length);
|
|
401
|
-
const len = data.length;
|
|
402
|
-
for (let i = 0; i < len; i++)
|
|
403
|
-
{
|
|
404
|
-
let sample = data[i] * 32768;
|
|
405
|
-
// Clamp for safety (do not use Math.max/Math.min here)
|
|
406
|
-
if (sample > 32767)
|
|
407
|
-
{
|
|
408
|
-
sample = 32767;
|
|
409
|
-
}
|
|
410
|
-
else if (sample < -32768)
|
|
411
|
-
{
|
|
412
|
-
sample = -32768;
|
|
413
|
-
}
|
|
414
|
-
data16[i] = sample;
|
|
415
|
-
}
|
|
416
|
-
return new IndexedByteArray(data16.buffer);
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
// noinspection JSUnusedGlobalSymbols
|
|
420
|
-
/**
|
|
421
|
-
* REPLACES the audio data
|
|
422
|
-
* @param audioData {Float32Array}
|
|
423
|
-
* @virtual
|
|
424
|
-
*/
|
|
425
|
-
setAudioData(audioData)
|
|
426
|
-
{
|
|
427
|
-
this.isCompressed = false;
|
|
428
|
-
delete this.compressedData;
|
|
429
|
-
this.sampleData = audioData;
|
|
430
|
-
this.dataOverriden = true;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
/**
|
|
434
|
-
* Replaces the audio with a compressed data sample
|
|
435
|
-
* @param data {Uint8Array}
|
|
436
|
-
*/
|
|
437
|
-
setCompressedData(data)
|
|
438
|
-
{
|
|
439
|
-
this.sampleData = undefined;
|
|
440
|
-
this.compressedData = data;
|
|
441
|
-
this.isCompressed = true;
|
|
442
|
-
this.dataOverriden = false;
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
export class CreatedSample extends BasicSample
|
|
448
|
-
{
|
|
449
|
-
/**
|
|
450
|
-
* A simplified class for creating samples
|
|
451
|
-
* @param name
|
|
452
|
-
* @param sampleRate
|
|
453
|
-
* @param sampleData
|
|
454
|
-
*/
|
|
455
|
-
constructor(name, sampleRate, sampleData)
|
|
456
|
-
{
|
|
457
|
-
super(name, sampleRate, 60, 0, sampleTypes.monoSample, 0, sampleData.length - 1);
|
|
458
|
-
this.setAudioData(sampleData);
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
/**
|
|
462
|
-
* @param allowVorbis {boolean}
|
|
463
|
-
* @returns {Uint8Array}
|
|
464
|
-
*/
|
|
465
|
-
getRawData(allowVorbis)
|
|
466
|
-
{
|
|
467
|
-
return super.getRawData(allowVorbis);
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
/**
|
|
471
|
-
* @param audioData {Float32Array}
|
|
472
|
-
*/
|
|
473
|
-
setAudioData(audioData)
|
|
474
|
-
{
|
|
475
|
-
super.setAudioData(audioData);
|
|
476
|
-
}
|
|
477
|
-
}
|