From 0cca2bbd5aec1da33a27a196c5ec8cd5db4fc8e1 Mon Sep 17 00:00:00 2001 From: Steeely Dan Date: Tue, 27 Aug 2024 17:55:51 +0200 Subject: [PATCH] Bump version --- compiler/package-lock.json | 4 ++-- compiler/package.json | 2 +- desktop/package-lock.json | 4 ++-- desktop/package.json | 2 +- gui/package-lock.json | 4 ++-- gui/package.json | 2 +- gui/src/docs/rendered-docs.json | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/package-lock.json b/compiler/package-lock.json index 1c6e78e..73b9422 100644 --- a/compiler/package-lock.json +++ b/compiler/package-lock.json @@ -1,12 +1,12 @@ { "name": "@js2eel/compiler", - "version": "0.10.0", + "version": "0.11.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@js2eel/compiler", - "version": "0.10.0", + "version": "0.11.0", "license": "GPL-3.0", "dependencies": { "acorn": "8.12.1", diff --git a/compiler/package.json b/compiler/package.json index 07f38dc..27bdc68 100644 --- a/compiler/package.json +++ b/compiler/package.json @@ -1,6 +1,6 @@ { "name": "@js2eel/compiler", - "version": "0.10.0", + "version": "0.11.0", "description": "Write REAPER JSFX/EEL2 plugins in JavaScript", "engines": { "node": ">=20.0.0" diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 2708833..c1aa965 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -1,12 +1,12 @@ { "name": "js2eel-desktop", - "version": "0.10.0", + "version": "0.11.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "js2eel-desktop", - "version": "0.10.0", + "version": "0.11.0", "license": "GPL-3.0", "dependencies": { "@js2eel/compiler": "file:../compiler", diff --git a/desktop/package.json b/desktop/package.json index c8a9486..9a8848c 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -1,6 +1,6 @@ { "name": "js2eel-desktop", - "version": "0.10.0", + "version": "0.11.0", "homepage": "https://js2eel.org", "description": "JS2EEL", "engines": { diff --git a/gui/package-lock.json b/gui/package-lock.json index 2fc2046..b9f2515 100644 --- a/gui/package-lock.json +++ b/gui/package-lock.json @@ -1,12 +1,12 @@ { "name": "@js2eel/gui", - "version": "0.10.0", + "version": "0.11.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@js2eel/gui", - "version": "0.10.0", + "version": "0.11.0", "dependencies": { "@codemirror/lang-javascript": "6.2.2", "@codemirror/lang-json": "6.0.1", diff --git a/gui/package.json b/gui/package.json index e7646e1..ee44eb8 100644 --- a/gui/package.json +++ b/gui/package.json @@ -1,7 +1,7 @@ { "name": "@js2eel/gui", "private": true, - "version": "0.10.0", + "version": "0.11.0", "engines": { "node": ">=20.0.0" }, diff --git a/gui/src/docs/rendered-docs.json b/gui/src/docs/rendered-docs.json index 9a311d6..d6d510b 100644 --- a/gui/src/docs/rendered-docs.json +++ b/gui/src/docs/rendered-docs.json @@ -1,8 +1,8 @@ { "api-documentation": "

API Documentation

\n\n

Configuration

\n

config()

\n

Configures the plugin.

\n
config({\n    description,\n    inChannels,\n    outChannels,\n    extTailSize\n}: {\n    description: number;\n    inChannels: number;\n    outChannels: number;\n    extTailSize?: number;\n}): void;\n
\n

Example:

\n
config({ description: 'volume', inChannels: 2, outChannels: 2 });\n
\n

slider()

\n

Registers a slider and its bound variable to be displayed in the plugin.

\n
slider(\n    sliderNumber: number,\n    variable: number,\n    initialValue: number,\n    min: number,\n    max: number,\n    step: number,\n    label: string\n): void;\n
\n

Example:

\n
slider(1, volume, 0, -150, 18, 0.1, 'Volume [dB]');\n
\n

selectBox()

\n

Registers a select box and its bound variable to be displayed in the plugin.

\n
selectBox(\n    sliderNumber: number,\n    variable: string,\n    initialValue: string,\n    values: { name: string; label: string }[],\n    label: string\n): void;\n
\n

Example:

\n
selectBox(\n    3,\n    algorithm,\n    'sigmoid',\n    [\n        { name: 'sigmoid', label: 'Sigmoid' },\n        { name: 'htan', label: 'Hyperbolic Tangent' },\n        { name: 'hclip', label: 'Hard Clip' }\n    ],\n    'Algorithm'\n);\n
\n

fileSelector()

\n

Registers a file selector to be displayed in the plugin.

\n

The path is relative to /data.

\n
fileSelector(\n    sliderNumber: number,\n    variable: string,\n    path: string,\n    defaultValue: string,\n    label: string\n): void;\n
\n

Example:

\n
fileSelector(\n    5,\n    ampModel,\n    'amp_models',\n    'none',\n    'Impulse Response'\n);\n
\n

Debugging

\n

console

\n

JS2EEL only supports the .log() method.\nconsole.log() creates a debug variable to print the value of a variable in the JSFX dev environment.

\n
console: {\n    log: (someVar: number | string) => void;\n};\n
\n

Example:

\n
let myVal = 3;\nconsole.log(myVal);\n
\n

JSFX Computation Stages

\n

These functions correspond to JSFX's @sample etc.

\n

onInit()

\n

Init variables and functions here.

\n
onInit(callback: () => void): void;\n
\n

onSlider()

\n

What happens when a slider is moved.

\n
onSlider(callback: () => void): void;\n
\n

onBlock()

\n

Called for every audio block.

\n
onBlock(callback: () => void): void;\n
\n

onSample()

\n

Called for every single sample.

\n
onSample(callback: () => void): void;\n
\n

eachChannel()

\n

Iterates over each channel and provides the current sample for manipulation.

\n
eachChannel(callback: (sample: number, channel: number) => void): void;\n
\n

Data Structures

\n

EelBuffer

\n

A fixed-size, multi-dimensional container for audio samples.

\n

Access: buf[dimension][position]

\n

Translates to EEL2s memory objects. Is not inlined in the EEL source, so\nonly feasible for large data. For small data, use EelArray.

\n
EelBuffer {\n    constructor(dimensions: number, size: number);\n\n    dimensions(): number;\n    size(): number;\n    start(): number;\n}\n
\n

EelArray

\n

A fixed-size, multi-dimensional container for numeric data.

\n

Access: arr[dimension][position]

\n

Is inlined in the EEL source, dimensions and size are restricted to 16 each. For large data,\nuse EelBuffer.

\n
EelArray {\n    constructor(dimensions: number, size: number);\n\n    dimensions(): number;\n    size(): number;\n}\n
\n

Audio Constants

\n

srate

\n

The sample rate of your project

\n
srate: number;\n
\n

num_ch

\n

Number of channels available

\n
num_ch: number;\n
\n

samplesblock

\n

How many samples will come before the next onBlock() call

\n
samplesblock: number;\n
\n

tempo

\n

The tempo of your project

\n
tempo: number;\n
\n

play_state

\n

The current playback state of REAPER (0=stopped, <0=error, 1=playing, 2=paused, 5=recording, 6=record paused)

\n
play_state: number;\n
\n

play_position

\n

The current playback position in REAPER (as of last @block), in seconds

\n
play_position: number;\n
\n

beat_position

\n

Read-only. The current playback position (as of last @block) in REAPER, in beats (beats = quarternotes in /4 time signatures).

\n
beat_position: number;\n
\n

ts_num

\n

Read-only. The current time signature numerator, i.e. 3.0 if using 3/4 time.

\n
ts_num: number;\n
\n

ts_denom

\n

Read-only. The current time signature denominator, i.e. 4.0 if using 3/4 time.

\n
ts_denom: number;\n
\n

spl<1-64>

\n

Channel 1 (L) sample variable

\n
spl0: number;\n
\n

Math Constants

\n

$pi

\n

Pi

\n
$pi: number;\n
\n

Math Functions

\n

These functions correspond exactly to their equivalents in JSFX/EEL2.

\n

sin()

\n

Returns the Sine of the angle specified (specified in radians).

\n
sin(angle: number): number;\n
\n

cos()

\n

Returns the Cosine of the angle specified (specified in radians).

\n
cos(angle: number): number;\n
\n

tan()

\n

Returns the Tangent of the angle specified (specified in radians).

\n
tan(angle: number): number;\n
\n

asin()

\n

Returns the Arc Sine of the value specified (return value is in radians).

\n
asin(x: number): number;\n
\n

acos()

\n

Returns the Arc Cosine of the value specified (return value is in radians).

\n
acos(x: number): number;\n
\n

atan()

\n

Returns the Arc Tangent of the value specified (return value is in radians).

\n
atan(x: number): number;\n
\n

atan2()

\n

Returns the Arc Tangent of x divided by y (return value is in radians).

\n
atan2(x: number, y: number): number;\n
\n

sqr()

\n

Returns the square of the parameter (similar to x*x, though only evaluating x once).

\n
sqr(x: number): number;\n
\n

sqrt()

\n

Returns the square root of the parameter.

\n
sqrt(x: number): number;\n
\n

pow()

\n

Returns the first parameter raised to the second parameter-th power.\nIdentical in behavior and performance to the ^ operator.

\n
pow(x: number, y: number): number;\n
\n

exp()

\n

Returns the number e (approx 2.718) raised to the parameter-th power.\nThis function is significantly faster than pow() or the ^ operator.

\n
exp(x: number): number;\n
\n

log()

\n

Returns the natural logarithm (base e) of the parameter.

\n
log(x: number): number;\n
\n

log10()

\n

Returns the logarithm (base 10) of the parameter.

\n
log10(x: number): number;\n
\n

abs()

\n

Returns the absolute value of the parameter.

\n
abs(x: number): number;\n
\n

min()

\n

Returns the minimum value of the two parameters.

\n
min(x: number, y: number): number;\n
\n

max()

\n

Returns the maximum value of the two parameters.

\n
max(x: number, y: number): number;\n
\n

sign()

\n

Returns the sign of the parameter (-1, 0, or 1).

\n
sign(x: number): number;\n
\n

rand()

\n

Returns a pseudo-random number between 0 and the parameter.

\n
rand(x: number): number;\n
\n

floor()

\n

Rounds the value to the lowest integer possible (floor(3.9)==3, floor(-3.1)==-4).

\n
floor(x: number): number;\n
\n

ceil()

\n

Rounds the value to the highest integer possible (ceil(3.1)==4, ceil(-3.9)==-3).

\n
ceil(x: number): number;\n
\n

invsqrt()

\n

Returns a fast inverse square root (1/sqrt(x)) approximation of the parameter.

\n
invsqrt(x: number): number;\n
\n

Memory Functions

\n

memset()

\n
memset(): void;\n
\n

File Functions

\n

file_open()

\n

Opens a file from a file slider. Once open, you may use all of the file functions available. Be sure to close the file handle when done with it, using file_close(). The search path for finding files depends on the method used, but generally speaking in 4.59+ it will look in the same path as the current effect, then in the JS Data/ directory.

\n

@param fileSelector A variable that is bound to the respective file selector. Will be compiled to sliderXY. FIXME types

\n
file_open(fileSelector: any): number;\n
\n

file_close()

\n

Closes a file opened with file_open().

\n
file_close(fileHandle: any): void;\n
\n

file_avail()

\n

Returns the number of items remaining in the file, if it is in read mode. Returns < 0 if in write mode. If the file is in text mode (file_text(handle) returns TRUE), then the return value is simply 0 if EOF, 1 if not EOF.

\n
file_avail(fileSelector: any): number;\n
\n

file_riff()

\n

If the file was a media file (.wav, .ogg, etc), this will set the first parameter to the number of channels, and the second to the samplerate.

\n

REAPER 6.29+: if the caller sets nch to 'rqsr' and samplerate to a valid samplerate, the file will be resampled to the desired samplerate (this must ONLY be called before any file_var() or file_mem() calls and will change the value returned by file_avail())

\n
file_riff(fileHandle: any, numberOfCh: number, sampleRate: number): void;\n
\n

file_mem()

\n

Reads (or writes) the block of local memory from(to) the current file. Returns the actual number of items read (or written).

\n
file_mem(fileHandle: any, offset: number, length: number): number;\n
\n

FFT & MDCT Functions

\n

fft()

\n

Performs a FFT (or inverse in the case of ifft()) on the data in the local memory buffer at the offset specified by the first parameter. The size of the FFT is specified by the second parameter, which must be 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, or 32768. The outputs are permuted, so if you plan to use them in-order, call fft_permute(buffer, size) before and fft_ipermute(buffer,size) after your in-order use. Your inputs or outputs will need to be scaled down by 1/size, if used.

\n

Note that the FFT/IFFT require real/imaginary input pairs (so a 256 point FFT actually works with 512 items).

\n

Note that the FFT/IFFT must NOT cross a 65,536 item boundary, so be sure to specify the offset accordingly.

\n

The fft_real()/ifft_real() variants operate on a set of size real inputs, and produce size/2 complex outputs. The first output pair is DC,nyquist. Normally this is used with fft_permute(buffer,size/2).

\n
fft(startIndex: number, size: number): void;\n
\n

ifft()

\n

Performs a FFT (or inverse in the case of ifft()) on the data in the local memory buffer at the offset specified by the first parameter. The size of the FFT is specified by the second parameter, which must be 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, or 32768. The outputs are permuted, so if you plan to use them in-order, call fft_permute(buffer, size) before and fft_ipermute(buffer,size) after your in-order use. Your inputs or outputs will need to be scaled down by 1/size, if used.

\n

Note that the FFT/IFFT require real/imaginary input pairs (so a 256 point FFT actually works with 512 items).

\n

Note that the FFT/IFFT must NOT cross a 65,536 item boundary, so be sure to specify the offset accordingly.

\n

The fft_real()/ifft_real() variants operate on a set of size real inputs, and produce size/2 complex outputs. The first output pair is DC,nyquist. Normally this is used with fft_permute(buffer,size/2).

\n
ifft(startIndex: number, size: number): void;\n
\n

convolve_c()

\n

Used to convolve two buffers, typically after FFTing them. convolve_c works with complex numbers. The sizes specify number of items (the number of complex number pairs).

\n

Note that the convolution must NOT cross a 65,536 item boundary, so be sure to specify the offset accordingly.

\n
convolve_c(destination: number, source: number, size: number): void;\n
\n", - "changelog": "

Changelog

\n\n", + "changelog": "

Changelog

\n\n", "development": "

Development

\n

Requirements

\n\n

Setup

\n\n

Guidelines

\n\n

Architecture

\n

TODO

\n

Recommended VSCode Extensions

\n

TODO

\n", - "feature-comparison": "

Feature Comparison with JSFX

\n

JSFX Reference: https://www.reaper.fm/sdk/js/js.php

\n

Find the JS2EEL type declarations here. The API Docs are created from that file, as well as the code completion.

\n

✅: Implemented

\n

🕒: Should be implemented

\n

❌: Won't be implemented

\n

❔: Unknown if feasible, useful, or working properly

\n

Description Lines and Utility Features

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
descImplemented as part of config()
🕒tags
🕒options
🕒JSFX comments
\n

Code Sections

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
@initonInit()
@slideronSlider()
🕒@block
@sampleonSample()
🕒@serialize
🕒@gfxDeclarative with React-like syntax?
\n

File Handling

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒import
🕒filename
file_open(index | slider)Slider variant implemented
file_close(handle)
🕒file_rewind(handle)
🕒file_var(handle, variable)
file_mem(handle, offset, length)
file_avail(handle)
file_riff(handle, nch, samplerate)
🕒file_text(handle, istext)
🕒file_string(handle,str)
\n

Routing and Input

\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
in_pin, out_pinImplemented as part of config()
\n

UI

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
Slider: Normalslider()
Slider: SelectselectBox()
Slider: File
🕒Hidden sliders
🕒Slider: shapes
slider(index)Might not be necessary as every slider is bound to a variable
🕒slider_next_chg(sliderindex,nextval)
\n

Sample Access

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
spl0 - spl63
spl(index)
\n

Audio and Transport State Vars

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
srate
num_ch
samplesblock
tempo
play_state
play_position
beat_position
ts_num
ts_denom
\n

Data Structures and Encodings

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
Local variableslet & const
Local address space (buffers)EelBuffer (equivalent to JSFX buffers) & EelArray (inlined)
Local address space 8m word restriction
🕒Global address space (gmem[])
🕒Named global address space
Global named variables (_global. prefix)
🕒Hex numbers
🕒ASCII chars
🕒Bitmasks
StringsAlready fully implemented?
\n

Control Structures

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
FunctionsUser definable functions are inlined in compiled code
Conditionals
Conditional Branching
🕒loop(counter, actions...)We should have generic loops even if sample- and channel related iterations should be handled by eachChannel()
🕒while(actions..., condition)
🕒while(condition) (actions...)
\n

Operators

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
!value
-value
+value
base ^ exponentMath.pow(base, exponent) or **
numerator % denominator
value / divisor
value * another_value
value - another_value
value + another_value
value1 == value2Has a tolerance of 0.00001. We only allow ===
value1 === value2
value1 != value2Has a tolerance of 0.00001. We only allow ===
value1 !== value2
value1 < value2
value1 > value2
value1 <= value2
value1 >= value2
y || z
y && z
y ? z
y ? z : x
y = z
y *= z
y /= divisor
y %= divisor
🕒base ^= exponentShould be implemented as JavaScript's **=
y += z
y -= z
\n

Bitwise operators

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒value << shift_amt
🕒value >> shift_amt
🕒a | b
🕒a & b
🕒a ~ b
🕒y | = z
🕒y &= z
🕒y ~= z
\n

Math Functions

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
sin(angle)
cos(angle)
tan(angle)
asin(x)
acos(x)
atan(x)
atan2(x, y)
sqr(x)
sqrt(x)
pow(x, y)
exp(x)
log(x)
log10(x)
abs(x)
min(x, y)
max(x, y)
sign(x)
rand(x)
floor(x)
ceil(x)
invsqrt(x)
\n

Time Functions

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒time([v])
🕒time_precise([v])
\n

Midi Functions

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒midisend(offset, msg1, msg2)
🕒midisend(offset, msg1, msg2 + (msg3 * 256))
🕒midisend(offset, msg1, msg2, msg3)
🕒midisend_buf(offset, buf, len)
🕒midisend_str(offset, string)
🕒midirecv(offset, msg1, msg23)
🕒midirecv(offset, msg1, msg2, msg3)
🕒midirecv_buf(offset, buf, maxlen)
🕒midirecv_str(offset, string)
🕒midisyx(offset, msgptr, len)
\n

Memory/FFT/MDCT Functions

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒mdct(start_index, size)
🕒imdct(start_index, size)
🕒fft(start_index, size)
🕒ifft(start_index, size)
🕒fft_real(start_index, size)
🕒ifft_real(start_index, size)
🕒fft_permute(index, size)
🕒fft_ipermute(index, size)
🕒convolve_c(dest, src, size)
🕒freembuf(top)
🕒memcpy(dest, source, length)
🕒memset(dest, value, length)
🕒mem_multiply_sum(buf1, buf2, length)
🕒mem_insert_shuffle(buf, len, value)
🕒__memtop()
🕒stack_push(value)
🕒stack_pop(value)
🕒stack_peek(index)
🕒stack_exch(value)
🕒atomic_setifequal(dest, value, newvalue)
🕒atomic_exch(val1, val2)
🕒atomic_add(dest_val1, val2)
🕒atomic_set(dest_val1, val2)
🕒atomic_get(val)
\n

Host Interaction Functions

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒sliderchange(mask | sliderX)
🕒slider_automate(mask or sliderX[, end_touch])
🕒slider_show(mask or sliderX[, value])
🕒export_buffer_to_project(buffer, length_samples, nch, srate, track_index[, flags, tempo, planar_pitch]) --
🕒get_host_numchan()
🕒set_host_numchan(numchan)
🕒get_pin_mapping(inout, pin, startchan, chanmask)
🕒set_pin_mapping(inout, pin, startchan, chanmask, mapping)
🕒get_pinmapper_flags(no parameters)
🕒set_pinmapper_flags(flags)
🕒get_host_placement([chain_pos, flags])
\n

String Functions

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒strlen(str)
🕒strcpy(str, srcstr)
🕒strcat(str, srcstr)
🕒strcmp(str, str2)
🕒stricmp(str, str2)
🕒strncmp(str, str2, maxlen)
🕒strnicmp(str, str2, maxlen)
🕒strncpy(str, srcstr, maxlen)
🕒strncat(str, srcstr, maxlen)
🕒strcpy_from(str, srcstr, offset)
🕒strcpy_substr(str, srcstr, offset, maxlen)
🕒str_getchar(str, offset[, type])
🕒str_setchar(str, offset, value[, type])
🕒strcpy_fromslider(str, slider)
🕒sprintf(str, format, ...)
🕒match(needle, haystack, ...)
🕒matchi(needle, haystack, ...)
\n

GFX Functions

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒gfx_set(r[g, b, a, mode, dest])
🕒gfx_lineto(x, y, aa)
🕒gfx_line(x, y, x2, y2[, aa])
🕒gfx_rectto(x, y)
🕒gfx_rect(x, y, w, h)
🕒gfx_setpixel(r, g, b)
🕒gfx_getpixel(r, g, b)
🕒gfx_drawnumber(n, ndigits)
🕒gfx_drawchar($'c')
🕒gfx_drawstr(str[, flags, right, bottom])
🕒gfx_measurestr(str, w, h)
🕒gfx_setfont(idx[, fontface, sz, flags])
🕒gfx_getfont()
🕒gfx_printf(str, ...)
🕒gfx_blurto(x,y)
🕒gfx_blit(source, scale, rotation)
🕒gfx_blit(source, scale, rotation[, srcx, srcy, srcw, srch, destx, desty, destw, desth, rotxoffs, rotyoffs])
🕒gfx_blitext(source, coordinatelist, rotation)
🕒gfx_getimgdim(image, w, h)
🕒gfx_setimgdim(image, w,h)
🕒gfx_loadimg(image, filename)
🕒gfx_gradrect(x,y,w,h, r,g,b,a[, drdx, dgdx, dbdx, dadx, drdy, dgdy, dbdy, dady])
🕒gfx_muladdrect(x,y,w,h, mul_r, mul_g, mul_b[, mul_a, add_r, add_g, add_b, add_a])
🕒gfx_deltablit(srcimg,srcx,srcy,srcw,srch, destx, desty, destw, desth, dsdx, dtdx, dsdy, dtdy, dsdxdy, dtdxdy[, usecliprect=1] )
🕒gfx_transformblit(srcimg, destx, desty, destw, desth, div_w, div_h, table)
🕒gfx_circle(x,y,r[,fill,antialias])
🕒gfx_roundrect(x,y,w,h,radius[,antialias])
🕒gfx_arc(x,y,r, ang1, ang2[,antialias])
🕒gfx_triangle(x1,y1,x2,y2,x3,y3[,x4,y4,...])
🕒gfx_getchar([char, unicodechar])
🕒gfx_showmenu("str")
🕒gfx_setcursor(resource_id[,"custom cursor name"])
\n

GFX Vars

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒gfx_r, gfx_g, gfx_b, gfx_a
🕒gfx_w, gfx_h
🕒gfx_x, gfx_y
🕒gfx_mode
🕒gfx_clear
🕒gfx_dest
🕒gfx_texth
🕒gfx_ext_retina
🕒gfx_ext_flags
🕒mouse_x, mouse_y
🕒mouse_cap
🕒mouse_wheel, mouse_hwheel
\n

Special Vars and Extended Functionality

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒trigger
🕒ext_noinit
🕒ext_nodenorm
ext_tail_size
🕒reg00-reg99
🕒_global.*
\n

Delay Compensation Vars

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒pdc_delay
🕒pdc_bot_ch
🕒pdc_top_ch
🕒pdc_midi
\n", + "feature-comparison": "

Feature Comparison with JSFX

\n

JSFX Reference: https://www.reaper.fm/sdk/js/js.php

\n

Find the JS2EEL type declarations here. The API Docs are created from that file, as well as the code completion.

\n

✅: Implemented

\n

🕒: Should be implemented

\n

❌: Won't be implemented

\n

❔: Unknown if feasible, useful, or working properly

\n

Description Lines and Utility Features

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
descImplemented as part of config()
🕒tags
🕒options
🕒JSFX comments
\n

Code Sections

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
@initonInit()
@slideronSlider()
@block
@sampleonSample()
🕒@serialize
🕒@gfxDeclarative with React-like syntax?
\n

File Handling

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒import
🕒filename
file_open(index | slider)Slider variant implemented
file_close(handle)
🕒file_rewind(handle)
🕒file_var(handle, variable)
file_mem(handle, offset, length)
file_avail(handle)
file_riff(handle, nch, samplerate)
🕒file_text(handle, istext)
🕒file_string(handle,str)
\n

Routing and Input

\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
in_pin, out_pinImplemented as part of config()
\n

UI

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
Slider: Normalslider()
Slider: SelectselectBox()
Slider: File
🕒Hidden sliders
🕒Slider: shapes
slider(index)Might not be necessary as every slider is bound to a variable
🕒slider_next_chg(sliderindex,nextval)
\n

Sample Access

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
spl0 - spl63
spl(index)
\n

Audio and Transport State Vars

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
srate
num_ch
samplesblock
tempo
play_state
play_position
beat_position
ts_num
ts_denom
\n

Data Structures and Encodings

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
Local variableslet & const
Local address space (buffers)EelBuffer (equivalent to JSFX buffers) & EelArray (inlined)
Local address space 8m word restriction
🕒Global address space (gmem[])
🕒Named global address space
Global named variables (_global. prefix)
🕒Hex numbers
🕒ASCII chars
🕒Bitmasks
StringsAlready fully implemented?
\n

Control Structures

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
FunctionsUser definable functions are inlined in compiled code
Conditionals
Conditional Branching
🕒loop(counter, actions...)We should have generic loops even if sample- and channel related iterations should be handled by eachChannel()
🕒while(actions..., condition)
while(condition) (actions...)
\n

Operators

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
!value
-value
+value
base ^ exponentMath.pow(base, exponent) or **
numerator % denominator
value / divisor
value * another_value
value - another_value
value + another_value
value1 == value2Has a tolerance of 0.00001. We only allow ===
value1 === value2
value1 != value2Has a tolerance of 0.00001. We only allow ===
value1 !== value2
value1 < value2
value1 > value2
value1 <= value2
value1 >= value2
y || z
y && z
y ? z
y ? z : x
y = z
y *= z
y /= divisor
y %= divisor
🕒base ^= exponentShould be implemented as JavaScript's **=
y += z
y -= z
\n

Bitwise operators

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒value << shift_amt
🕒value >> shift_amt
🕒a | b
🕒a & b
🕒a ~ b
🕒y | = z
🕒y &= z
🕒y ~= z
\n

Math Functions

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
sin(angle)
cos(angle)
tan(angle)
asin(x)
acos(x)
atan(x)
atan2(x, y)
sqr(x)
sqrt(x)
pow(x, y)
exp(x)
log(x)
log10(x)
abs(x)
min(x, y)
max(x, y)
sign(x)
rand(x)
floor(x)
ceil(x)
invsqrt(x)
\n

Time Functions

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒time([v])
🕒time_precise([v])
\n

Midi Functions

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒midisend(offset, msg1, msg2)
🕒midisend(offset, msg1, msg2 + (msg3 * 256))
🕒midisend(offset, msg1, msg2, msg3)
🕒midisend_buf(offset, buf, len)
🕒midisend_str(offset, string)
🕒midirecv(offset, msg1, msg23)
🕒midirecv(offset, msg1, msg2, msg3)
🕒midirecv_buf(offset, buf, maxlen)
🕒midirecv_str(offset, string)
🕒midisyx(offset, msgptr, len)
\n

Memory/FFT/MDCT Functions

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒mdct(start_index, size)
🕒imdct(start_index, size)
fft(start_index, size)
ifft(start_index, size)
🕒fft_real(start_index, size)
🕒ifft_real(start_index, size)
🕒fft_permute(index, size)
🕒fft_ipermute(index, size)
convolve_c(dest, src, size)
🕒freembuf(top)
🕒memcpy(dest, source, length)
memset(dest, value, length)
🕒mem_multiply_sum(buf1, buf2, length)
🕒mem_insert_shuffle(buf, len, value)
🕒__memtop()
🕒stack_push(value)
🕒stack_pop(value)
🕒stack_peek(index)
🕒stack_exch(value)
🕒atomic_setifequal(dest, value, newvalue)
🕒atomic_exch(val1, val2)
🕒atomic_add(dest_val1, val2)
🕒atomic_set(dest_val1, val2)
🕒atomic_get(val)
\n

Host Interaction Functions

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒sliderchange(mask | sliderX)
🕒slider_automate(mask or sliderX[, end_touch])
🕒slider_show(mask or sliderX[, value])
🕒export_buffer_to_project(buffer, length_samples, nch, srate, track_index[, flags, tempo, planar_pitch]) --
🕒get_host_numchan()
🕒set_host_numchan(numchan)
🕒get_pin_mapping(inout, pin, startchan, chanmask)
🕒set_pin_mapping(inout, pin, startchan, chanmask, mapping)
🕒get_pinmapper_flags(no parameters)
🕒set_pinmapper_flags(flags)
🕒get_host_placement([chain_pos, flags])
\n

String Functions

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒strlen(str)
🕒strcpy(str, srcstr)
🕒strcat(str, srcstr)
🕒strcmp(str, str2)
🕒stricmp(str, str2)
🕒strncmp(str, str2, maxlen)
🕒strnicmp(str, str2, maxlen)
🕒strncpy(str, srcstr, maxlen)
🕒strncat(str, srcstr, maxlen)
🕒strcpy_from(str, srcstr, offset)
🕒strcpy_substr(str, srcstr, offset, maxlen)
🕒str_getchar(str, offset[, type])
🕒str_setchar(str, offset, value[, type])
🕒strcpy_fromslider(str, slider)
🕒sprintf(str, format, ...)
🕒match(needle, haystack, ...)
🕒matchi(needle, haystack, ...)
\n

GFX Functions

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒gfx_set(r[g, b, a, mode, dest])
🕒gfx_lineto(x, y, aa)
🕒gfx_line(x, y, x2, y2[, aa])
🕒gfx_rectto(x, y)
🕒gfx_rect(x, y, w, h)
🕒gfx_setpixel(r, g, b)
🕒gfx_getpixel(r, g, b)
🕒gfx_drawnumber(n, ndigits)
🕒gfx_drawchar($'c')
🕒gfx_drawstr(str[, flags, right, bottom])
🕒gfx_measurestr(str, w, h)
🕒gfx_setfont(idx[, fontface, sz, flags])
🕒gfx_getfont()
🕒gfx_printf(str, ...)
🕒gfx_blurto(x,y)
🕒gfx_blit(source, scale, rotation)
🕒gfx_blit(source, scale, rotation[, srcx, srcy, srcw, srch, destx, desty, destw, desth, rotxoffs, rotyoffs])
🕒gfx_blitext(source, coordinatelist, rotation)
🕒gfx_getimgdim(image, w, h)
🕒gfx_setimgdim(image, w,h)
🕒gfx_loadimg(image, filename)
🕒gfx_gradrect(x,y,w,h, r,g,b,a[, drdx, dgdx, dbdx, dadx, drdy, dgdy, dbdy, dady])
🕒gfx_muladdrect(x,y,w,h, mul_r, mul_g, mul_b[, mul_a, add_r, add_g, add_b, add_a])
🕒gfx_deltablit(srcimg,srcx,srcy,srcw,srch, destx, desty, destw, desth, dsdx, dtdx, dsdy, dtdy, dsdxdy, dtdxdy[, usecliprect=1] )
🕒gfx_transformblit(srcimg, destx, desty, destw, desth, div_w, div_h, table)
🕒gfx_circle(x,y,r[,fill,antialias])
🕒gfx_roundrect(x,y,w,h,radius[,antialias])
🕒gfx_arc(x,y,r, ang1, ang2[,antialias])
🕒gfx_triangle(x1,y1,x2,y2,x3,y3[,x4,y4,...])
🕒gfx_getchar([char, unicodechar])
🕒gfx_showmenu("str")
🕒gfx_setcursor(resource_id[,"custom cursor name"])
\n

GFX Vars

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒gfx_r, gfx_g, gfx_b, gfx_a
🕒gfx_w, gfx_h
🕒gfx_x, gfx_y
🕒gfx_mode
🕒gfx_clear
🕒gfx_dest
🕒gfx_texth
🕒gfx_ext_retina
🕒gfx_ext_flags
🕒mouse_x, mouse_y
🕒mouse_cap
🕒mouse_wheel, mouse_hwheel
\n

Special Vars and Extended Functionality

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒trigger
🕒ext_noinit
🕒ext_nodenorm
ext_tail_size
🕒reg00-reg99
🕒_global.*
\n

Delay Compensation Vars

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusFeatureComment
🕒pdc_delay
🕒pdc_bot_ch
🕒pdc_top_ch
🕒pdc_midi
\n", "getting-started": "

Getting Started: Your First JS2EEL Plugin

\n

Let's create our first JS2EEL plugin. We'll write it in JavaScript. JS2EEL will compile it into a REAPER JSFX plugin that you can use instantly.

\n

Our plugin will take an input audio signal and modify its volume. If you'd like to see the finished plugin, feel free to load the example plugin volume.js.

\n

Step 1: Create a New File

\n

Click on the "New File" button in the upper left half of the window.

\n

A modal will appear where you have to enter a filename for the JavaScript code and a description that will be used to reference the JSFX plugin in REAPER. Let's start with the same value for both: volume.

\n

As you create the new file, the JS code tab will be pre-populated with a minimal template. There will be a call to the config() function, where the name and the channel configuration of the plugin is defined:

\n
config({ description: 'volume', inChannels: 2, outChannels: 2 });\n
\n

Take a look at the resulting JSFX code on the right. If you're familiar with JSFX, you'll meet some old friends here: desc: and the in_pin and out_pin configuration for your plugin's channel routing.

\n

Additionally, a template for the onSample() function call is provided. This is a JS2EEL library function that iterates through every sample of the audio block and allows you to modify it. This corresponds to the @sample part in JSFX.

\n

Step 2: Declare Volume Adjustment Holder Variables

\n

Next, we will create variables to hold the current volume level and the target volume level. Between config() and onSample(), add the following code:

\n
let volume = 0;\nlet target = 0;\n
\n

volume represents the volume in dB, and target represents the target volume in linear scale.

\n

Step 3: Create a Slider for User Input

\n

To allow the user to adjust the volume, we'll use a slider. We'll bind that slider to the volume variable created above. After the variable declarations, add the following code to your file:

\n
slider(1, volume, 0, -150, 18, 0.1, 'Volume [dB]');\n
\n

As you might know, slider numbering is important in EEL. It starts at 1, and so our slider takes 1 as the first argument.

\n

The second argument is the variable to bind to: volume.

\n

The third argument is the default value: 0.

\n

The fourth and fifth arguments are the minimum and maximum values: -150 and 18 dB, respectively.

\n

The sixth argument is the step size: 0.1.

\n

The last argument is the label for the slider which will be displayed in the GUI: Volume [dB].

\n

Step 4: Handle Slider Value Changes

\n

Now, we need to update the target variable whenever the user adjusts the slider. We'll use the onSlider() library function to handle slider value changes. This corresponds to EEL's @slider. After the slider definition via slider(), add the following code to your file:

\n
onSlider(() => {\n    if (volume > -149.9) {\n        target = Math.pow(10, volume / 20);\n    } else {\n        target = 0;\n    }\n});\n
\n

Here we assign a linear target level to the target variable, which will be used later to adjust our sample amplitude. If the slider is at its lower boundary, we set the target to 0 to mute the audio.

\n

Step 5: Process Audio Samples

\n

The final step is to process audio samples based on the calculated target volume. We'll use the onSample() function to perform audio processing. This corresponds to EEL's @sample. In the callback arrow function parameter of onSample(), add the following code:

\n
eachChannel((sample, _ch) => {\n    sample *= target;\n});\n
\n

eachChannel() is another JS2EEL library function that makes it easy to manipulate samples per channel. It can only be called in onSample. It has no equivalent in EEL. We just multiply every sample in each of the two channels by the target volume to adjust its amplitude respectively.

\n

Finished Plugin

\n

Here is the complete code:

\n
config({ description: 'volume', inChannels: 2, outChannels: 2 });\n\nlet volume = 0;\nlet target = 0;\n\nslider(1, volume, 0, -150, 18, 0.1, 'Volume [dB]');\n\nonSlider(() => {\n    if (volume > -149.9) {\n        target = Math.pow(10, volume / 20);\n    } else {\n        target = 0;\n    }\n});\n\nonSample(() => {\n    eachChannel((sample, _ch) => {\n        sample *= target;\n    });\n});\n
\n

Conclusion

\n

That's it! You've successfully created a simple volume plugin using JS2EEL. If you're using the web app version of JS2EEL, copy the JSFX code into a new JSFX in REAPER to hear it in action. If you're using the desktop app and have configured the output path correctly, your volume JSFX should appear in the JS subdirectory of the FX selector.

\n

Feel free to take a look at the other examples. You'll be inspired to write your own JS2EEL plugin in no time!

\n", "limitations": "

Limitations

\n\n

Accessing Arrays

\n\n

TODO

\n", "shortcuts": "

Keyboard Shortcuts

\n

Editor

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Linux & WindowsMacDescription
Ctrl + SCmd + SSave
Ctrl + ICmd + IAutoformat
Ctrl + /Cmd + /Toggle line comment(s)
Alt + Up/DownAlt + Up/DownMove line(s) up/down
Ctrl + DCmd + DSelect next symbol occurence
Ctrl + FCmd + FOpen search panel
\n",