@blibliki/engine 0.1.27 → 0.3.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.
Files changed (123) hide show
  1. package/README.md +252 -76
  2. package/dist/index.cjs +2 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +765 -0
  5. package/dist/index.d.ts +765 -0
  6. package/dist/index.js +2 -19484
  7. package/dist/index.js.map +1 -0
  8. package/package.json +19 -28
  9. package/src/Engine.ts +158 -177
  10. package/src/core/IO/AudioIO.ts +72 -0
  11. package/src/core/IO/Base.ts +118 -0
  12. package/src/core/IO/Collection.ts +123 -47
  13. package/src/core/IO/MidiIO.ts +43 -0
  14. package/src/core/IO/PolyAudioIO.ts +115 -0
  15. package/src/core/IO/index.ts +7 -61
  16. package/src/core/Note/frequencyTable.ts +144 -144
  17. package/src/core/Note/index.ts +49 -59
  18. package/src/core/Route.ts +79 -0
  19. package/src/core/Timing/Scheduler.ts +37 -0
  20. package/src/core/Timing/Time.ts +103 -0
  21. package/src/core/Timing/Transport.ts +104 -0
  22. package/src/core/Timing/index.ts +16 -0
  23. package/src/core/index.ts +36 -0
  24. package/src/core/midi/{ComputerKeyboardInput.ts → ComputerKeyboardDevice.ts} +31 -11
  25. package/src/core/midi/MidiDevice.ts +38 -31
  26. package/src/core/midi/MidiDeviceManager.ts +54 -55
  27. package/src/core/midi/MidiEvent.ts +36 -60
  28. package/src/core/module/Module.ts +233 -0
  29. package/src/core/module/PolyModule.ts +246 -0
  30. package/src/core/module/VoiceScheduler.ts +121 -0
  31. package/src/core/module/index.ts +3 -0
  32. package/src/core/schema.ts +41 -0
  33. package/src/index.ts +31 -9
  34. package/src/modules/BiquadFilter.ts +162 -0
  35. package/src/modules/Constant.ts +72 -0
  36. package/src/modules/Envelope.ts +178 -0
  37. package/src/modules/Filter.ts +109 -104
  38. package/src/modules/Gain.ts +78 -0
  39. package/src/modules/Inspector.ts +59 -0
  40. package/src/modules/Master.ts +18 -21
  41. package/src/modules/MidiSelector.ts +50 -50
  42. package/src/modules/Oscillator.ts +203 -158
  43. package/src/modules/Scale.ts +79 -0
  44. package/src/modules/StepSequencer.ts +61 -0
  45. package/src/modules/VirtualMidi.ts +33 -49
  46. package/src/modules/index.ts +159 -74
  47. package/src/nodePolyfill.ts +25 -0
  48. package/src/processors/filter-processor.ts +82 -0
  49. package/src/processors/index.ts +28 -0
  50. package/src/processors/scale-processor.ts +81 -0
  51. package/dist/index.umd.cjs +0 -227
  52. package/dist/src/Engine.d.ts +0 -83
  53. package/dist/src/core/IO/AudioNode.d.ts +0 -36
  54. package/dist/src/core/IO/Collection.d.ts +0 -14
  55. package/dist/src/core/IO/ForwardNode/Base.d.ts +0 -19
  56. package/dist/src/core/IO/ForwardNode/index.d.ts +0 -28
  57. package/dist/src/core/IO/MidiNode.d.ts +0 -31
  58. package/dist/src/core/IO/Node.d.ts +0 -41
  59. package/dist/src/core/IO/index.d.ts +0 -22
  60. package/dist/src/core/Module/MonoModule.d.ts +0 -68
  61. package/dist/src/core/Module/PolyModule.d.ts +0 -62
  62. package/dist/src/core/Module/index.d.ts +0 -7
  63. package/dist/src/core/Note/frequencyTable.d.ts +0 -4
  64. package/dist/src/core/Note/index.d.ts +0 -28
  65. package/dist/src/core/midi/ComputerKeyboardInput.d.ts +0 -12
  66. package/dist/src/core/midi/MidiDevice.d.ts +0 -30
  67. package/dist/src/core/midi/MidiDeviceManager.d.ts +0 -15
  68. package/dist/src/core/midi/MidiEvent.d.ts +0 -22
  69. package/dist/src/core/midi/index.d.ts +0 -5
  70. package/dist/src/index.d.ts +0 -9
  71. package/dist/src/main.d.ts +0 -0
  72. package/dist/src/modules/BitCrusher.d.ts +0 -17
  73. package/dist/src/modules/Delay.d.ts +0 -20
  74. package/dist/src/modules/Distortion.d.ts +0 -17
  75. package/dist/src/modules/Effect.d.ts +0 -20
  76. package/dist/src/modules/Envelope/AmpEnvelope.d.ts +0 -19
  77. package/dist/src/modules/Envelope/Base.d.ts +0 -67
  78. package/dist/src/modules/Envelope/FreqEnvelope.d.ts +0 -26
  79. package/dist/src/modules/Envelope/index.d.ts +0 -3
  80. package/dist/src/modules/Filter.d.ts +0 -43
  81. package/dist/src/modules/LFO.d.ts +0 -45
  82. package/dist/src/modules/Master.d.ts +0 -12
  83. package/dist/src/modules/MidiSelector.d.ts +0 -22
  84. package/dist/src/modules/Oscillator.d.ts +0 -56
  85. package/dist/src/modules/Reverb.d.ts +0 -20
  86. package/dist/src/modules/Sequencer.d.ts +0 -43
  87. package/dist/src/modules/VirtualMidi.d.ts +0 -33
  88. package/dist/src/modules/VoiceScheduler.d.ts +0 -45
  89. package/dist/src/modules/Volume.d.ts +0 -27
  90. package/dist/src/modules/index.d.ts +0 -18
  91. package/dist/src/routes.d.ts +0 -19
  92. package/dist/src/types.d.ts +0 -5
  93. package/dist/src/utils.d.ts +0 -1
  94. package/dist/test/MockingModules.d.ts +0 -22
  95. package/dist/test/Module/Oscillator.test.d.ts +0 -1
  96. package/dist/test/core/IO.test.d.ts +0 -1
  97. package/src/core/IO/AudioNode.ts +0 -82
  98. package/src/core/IO/ForwardNode/Base.ts +0 -99
  99. package/src/core/IO/ForwardNode/index.ts +0 -60
  100. package/src/core/IO/MidiNode.ts +0 -67
  101. package/src/core/IO/Node.ts +0 -118
  102. package/src/core/Module/MonoModule.ts +0 -219
  103. package/src/core/Module/PolyModule.ts +0 -218
  104. package/src/core/Module/index.ts +0 -15
  105. package/src/core/midi/index.ts +0 -5
  106. package/src/main.ts +0 -1
  107. package/src/modules/BitCrusher.ts +0 -45
  108. package/src/modules/Delay.ts +0 -53
  109. package/src/modules/Distortion.ts +0 -45
  110. package/src/modules/Effect.ts +0 -46
  111. package/src/modules/Envelope/AmpEnvelope.ts +0 -23
  112. package/src/modules/Envelope/Base.ts +0 -176
  113. package/src/modules/Envelope/FreqEnvelope.ts +0 -64
  114. package/src/modules/Envelope/index.ts +0 -3
  115. package/src/modules/LFO.ts +0 -149
  116. package/src/modules/Reverb.ts +0 -53
  117. package/src/modules/Sequencer.ts +0 -178
  118. package/src/modules/VoiceScheduler.ts +0 -145
  119. package/src/modules/Volume.ts +0 -72
  120. package/src/routes.ts +0 -49
  121. package/src/types.ts +0 -3
  122. package/src/utils.ts +0 -18
  123. package/src/vite-env.d.ts +0 -1
