spessasynth_lib 3.21.13 → 3.21.14
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/synthetizer/synthetizer.d.ts +4 -0
- package/package.json +1 -1
- package/soundfont/dls/read_samples.js +3 -2
- package/synthetizer/synthetizer.js +26 -6
- package/synthetizer/worklet_processor.min.js +10 -10
- package/synthetizer/worklet_system/main_processor.js +5 -2
- package/synthetizer/worklet_system/worklet_methods/controller_control.js +2 -2
- package/synthetizer/worklet_system/worklet_methods/snapshot.js +1 -0
- package/synthetizer/worklet_system/worklet_methods/voice_control.js +4 -17
- package/synthetizer/worklet_system/worklet_utilities/stereo_panner.js +25 -22
|
@@ -50,6 +50,7 @@ import { applySynthesizerSnapshot, sendSynthesizerSnapshot } from "./worklet_met
|
|
|
50
50
|
import { WorkletSoundfontManager } from "./worklet_methods/worklet_soundfont_manager/worklet_soundfont_manager.js";
|
|
51
51
|
import { interpolationTypes } from "./worklet_utilities/wavetable_oscillator.js";
|
|
52
52
|
import { getWorkletVoices } from "./worklet_utilities/worklet_voice.js";
|
|
53
|
+
import { panVoice } from "./worklet_utilities/stereo_panner.js";
|
|
53
54
|
|
|
54
55
|
|
|
55
56
|
/**
|
|
@@ -144,7 +145,7 @@ class SpessaSynthProcessor extends AudioWorkletProcessor
|
|
|
144
145
|
* the pan of the left channel
|
|
145
146
|
* @type {number}
|
|
146
147
|
*/
|
|
147
|
-
this.panLeft = 0.5
|
|
148
|
+
this.panLeft = 0.5;
|
|
148
149
|
|
|
149
150
|
this.highPerformanceMode = false;
|
|
150
151
|
|
|
@@ -158,7 +159,7 @@ class SpessaSynthProcessor extends AudioWorkletProcessor
|
|
|
158
159
|
* the pan of the right channel
|
|
159
160
|
* @type {number}
|
|
160
161
|
*/
|
|
161
|
-
this.panRight = 0.5
|
|
162
|
+
this.panRight = 0.5;
|
|
162
163
|
try
|
|
163
164
|
{
|
|
164
165
|
/**
|
|
@@ -445,4 +446,6 @@ SpessaSynthProcessor.prototype.sendPresetList = sendPresetList;
|
|
|
445
446
|
SpessaSynthProcessor.prototype.sendSynthesizerSnapshot = sendSynthesizerSnapshot;
|
|
446
447
|
SpessaSynthProcessor.prototype.applySynthesizerSnapshot = applySynthesizerSnapshot;
|
|
447
448
|
|
|
449
|
+
SpessaSynthProcessor.prototype.panVoice = panVoice;
|
|
450
|
+
|
|
448
451
|
export { SpessaSynthProcessor };
|
|
@@ -235,8 +235,8 @@ export function setMasterPan(pan)
|
|
|
235
235
|
this.pan = pan;
|
|
236
236
|
// clamp to 0-1 (0 is left)
|
|
237
237
|
pan = (pan / 2) + 0.5;
|
|
238
|
-
this.panLeft = (1 - pan)
|
|
239
|
-
this.panRight = (pan)
|
|
238
|
+
this.panLeft = (1 - pan);
|
|
239
|
+
this.panRight = (pan);
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
/**
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
* @property {interpolationTypes} interpolation - the synth's interpolation type
|
|
33
33
|
* @property {SynthSystem} system - the synths system. Values can be "gs", "gm", "gm2" or "xg"
|
|
34
34
|
* @property {number} transposition - the current synth transpositon in semitones. can be a float
|
|
35
|
+
* @property {EffectsConfig} effectsConfig - the effects configuration object
|
|
35
36
|
*/
|
|
36
37
|
|
|
37
38
|
import { returnMessageType } from "../message_protocol/worklet_message.js";
|
|
@@ -7,15 +7,12 @@ import {
|
|
|
7
7
|
getSampleNearest,
|
|
8
8
|
interpolationTypes
|
|
9
9
|
} from "../worklet_utilities/wavetable_oscillator.js";
|
|
10
|
-
import { panVoice } from "../worklet_utilities/stereo_panner.js";
|
|
11
10
|
import { WorkletLowpassFilter } from "../worklet_utilities/lowpass_filter.js";
|
|
12
11
|
import { MIN_NOTE_LENGTH } from "../main_processor.js";
|
|
13
12
|
import { WorkletVolumeEnvelope } from "../worklet_utilities/volume_envelope.js";
|
|
14
13
|
import { generatorTypes } from "../../../soundfont/basic_soundfont/generator.js";
|
|
15
14
|
import { customControllers } from "../worklet_utilities/controller_tables.js";
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
const HALF_PI = Math.PI / 2;
|
|
19
16
|
export const PAN_SMOOTHING_FACTOR = 0.05;
|
|
20
17
|
|
|
21
18
|
/**
|
|
@@ -157,8 +154,6 @@ export function renderVoice(
|
|
|
157
154
|
voice.currentTuningCalculated = Math.pow(2, centsTotal / 1200);
|
|
158
155
|
}
|
|
159
156
|
|
|
160
|
-
// PANNING
|
|
161
|
-
const pan = ((Math.max(-500, Math.min(500, voice.modulatedGenerators[generatorTypes.pan])) + 500) / 1000); // 0 to 1
|
|
162
157
|
|
|
163
158
|
// SYNTHESIS
|
|
164
159
|
const bufferOut = new Float32Array(outputLeft.length);
|
|
@@ -189,20 +184,12 @@ export function renderVoice(
|
|
|
189
184
|
// volenv
|
|
190
185
|
WorkletVolumeEnvelope.apply(voice, bufferOut, modLfoCentibels, this.volumeEnvelopeSmoothingFactor);
|
|
191
186
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
const panLeft = Math.cos(HALF_PI * voice.currentPan) * this.panLeft;
|
|
195
|
-
const panRight = Math.sin(HALF_PI * voice.currentPan) * this.panRight;
|
|
196
|
-
// disable reverb and chorus in one output mode
|
|
197
|
-
const reverb = this.oneOutputMode ? 0 : voice.modulatedGenerators[generatorTypes.reverbEffectsSend];
|
|
198
|
-
const chorus = this.oneOutputMode ? 0 : voice.modulatedGenerators[generatorTypes.chorusEffectsSend];
|
|
199
|
-
panVoice(
|
|
200
|
-
panLeft,
|
|
201
|
-
panRight,
|
|
187
|
+
this.panVoice(
|
|
188
|
+
voice,
|
|
202
189
|
bufferOut,
|
|
203
190
|
outputLeft, outputRight,
|
|
204
|
-
reverbOutput,
|
|
205
|
-
chorusOutput
|
|
191
|
+
reverbOutput,
|
|
192
|
+
chorusOutput
|
|
206
193
|
);
|
|
207
194
|
}
|
|
208
195
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { generatorTypes } from "../../../soundfont/basic_soundfont/generator.js";
|
|
2
|
+
|
|
1
3
|
export const WORKLET_SYSTEM_REVERB_DIVIDER = 4600;
|
|
2
4
|
export const WORKLET_SYSTEM_CHORUS_DIVIDER = 2000;
|
|
5
|
+
const HALF_PI = Math.PI / 2;
|
|
3
6
|
|
|
4
7
|
/**
|
|
5
8
|
* stereo_panner.js
|
|
@@ -8,53 +11,53 @@ export const WORKLET_SYSTEM_CHORUS_DIVIDER = 2000;
|
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
13
|
* Pans the voice to the given output buffers
|
|
11
|
-
* @param
|
|
12
|
-
* @param gainRight {number} the right channel gain
|
|
14
|
+
* @param voice {WorkletVoice} the voice to pan
|
|
13
15
|
* @param inputBuffer {Float32Array} the input buffer in mono
|
|
14
16
|
* @param outputLeft {Float32Array} left output buffer
|
|
15
17
|
* @param outputRight {Float32Array} right output buffer
|
|
16
18
|
* @param reverb {Float32Array[]} stereo reverb input
|
|
17
|
-
* @param
|
|
18
|
-
* @
|
|
19
|
-
* @param chorusLevel {number} 0 to 1000, the level of chorus to send
|
|
19
|
+
* @param chorus {Float32Array[]} stereo chorus buffer
|
|
20
|
+
* @this {SpessaSynthProcessor}
|
|
20
21
|
*/
|
|
21
|
-
export function panVoice(
|
|
22
|
-
gainRight,
|
|
22
|
+
export function panVoice(voice,
|
|
23
23
|
inputBuffer,
|
|
24
24
|
outputLeft, outputRight,
|
|
25
25
|
reverb,
|
|
26
|
-
|
|
27
|
-
chorus,
|
|
28
|
-
chorusLevel)
|
|
26
|
+
chorus)
|
|
29
27
|
{
|
|
30
28
|
if (isNaN(inputBuffer[0]))
|
|
31
29
|
{
|
|
32
30
|
return;
|
|
33
31
|
}
|
|
32
|
+
const pan = ((Math.max(-500, Math.min(500, voice.modulatedGenerators[generatorTypes.pan])) + 500) / 1000); // 0 to 1
|
|
33
|
+
voice.currentPan += (pan - voice.currentPan) * this.panSmoothingFactor; // smooth out pan to prevent clicking
|
|
34
|
+
|
|
35
|
+
const gain = this.currentGain;
|
|
36
|
+
// pan the voice and write out
|
|
37
|
+
const gainLeft = Math.cos(HALF_PI * voice.currentPan) * gain * this.panLeft;
|
|
38
|
+
const gainRight = Math.sin(HALF_PI * voice.currentPan) * gain * this.panRight;
|
|
39
|
+
// disable reverb and chorus in one output mode
|
|
40
|
+
|
|
41
|
+
const reverbLevel = voice.modulatedGenerators[generatorTypes.reverbEffectsSend] / WORKLET_SYSTEM_REVERB_DIVIDER * gain;
|
|
42
|
+
const chorusLevel = voice.modulatedGenerators[generatorTypes.chorusEffectsSend] / WORKLET_SYSTEM_CHORUS_DIVIDER;
|
|
34
43
|
|
|
35
|
-
if (reverbLevel > 0)
|
|
44
|
+
if (reverbLevel > 0 && !this.oneOutputMode)
|
|
36
45
|
{
|
|
37
46
|
const reverbLeft = reverb[0];
|
|
38
47
|
const reverbRight = reverb[1];
|
|
39
|
-
// cap reverb
|
|
40
|
-
reverbLevel = Math.min(reverbLevel, 1000);
|
|
41
|
-
const reverbGain = reverbLevel / WORKLET_SYSTEM_REVERB_DIVIDER;
|
|
42
48
|
for (let i = 0; i < inputBuffer.length; i++)
|
|
43
49
|
{
|
|
44
|
-
reverbLeft[i] +=
|
|
45
|
-
reverbRight[i] +=
|
|
50
|
+
reverbLeft[i] += reverbLevel * inputBuffer[i];
|
|
51
|
+
reverbRight[i] += reverbLevel * inputBuffer[i];
|
|
46
52
|
}
|
|
47
53
|
}
|
|
48
54
|
|
|
49
|
-
if (chorusLevel > 0)
|
|
55
|
+
if (chorusLevel > 0 && !this.oneOutputMode)
|
|
50
56
|
{
|
|
51
57
|
const chorusLeft = chorus[0];
|
|
52
58
|
const chorusRight = chorus[1];
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const chorusGain = chorusLevel / WORKLET_SYSTEM_CHORUS_DIVIDER;
|
|
56
|
-
const chorusLeftGain = gainLeft * chorusGain;
|
|
57
|
-
const chorusRightGain = gainRight * chorusGain;
|
|
59
|
+
const chorusLeftGain = gainLeft * chorusLevel;
|
|
60
|
+
const chorusRightGain = gainRight * chorusLevel;
|
|
58
61
|
for (let i = 0; i < inputBuffer.length; i++)
|
|
59
62
|
{
|
|
60
63
|
chorusLeft[i] += chorusLeftGain * inputBuffer[i];
|