@@ -1,84 +1,169 @@
1
- import { Envelope, AmpEnvelope, FreqEnvelope } from "./Envelope";
2
- import Oscillator, { MonoOscillator } from "./Oscillator";
3
- import Filter from "./Filter";
4
- import Master from "./Master";
5
- import VoiceScheduler from "./VoiceScheduler";
6
- import MidiSelector from "./MidiSelector";
7
- import Volume from "./Volume";
8
- import VirtualMidi from "./VirtualMidi";
9
- import Reverb from "./Reverb";
10
- import Delay from "./Delay";
11
- import Distortion from "./Distortion";
12
- import BitCrusher from "./BitCrusher";
13
- import Sequencer from "./Sequencer";
14
- import LFO from "./LFO";
15
- import { AudioModule } from "../core/Module";
1
+ import { assertNever } from "@blibliki/utils";
2
+ import { IModule, Module, PropSchema } from "@/core";
3
+ import { IPolyModuleConstructor } from "@/core/module/PolyModule";
4
+ import VoiceScheduler, {
5
+ IVoiceSchedulerProps,
6
+ voiceSchedulerPropSchema,
7
+ } from "@/core/module/VoiceScheduler";
8
+ import BiquadFilter, {
9
+ biquadFilterPropSchema,
10
+ IBiquadFilterProps,
11
+ } from "./BiquadFilter";
12
+ import Constant, { constantPropSchema, IConstantProps } from "./Constant";
13
+ import Envelope, { envelopePropSchema, IEnvelopeProps } from "./Envelope";
14
+ import Filter, { filterPropSchema, IFilterProps } from "./Filter";
15
+ import Gain, { gainPropSchema, IGainProps } from "./Gain";
16
+ import Inspector, { IInspectorProps, inspectorPropSchema } from "./Inspector";
17
+ import Master, { IMasterProps, masterPropSchema } from "./Master";
18
+ import MidiSelector, {
19
+ IMidiSelectorProps,
20
+ midiSelectorPropSchema,
21
+ } from "./MidiSelector";
22
+ import Oscillator, {
23
+ IOscillatorProps,
24
+ oscillatorPropSchema,
25
+ } from "./Oscillator";
26
+ import Scale, { IScaleProps, scalePropSchema } from "./Scale";
27
+ import StepSequencer, {
28
+ IStepSequencerProps,
29
+ stepSequencerPropSchema,
30
+ } from "./StepSequencer";
31
+ import VirtualMidi, {
32
+ IVirtualMidiProps,
33
+ virtualMidiPropSchema,
34
+ } from "./VirtualMidi";
16
35
 
17
- export { default as Master } from "./Master";
18
- export { default as Filter } from "./Filter";
19
- export { default as Oscillator, MonoOscillator } from "./Oscillator";
20
- export { default as VirtualMidi } from "./VirtualMidi";
21
- export { default as VoiceScheduler } from "./VoiceScheduler";
22
- export { default as Sequencer } from "./Sequencer";
23
- export type { ISequence } from "./Sequencer";
36
+ export enum ModuleType {
37
+ Master = "Master",
38
+ Oscillator = "Oscillator",
39
+ Gain = "Gain",
40
+ MidiSelector = "MidiSelector",
41
+ Envelope = "Envelope",
42
+ Filter = "Filter",
43
+ BiquadFilter = "BiquadFilter",
44
+ Scale = "Scale",
45
+ Inspector = "Inspector",
46
+ Constant = "Constant",
47
+ VirtualMidi = "VirtualMidi",
48
+ StepSequencer = "StepSequencer",
49
+ VoiceScheduler = "VoiceScheduler",
50
+ }
51
+
52
+ export type ModuleTypeToPropsMapping = {
53
+ [ModuleType.Oscillator]: IOscillatorProps;
54
+ [ModuleType.Gain]: IGainProps;
55
+ [ModuleType.Master]: IMasterProps;
56
+ [ModuleType.MidiSelector]: IMidiSelectorProps;
57
+ [ModuleType.Envelope]: IEnvelopeProps;
58
+ [ModuleType.Filter]: IFilterProps;
59
+ [ModuleType.BiquadFilter]: IBiquadFilterProps;
60
+ [ModuleType.Scale]: IScaleProps;
61
+ [ModuleType.Inspector]: IInspectorProps;
62
+ [ModuleType.Constant]: IConstantProps;
63
+ [ModuleType.VirtualMidi]: IVirtualMidiProps;
64
+ [ModuleType.StepSequencer]: IStepSequencerProps;
65
+ [ModuleType.VoiceScheduler]: IVoiceSchedulerProps;
66
+ };
67
+
68
+ export type ModuleTypeToModuleMapping = {
69
+ [ModuleType.Oscillator]: Oscillator;
70
+ [ModuleType.Gain]: Gain;
71
+ [ModuleType.Master]: Master;
72
+ [ModuleType.MidiSelector]: MidiSelector;
73
+ [ModuleType.Envelope]: Envelope;
74
+ [ModuleType.Filter]: Filter;
75
+ [ModuleType.BiquadFilter]: BiquadFilter;
76
+ [ModuleType.Scale]: Scale;
77
+ [ModuleType.Inspector]: Inspector;
78
+ [ModuleType.Constant]: Constant;
79
+ [ModuleType.VirtualMidi]: VirtualMidi;
80
+ [ModuleType.StepSequencer]: StepSequencer;
81
+ [ModuleType.VoiceScheduler]: VoiceScheduler;
82
+ };
83
+
84
+ export const moduleSchemas: {
85
+ [K in ModuleType]: PropSchema<Partial<ModuleTypeToPropsMapping[K]>>;
86
+ } = {
87
+ [ModuleType.Oscillator]: oscillatorPropSchema,
88
+ [ModuleType.Gain]: gainPropSchema,
89
+ [ModuleType.Master]: masterPropSchema,
90
+ [ModuleType.MidiSelector]: midiSelectorPropSchema,
91
+ [ModuleType.Envelope]: envelopePropSchema,
92
+ [ModuleType.Filter]: filterPropSchema,
93
+ [ModuleType.BiquadFilter]: biquadFilterPropSchema,
94
+ [ModuleType.Scale]: scalePropSchema,
95
+ [ModuleType.Inspector]: inspectorPropSchema,
96
+ [ModuleType.Constant]: constantPropSchema,
97
+ [ModuleType.VirtualMidi]: virtualMidiPropSchema,
98
+ [ModuleType.StepSequencer]: stepSequencerPropSchema,
99
+ [ModuleType.VoiceScheduler]: voiceSchedulerPropSchema,
100
+ };
24
101
 
25
- export {
26
- Envelope,
27
- AmpEnvelope,
28
- FreqEnvelope,
29
- EnvelopeStages,
30
- } from "./Envelope";
102
+ export type { IOscillator } from "./Oscillator";
103
+ export { OscillatorWave } from "./Oscillator";
104
+ export type { IGain } from "./Gain";
105
+ export type { IMaster } from "./Master";
106
+ export type { IMidiSelector } from "./MidiSelector";
107
+ export type {
108
+ IStepSequencer,
109
+ IStepSequencerProps,
110
+ ISequence,
111
+ } from "./StepSequencer";
31
112
 
32
- export interface ICreateModule {
113
+ export type AnyModule = Module<ModuleType>;
114
+ export type IAnyModule = IModule<ModuleType>;
115
+
116
+ export type ICreateModule<T extends ModuleType> = {
33
117
  id?: string;
34
118
  name: string;
35
- numberOfVoices?: number;
36
- type: string;
37
- props: any;
38
- }
119
+ moduleType: T;
120
+ props: Partial<ModuleTypeToPropsMapping[T]>;
121
+ };
39
122
 
40
- export function createModule(params: ICreateModule): AudioModule {
41
- const { id, type, name, props } = params;
42
- const klass = moduleClassFromType(type);
43
-
44
- return new klass({ id, name, props });
45
- }
123
+ export type ModuleParams = {
124
+ [K in ModuleType]: K extends
125
+ | ModuleType.Oscillator
126
+ | ModuleType.Gain
127
+ | ModuleType.Envelope
128
+ | ModuleType.Filter
129
+ | ModuleType.BiquadFilter
130
+ | ModuleType.VoiceScheduler
131
+ ? IPolyModuleConstructor<K>
132
+ : ICreateModule<K>;
133
+ }[ModuleType];
46
134
 
47
- function moduleClassFromType(type: string) {
48
- switch (type) {
49
- case Oscillator.moduleName:
50
- return Oscillator;
51
- case Envelope.moduleName:
52
- return Envelope;
53
- case AmpEnvelope.moduleName:
54
- return AmpEnvelope;
55
- case FreqEnvelope.moduleName:
56
- return FreqEnvelope;
57
- case Filter.moduleName:
58
- return Filter;
59
- case Volume.moduleName:
60
- return Volume;
61
- case Master.moduleName:
62
- return Master;
63
- case VoiceScheduler.moduleName:
64
- return VoiceScheduler;
65
- case MidiSelector.moduleName:
66
- return MidiSelector;
67
- case VirtualMidi.moduleName:
68
- return VirtualMidi;
69
- case Reverb.moduleName:
70
- return Reverb;
71
- case Delay.moduleName:
72
- return Delay;
73
- case Distortion.moduleName:
74
- return Distortion;
75
- case BitCrusher.moduleName:
76
- return BitCrusher;
77
- case Sequencer.moduleName:
78
- return Sequencer;
79
- case LFO.moduleName:
80
- return LFO;
135
+ export function createModule(
136
+ engineId: string,
137
+ params: ModuleParams,
138
+ ): ModuleTypeToModuleMapping[keyof ModuleTypeToModuleMapping] {
139
+ switch (params.moduleType) {
140
+ case ModuleType.Oscillator:
141
+ return new Oscillator(engineId, params);
142
+ case ModuleType.Gain:
143
+ return new Gain(engineId, params);
144
+ case ModuleType.Master:
145
+ return new Master(engineId, params);
146
+ case ModuleType.MidiSelector:
147
+ return new MidiSelector(engineId, params);
148
+ case ModuleType.Envelope:
149
+ return new Envelope(engineId, params);
150
+ case ModuleType.Filter:
151
+ return new Filter(engineId, params);
152
+ case ModuleType.BiquadFilter:
153
+ return new BiquadFilter(engineId, params);
154
+ case ModuleType.Scale:
155
+ return new Scale(engineId, params);
156
+ case ModuleType.Inspector:
157
+ return new Inspector(engineId, params);
158
+ case ModuleType.Constant:
159
+ return new Constant(engineId, params);
160
+ case ModuleType.VirtualMidi:
161
+ return new VirtualMidi(engineId, params);
162
+ case ModuleType.StepSequencer:
163
+ return new StepSequencer(engineId, params);
164
+ case ModuleType.VoiceScheduler:
165
+ return new VoiceScheduler(engineId, params);
81
166
  default:
82
- throw Error(`Unknown module type ${type}`);
167
+ assertNever(params);
83
168
  }
84
169
  }
@@ -0,0 +1,25 @@
1
+ import {
2
+ AudioContext,
3
+ AnalyserNode,
4
+ AudioParam,
5
+ AudioNode,
6
+ AudioWorkletNode,
7
+ BiquadFilterNode,
8
+ GainNode,
9
+ OfflineAudioContext,
10
+ OscillatorNode,
11
+ ConstantSourceNode,
12
+ WaveShaperNode,
13
+ } from "node-web-audio-api";
14
+
15
+ globalThis.AudioContext = AudioContext;
16
+ globalThis.OfflineAudioContext = OfflineAudioContext;
17
+ globalThis.AudioParam = AudioParam;
18
+ globalThis.AudioNode = AudioNode;
19
+ globalThis.AudioWorkletNode = AudioWorkletNode;
20
+ globalThis.AnalyserNode = AnalyserNode;
21
+ globalThis.GainNode = GainNode;
22
+ globalThis.OscillatorNode = OscillatorNode;
23
+ globalThis.BiquadFilterNode = BiquadFilterNode;
24
+ globalThis.ConstantSourceNode = ConstantSourceNode;
25
+ globalThis.WaveShaperNode = WaveShaperNode;
@@ -0,0 +1,82 @@
1
+ export const filterProcessorURL = URL.createObjectURL(
2
+ new Blob(
3
+ [
4
+ "(",
5
+ (() => {
6
+ class FilterProcessor extends AudioWorkletProcessor {
7
+ s0: number;
8
+ s1: number;
9
+
10
+ constructor() {
11
+ super();
12
+ this.s0 = 0;
13
+ this.s1 = 0;
14
+ }
15
+
16
+ static get parameterDescriptors() {
17
+ return [
18
+ {
19
+ name: "cutoff",
20
+ defaultValue: 1000,
21
+ minValue: 20,
22
+ maxValue: 20000,
23
+ },
24
+ {
25
+ name: "resonance",
26
+ defaultValue: 0.0,
27
+ minValue: 0.0,
28
+ maxValue: 4.0,
29
+ },
30
+ ];
31
+ }
32
+
33
+ process(
34
+ inputs: Float32Array[][],
35
+ outputs: Float32Array[][],
36
+ parameters: Record<string, Float32Array>,
37
+ ): boolean {
38
+ const input = inputs[0];
39
+ const output = outputs[0];
40
+
41
+ const cutoff = parameters.cutoff;
42
+ const resonance = parameters.resonance;
43
+
44
+ for (let channelNum = 0; channelNum < input.length; channelNum++) {
45
+ const inputChannel = input[channelNum];
46
+ const outputChannel = output[channelNum];
47
+
48
+ for (let i = 0; i < inputChannel.length; i++) {
49
+ const s = inputChannel[i];
50
+ // Convert Hz to normalized frequency using logarithmic scale
51
+ // This better matches human hearing perception
52
+ const cutoffHz = cutoff.length > 1 ? cutoff[i] : cutoff[0];
53
+ const clampedHz = Math.max(20, Math.min(20000, cutoffHz));
54
+ const normalizedCutoff =
55
+ Math.log(clampedHz / 20) / Math.log(20000 / 20);
56
+ const c = Math.pow(0.5, (1 - normalizedCutoff) / 0.125);
57
+ const r = Math.pow(
58
+ 0.5,
59
+ ((resonance.length > 1 ? resonance[i] : resonance[0]) +
60
+ 0.125) /
61
+ 0.125,
62
+ );
63
+ const mrc = 1 - r * c;
64
+
65
+ this.s0 = mrc * this.s0 - c * this.s1 + c * s;
66
+ this.s1 = mrc * this.s1 + c * this.s0;
67
+
68
+ outputChannel[i] = this.s1;
69
+ }
70
+ }
71
+
72
+ return true;
73
+ }
74
+ }
75
+
76
+ registerProcessor("filter-processor", FilterProcessor);
77
+ }).toString(),
78
+ ")()",
79
+ ],
80
+ { type: "application/javascript" },
81
+ ),
82
+ );
@@ -0,0 +1,28 @@
1
+ import { assertNever } from "@blibliki/utils";
2
+ import { IAnyAudioContext } from "@/core";
3
+ import { filterProcessorURL } from "./filter-processor";
4
+ import { scaleProcessorURL } from "./scale-processor";
5
+
6
+ export enum CustomWorklet {
7
+ ScaleProcessor = "ScaleProcessor",
8
+ FilterProcessor = "FilterProcessor",
9
+ }
10
+
11
+ export async function loadProcessors(context: IAnyAudioContext) {
12
+ await context.audioWorklet.addModule(scaleProcessorURL);
13
+ await context.audioWorklet.addModule(filterProcessorURL);
14
+ }
15
+
16
+ export function newAudioWorklet(
17
+ context: IAnyAudioContext,
18
+ worklet: CustomWorklet,
19
+ ) {
20
+ switch (worklet) {
21
+ case CustomWorklet.ScaleProcessor:
22
+ return new AudioWorkletNode(context, "scale-processor");
23
+ case CustomWorklet.FilterProcessor:
24
+ return new AudioWorkletNode(context, "filter-processor");
25
+ default:
26
+ assertNever(worklet);
27
+ }
28
+ }
@@ -0,0 +1,81 @@
1
+ export const scaleProcessorURL = URL.createObjectURL(
2
+ new Blob(
3
+ [
4
+ "(",
5
+ (() => {
6
+ class ScaleProcessor extends AudioWorkletProcessor {
7
+ static get parameterDescriptors() {
8
+ return [
9
+ {
10
+ name: "min",
11
+ defaultValue: 1e-10,
12
+ },
13
+ {
14
+ name: "max",
15
+ defaultValue: 1,
16
+ },
17
+ {
18
+ name: "current",
19
+ defaultValue: 0.5,
20
+ },
21
+ ];
22
+ }
23
+
24
+ process(
25
+ inputs: Float32Array[][],
26
+ outputs: Float32Array[][],
27
+ parameters: Record<string, Float32Array>,
28
+ ) {
29
+ const input = inputs[0];
30
+ const output = outputs[0];
31
+
32
+ const minValues = parameters.min;
33
+ const maxValues = parameters.max;
34
+ const currentValues = parameters.current;
35
+
36
+ if (!input.length || input[0].length === 0) {
37
+ for (const outputChannel of output) {
38
+ const current =
39
+ parameters.current.length > 1
40
+ ? parameters.current[0]
41
+ : parameters.current[0];
42
+
43
+ outputChannel.fill(current);
44
+ }
45
+
46
+ return true;
47
+ }
48
+
49
+ for (let channel = 0; channel < input.length; channel++) {
50
+ const inputChannel = input[channel];
51
+ const outputChannel = output[channel];
52
+
53
+ for (let i = 0; i < inputChannel.length; i++) {
54
+ const x = inputChannel[i];
55
+
56
+ const min = minValues.length > 1 ? minValues[i] : minValues[0];
57
+ const max = maxValues.length > 1 ? maxValues[i] : maxValues[0];
58
+ const current =
59
+ currentValues.length > 1
60
+ ? currentValues[i]
61
+ : currentValues[0];
62
+
63
+ if (x < 0) {
64
+ outputChannel[i] = current * Math.pow(min / current, -x);
65
+ } else {
66
+ outputChannel[i] = current * Math.pow(max / current, x);
67
+ }
68
+ }
69
+ }
70
+
71
+ return true;
72
+ }
73
+ }
74
+
75
+ registerProcessor("scale-processor", ScaleProcessor);
76
+ }).toString(),
77
+ ")()",
78
+ ],
79
+ { type: "application/javascript" },
80
+ ),
81
+ );