### Start GUI Development Server Source: https://github.com/steeelydan/js2eel/blob/main/docs/development.md Navigate to the GUI directory and run this command to start the development server for the graphical user interface. ```shell cd gui npm run dev ``` -------------------------------- ### Start Compiler Development Server Source: https://github.com/steeelydan/js2eel/blob/main/docs/development.md Navigate to the compiler directory and run this command to start the development server for the compiler. ```shell cd compiler npm run dev ``` -------------------------------- ### Install Dependencies Script Source: https://github.com/steeelydan/js2eel/blob/main/docs/development.md Run this shell script to install all necessary project dependencies. ```shell cd scripts ./install.sh ``` -------------------------------- ### Start Desktop Development Server Source: https://github.com/steeelydan/js2eel/blob/main/docs/development.md Navigate to the desktop directory and run this command to start the development server for the desktop application. This will also launch the Electron build. ```shell cd desktop npm run dev ``` -------------------------------- ### Initialize Plugin Variables with onInit Source: https://context7.com/steeelydan/js2eel/llms.txt Use onInit to perform one-time setup tasks like variable initialization or buffer allocation when the plugin loads. ```javascript config({ description: 'init_example', inChannels: 2, outChannels: 2 }); let coefficient; let buffer = new EelBuffer(2, 1024); onInit(() => { coefficient = 0.5; // Initialize buffer values let i = 0; while (i < 1024) { buffer[0][i] = 0; buffer[1][i] = 0; i += 1; } }); ``` -------------------------------- ### Show Menu with String Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Use `gfx_showmenu` to display a menu with a given string. No specific setup is required beyond the function call. ```javascript gfx_showmenu("str") ``` -------------------------------- ### Complete Stereo Delay Plugin with JS2EEL Source: https://context7.com/steeelydan/js2eel/llms.txt This example demonstrates a full-featured stereo delay plugin. It utilizes JS2EEL's configuration, slider, and sample processing functions to create a functional audio effect. Ensure the buffer size is adequate for the desired delay time and sample rate. ```javascript config({ description: 'stereo_delay', inChannels: 2, outChannels: 2 }); let lengthMs; let mixDb; let feedbackDb; let numSamples; let mix; let feedback; let readIndex = 0; let writeIndex = 0; let bufferValue = 0; // Large buffer for delay line (2 channels, ~9 seconds at 44.1kHz) const buffer = new EelBuffer(2, 400000); slider(1, lengthMs, 250, 0, 2000, 1, 'Delay Time (ms)'); slider(2, mixDb, -6, -120, 6, 0.1, 'Wet Mix (dB)'); slider(3, feedbackDb, -12, -60, 0, 0.1, 'Feedback (dB)'); onSlider(() => { // Convert ms to samples numSamples = (lengthMs * srate) / 1000; // Convert dB to linear mix = Math.pow(10, mixDb / 20); feedback = Math.pow(10, feedbackDb / 20); }); onSample(() => { // Calculate read position (circular buffer) readIndex = writeIndex - numSamples; if (readIndex < 0) { readIndex += buffer.size(); } // Advance write position writeIndex += 1; if (writeIndex >= buffer.size()) { writeIndex = 0; } eachChannel((sample, ch) => { // Read delayed sample bufferValue = buffer[ch][readIndex]; // Write input + feedback to buffer buffer[ch][writeIndex] = sample + bufferValue * feedback; // Output dry + wet sample = sample + bufferValue * mix; }); }); ``` -------------------------------- ### Implement User-Defined Functions for Audio Filters in EEL2 Source: https://context7.com/steeelydan/js2eel/llms.txt This example shows how to create and use user-defined functions in EEL2 for audio filtering, such as a 4-band EQ. Functions are automatically inlined for performance. Coefficients and storage arrays must be initialized. ```javascript config({ description: '4band_eq', inChannels: 2, outChannels: 2 }); // Coefficient storage const hpCoefs = { a1x: 0, a2x: 0, b0x: 0, b1x: 0, b2x: 0 }; const hpXStore = new EelArray(2, 3); const hpYStore = new EelArray(2, 3); let hpFreq; let hpQ; slider(1, hpFreq, 20, 20, 1050, 1, 'HP Freq'); slider(2, hpQ, 0.5, 0.1, 7, 0.01, 'Q'); // User function - will be inlined function setHpCoefs() { const omega = (2 * $pi * hpFreq) / srate; const sinOmega = sin(omega); const cosOmega = cos(omega); const alpha = sinOmega / (2 * hpQ); const a0 = 1 + alpha; hpCoefs.a1x = (-2 * cosOmega) / a0; hpCoefs.a2x = (1 - alpha) / a0; hpCoefs.b0x = ((1 + cosOmega) / 2) / a0; hpCoefs.b1x = (-(1 + cosOmega)) / a0; hpCoefs.b2x = ((1 + cosOmega) / 2) / a0; } // Biquad processing function - inlined for performance function processBiquad(value, ch, coefs, xStore, yStore) { yStore[ch][0] = coefs.b0x * xStore[ch][0] + coefs.b1x * xStore[ch][1] + coefs.b2x * xStore[ch][2] - coefs.a1x * yStore[ch][1] - coefs.a2x * yStore[ch][2]; yStore[ch][2] = yStore[ch][1]; yStore[ch][1] = yStore[ch][0]; xStore[ch][2] = xStore[ch][1]; xStore[ch][1] = xStore[ch][0]; xStore[ch][0] = value; return yStore[ch][0]; } onSlider(() => { setHpCoefs(); }); onSample(() => { eachChannel((sample, ch) => { if (hpFreq > 20) { sample = processBiquad(sample, ch, hpCoefs, hpXStore, hpYStore); } }); }); ``` -------------------------------- ### Host Channel Management Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Functions to get and set the number of audio channels the host application is using. ```eel get_host_numchan() ``` ```eel set_host_numchan(numchan) ``` -------------------------------- ### Pin Mapper Flags Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Functions to get and set flags for the pin mapper. These flags can alter the behavior of the pin mapping system. ```eel get_pinmapper_flags(no parameters) ``` ```eel set_pinmapper_flags(flags) ``` -------------------------------- ### Declare Plugin Variables Source: https://github.com/steeelydan/js2eel/blob/main/docs/getting-started.md Initializes variables for volume level and target linear scale. ```javascript let volume = 0; let target = 0; ``` -------------------------------- ### config() Source: https://context7.com/steeelydan/js2eel/llms.txt Configures the JSFX plugin with essential parameters like description, channel routing, and optional extended tail size. ```APIDOC ## config() Configures the JSFX plugin with description, channel routing, and optional extended tail size for effects like reverb or delay. ```javascript // Basic stereo plugin config({ description: 'my_effect', inChannels: 2, outChannels: 2 }); // Plugin with extended tail (for reverbs, delays) config({ description: 'reverb', inChannels: 2, outChannels: 2, extTailSize: 32768 }); // Mono-to-stereo plugin config({ description: 'mono_to_stereo', inChannels: 1, outChannels: 2 }); ``` ``` -------------------------------- ### Utilize Standard Math Functions Source: https://context7.com/steeelydan/js2eel/llms.txt Demonstrates usage of EEL2-optimized math functions for trigonometric, power, logarithmic, and utility operations. ```javascript config({ description: 'math_demo', inChannels: 2, outChannels: 2 }); onSample(() => { eachChannel((sample, _ch) => { // Trigonometric const s = sin(sample); // Sine const c = cos(sample); // Cosine const t = tan(sample); // Tangent const as = asin(sample); // Arc sine const ac = acos(sample); // Arc cosine const at = atan(sample); // Arc tangent const at2 = atan2(sample, 1); // Arc tangent of y/x // Power and roots const squared = sqr(sample); // x^2 const root = sqrt(abs(sample)); // Square root const power = pow(sample, 2); // x^y const e = exp(sample); // e^x const invSqrt = invsqrt(sample); // Fast 1/sqrt(x) // Logarithms const ln = log(abs(sample)); // Natural log const log10Val = log10(abs(sample)); // Base 10 log // Utilities const absVal = abs(sample); // Absolute value const minVal = min(sample, 1); // Minimum const maxVal = max(sample, -1); // Maximum const signVal = sign(sample); // Sign (-1, 0, or 1) const random = rand(1); // Random 0 to x const floorVal = floor(sample); // Round down const ceilVal = ceil(sample); // Round up // Pi constant const twoPi = 2 * $pi; }); }); ``` -------------------------------- ### Plugin Configuration API Source: https://github.com/steeelydan/js2eel/blob/main/docs/api-documentation.md Functions for initializing the plugin and registering UI elements like sliders, select boxes, and file selectors. ```APIDOC ## Configuration Functions ### config() Configures the plugin metadata and channel settings. ### slider() Registers a slider and its bound variable to be displayed in the plugin UI. ### selectBox() Registers a select box and its bound variable to be displayed in the plugin UI. ### fileSelector() Registers a file selector to be displayed in the plugin UI, relative to /data. ``` -------------------------------- ### Configure JS2EEL Plugin Source: https://github.com/steeelydan/js2eel/blob/main/docs/getting-started.md Defines the plugin description and channel routing configuration. ```javascript config({ description: 'volume', inChannels: 2, outChannels: 2 }); ``` -------------------------------- ### Configure JSFX Plugin Source: https://context7.com/steeelydan/js2eel/llms.txt The config() function sets up plugin metadata like description, channel routing, and extended tail size for effects requiring it. ```javascript // Basic stereo plugin config({ description: 'my_effect', inChannels: 2, outChannels: 2 }); ``` ```javascript // Plugin with extended tail (for reverbs, delays) config({ description: 'reverb', inChannels: 2, outChannels: 2, extTailSize: 32768 }); ``` ```javascript // Mono-to-stereo plugin config({ description: 'mono_to_stereo', inChannels: 1, outChannels: 2 }); ``` -------------------------------- ### Complete Volume Plugin Code Source: https://github.com/steeelydan/js2eel/blob/main/docs/getting-started.md The full implementation of the volume plugin. ```javascript config({ description: 'volume', inChannels: 2, outChannels: 2 }); let volume = 0; let target = 0; slider(1, volume, 0, -150, 18, 0.1, 'Volume [dB]'); onSlider(() => { if (volume > -149.9) { target = Math.pow(10, volume / 20); } else { target = 0; } }); onSample(() => { eachChannel((sample, _ch) => { sample *= target; }); }); ``` -------------------------------- ### Configure Plugin Source: https://github.com/steeelydan/js2eel/blob/main/docs/api-documentation.md Defines the plugin's metadata and channel configuration. ```typescript config({ description, inChannels, outChannels, extTailSize }: { description: number; inChannels: number; outChannels: number; extTailSize?: number; }): void; ``` ```javascript config({ description: 'volume', inChannels: 2, outChannels: 2 }); ``` -------------------------------- ### Perform FFT on Local Buffer Source: https://github.com/steeelydan/js2eel/blob/main/docs/api-documentation.md Use fft() to compute the Fast Fourier Transform on data in local memory. Ensure the size is a power of 2 and does not cross a 65,536 item boundary. Outputs are permuted and may require scaling. ```typescript fft(startIndex: number, size: number): void; ``` -------------------------------- ### Host Placement Information Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Retrieves information about the host's placement or context, potentially including chain position and flags. ```eel get_host_placement([chain_pos, flags]) ``` -------------------------------- ### Process Audio Samples Source: https://github.com/steeelydan/js2eel/blob/main/docs/getting-started.md Applies the target volume to each audio channel sample. ```javascript eachChannel((sample, _ch) => { sample *= target; }); ``` -------------------------------- ### Perform Block-Level Calculations with onBlock Source: https://context7.com/steeelydan/js2eel/llms.txt Use onBlock for calculations that occur once per audio block, such as smoothing parameters to prevent audio artifacts. ```javascript config({ description: 'block_example', inChannels: 2, outChannels: 2 }); let blockGain; let smoothedGain = 1; slider(1, blockGain, 0, -60, 12, 0.1, 'Gain [dB]'); onSlider(() => { blockGain = Math.pow(10, blockGain / 20); }); onBlock(() => { // Smooth gain changes per block to avoid clicks smoothedGain = smoothedGain * 0.99 + blockGain * 0.01; }); onSample(() => { eachChannel((sample, _ch) => { sample *= smoothedGain; }); }); ``` -------------------------------- ### Data Structures Source: https://github.com/steeelydan/js2eel/blob/main/docs/api-documentation.md Containers for audio samples and numeric data. ```typescript EelBuffer { constructor(dimensions: number, size: number); dimensions(): number; size(): number; start(): number; swap(otherBuffer: EelBuffer): void; } ``` ```typescript EelArray { constructor(dimensions: number, size: number); dimensions(): number; size(): number; } ``` -------------------------------- ### Access REAPER Audio Constants Source: https://context7.com/steeelydan/js2eel/llms.txt Retrieves project-level audio information and playback state using built-in constants. ```javascript config({ description: 'audio_info', inChannels: 2, outChannels: 2 }); onSample(() => { // srate: Sample rate of the project (e.g., 44100, 48000) const nyquist = srate / 2; // num_ch: Number of available channels const channels = num_ch; // samplesblock: Samples per block const blockSize = samplesblock; // tempo: Project tempo in BPM const bpm = tempo; // play_state: 0=stopped, 1=playing, 2=paused, 5=recording, 6=record paused const isPlaying = play_state === 1; // play_position: Playback position in seconds const positionSec = play_position; // beat_position: Playback position in beats const positionBeats = beat_position; // ts_num, ts_denom: Time signature (e.g., 3/4 = ts_num:3, ts_denom:4) const timeSigNum = ts_num; const timeSigDenom = ts_denom; // Direct sample access: spl0-spl63 const leftSample = spl0; const rightSample = spl1; }); ``` -------------------------------- ### Define User Slider Source: https://github.com/steeelydan/js2eel/blob/main/docs/getting-started.md Creates a GUI slider bound to the volume variable. ```javascript slider(1, volume, 0, -150, 18, 0.1, 'Volume [dB]'); ``` -------------------------------- ### Process Audio Samples with onSample Source: https://context7.com/steeelydan/js2eel/llms.txt The onSample hook is the primary location for per-sample audio processing logic. ```javascript config({ description: 'sinewave', inChannels: 2, outChannels: 2 }); let freq; let voldb; let vol; let t; slider(1, freq, 80, 0, 440, 1, 'Frequency [Hz]'); slider(2, voldb, -9, -72, 0, 0.1, 'Volume [dB]'); onSlider(() => { vol = 10 ** (voldb / 20); }); onSample(() => { eachChannel((sample, _ch) => { sample = sin(2 * $pi * freq * t) * vol; }); t += 1 / srate; // Increment phase }); ``` -------------------------------- ### Sample Variable Source: https://github.com/steeelydan/js2eel/blob/main/docs/api-documentation.md Represents a channel sample variable. ```APIDOC ## spl<1-64> ### Description Channel 1 (L) sample variable ### Code Example ```typescript spl0: number; ``` ``` -------------------------------- ### Data Structures Source: https://github.com/steeelydan/js2eel/blob/main/docs/api-documentation.md Classes for managing audio samples and numeric data within the EEL2 environment. ```APIDOC ## Data Structures ### EelBuffer A fixed-size, multi-dimensional container for audio samples. Best for large data. ### EelArray A fixed-size, multi-dimensional container for numeric data. Inlined in EEL source, restricted to 16 dimensions/size. ``` -------------------------------- ### Host Interaction Functions Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Functions for interacting with the host environment, including sliders, pin mapping, and buffer exports. ```APIDOC ## Host Interaction Functions ### Description Functions to manage host-side interactions such as slider automation, pin mapping, and project data export. ### Functions - `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()` - `set_pinmapper_flags(flags)` - `get_host_placement([chain_pos, flags])` ``` -------------------------------- ### Audio Constants Source: https://github.com/steeelydan/js2eel/blob/main/docs/api-documentation.md Global constants providing project and playback state information. ```typescript srate: number; ``` ```typescript num_ch: number; ``` ```typescript samplesblock: number; ``` ```typescript tempo: number; ``` ```typescript play_state: number; ``` ```typescript play_position: number; ``` ```typescript beat_position: number; ``` ```typescript ts_num: number; ``` ```typescript ts_denom: number; ``` -------------------------------- ### fft() and ifft() Source: https://github.com/steeelydan/js2eel/blob/main/docs/api-documentation.md Performs a Fast Fourier Transform or its inverse on data in the local memory buffer. ```APIDOC ## fft(startIndex, size) ## ifft(startIndex, size) ### Description Performs a FFT (or inverse in the case of ifft()) on the data in the local memory buffer at the specified offset. Requires real/imaginary input pairs. ### Parameters #### Path Parameters - **startIndex** (number) - Required - The offset in the local memory buffer. - **size** (number) - Required - The size of the FFT (must be 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, or 32768). ### Request Example fft(0, 256); ``` -------------------------------- ### Send MIDI Buffer/String Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Functions for sending MIDI data from a buffer or a string. `midisend_buf` sends raw byte data, while `midisend_str` sends a null-terminated string. ```eel midisend_buf(offset, buf, len) ``` ```eel midisend_str(offset, string) ``` -------------------------------- ### selectBox() Source: https://context7.com/steeelydan/js2eel/llms.txt Registers a dropdown select box for choosing between discrete options, with values accessed by their string names. ```APIDOC ## selectBox() Registers a dropdown select box for choosing between discrete options. Values are accessed by their string names in code. ```javascript config({ description: 'saturation', inChannels: 2, outChannels: 2 }); let algorithm; let gainIn; slider(1, gainIn, 0, 0, 36, 0.01, 'Gain In (dB)'); selectBox( 2, algorithm, 'sigmoid', // default value [ { name: 'sigmoid', label: 'Sigmoid' }, { name: 'htan', label: 'Hyperbolic Tangent' }, { name: 'hclip', label: 'Hard Clip' } ], 'Algorithm' ); onSample(() => { eachChannel((sample, _ch) => { if (algorithm === 'sigmoid') { sample = 2 * (1 / (1 + exp(-gainIn * sample))) - 1; } else if (algorithm === 'htan') { sample = (exp(2 * sample * gainIn) - 1) / (exp(2 * sample * gainIn) + 1); } else if (algorithm === 'hclip') { sample *= gainIn; sample = abs(sample) > 0.5 ? 0.5 * sign(sample) : sample; } }); }); ``` ``` -------------------------------- ### Pin Mapping Functions Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Functions for retrieving and setting pin mappings for audio routing. These allow detailed control over input/output connections. ```eel get_pin_mapping(inout, pin, startchan, chanmask) ``` ```eel set_pin_mapping(inout, pin, startchan, chanmask, mapping) ``` -------------------------------- ### Receive MIDI Buffer/String Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Functions for receiving MIDI data into a buffer or a string. `midirecv_buf` reads raw byte data up to `maxlen`, while `midirecv_str` reads a null-terminated string. ```eel midirecv_buf(offset, buf, maxlen) ``` ```eel midirecv_str(offset, string) ``` -------------------------------- ### GFX Image and Blitting Functions Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Functions for loading images, manipulating image dimensions, and performing blitting operations. ```APIDOC ## GFX Image and Blitting Functions ### Description Handles image loading, dimension management, and various blitting techniques. ### Functions - `gfx_getimgdim(image, w, h)`: Gets the dimensions of an image. - `gfx_setimgdim(image, w, h)`: Sets the dimensions of an image. - `gfx_loadimg(image, filename)`: Loads an image from a file. - `gfx_blit(source, scale, rotation)`: Basic blitting operation. - `gfx_blit(source, scale, rotation[, srcx, srcy, srcw, srch, destx, desty, destw, desth, rotxoffs, rotyoffs])`: Advanced blitting with source/destination rectangle and rotation offsets. - `gfx_blitext(source, coordinatelist, rotation)`: Blitting with a coordinate list. - `gfx_gradrect(x, y, w, h, r, g, b, a[, drdx, dgdx, dbdx, dadx, drdy, dgdy, dbdy, dady])`: Fills a rectangle with a gradient. - `gfx_muladdrect(x, y, w, h, mul_r, mul_g, mul_b[, mul_a, add_r, add_g, add_b, add_a])`: Multiplies and adds color values to a rectangle. - `gfx_deltablit(srcimg, srcx, srcy, srcw, srch, destx, desty, destw, desth, dsdx, dtdx, dsdy, dtdy, dsdxdy, dtdxdy[, usecliprect=1])`: Delta blitting for efficient image updates. - `gfx_transformblit(srcimg, destx, desty, destw, desth, div_w, div_h, table)`: Blitting with a transformation table. ``` -------------------------------- ### fileSelector() Source: https://context7.com/steeelydan/js2eel/llms.txt Registers a file selector for loading external files, such as impulse responses, with paths relative to REAPER's data directory. ```APIDOC ## fileSelector() Registers a file selector for loading external files like impulse responses. Path is relative to REAPER's data directory. ```javascript config({ description: 'cab_sim', inChannels: 2, outChannels: 2, extTailSize: 32768 }); let ampModel; let importedBuffer = new EelBuffer(1, 131072); let importedBufferChAmount = 0; let importedBufferSize; // fileSelector(sliderNumber, variable, path, defaultValue, label) fileSelector(1, ampModel, 'amp_models', 'none', 'Impulse Response'); onSlider(() => { const fileHandle = file_open(ampModel); if (fileHandle > 0) { let sampleRate = 0; file_riff(fileHandle, importedBufferChAmount, sampleRate); if (importedBufferChAmount) { importedBufferSize = file_avail(fileHandle) / importedBufferChAmount; file_mem(fileHandle, importedBuffer.start(), importedBufferSize * importedBufferChAmount); } file_close(fileHandle); } }); ``` ``` -------------------------------- ### File System Functions Source: https://github.com/steeelydan/js2eel/blob/main/docs/api-documentation.md Functions for opening, closing, and reading file data. ```typescript file_open(fileSelector: any): number; ``` ```typescript file_close(fileHandle: any): void; ``` ```typescript file_avail(fileSelector: any): number; ``` ```typescript file_riff(fileHandle: any, numberOfCh: number, sampleRate: number): void; ``` ```typescript file_mem(fileHandle: any, offset: number, length: number): number; ``` -------------------------------- ### Iterate Channels with eachChannel Source: https://context7.com/steeelydan/js2eel/llms.txt Use eachChannel within onSample to apply processing logic across multiple audio channels simultaneously. ```javascript config({ description: 'stereo_processor', inChannels: 2, outChannels: 2 }); let gain; slider(1, gain, 0, -60, 12, 0.1, 'Gain [dB]'); let linearGain; onSlider(() => { linearGain = Math.pow(10, gain / 20); }); onSample(() => { // sample: current sample value (read/write) // ch: channel index (0 = left, 1 = right) eachChannel((sample, ch) => { sample *= linearGain; // Channel-specific processing if (ch === 0) { // Left channel only } else if (ch === 1) { // Right channel only } }); }); ``` -------------------------------- ### GFX Utility Functions Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Miscellaneous GFX utility functions. ```APIDOC ## GFX Utility Functions ### Description Provides utility functions for GFX operations. ### Functions - `gfx_blurto(x, y)`: Applies a blur effect to a target point. - `gfx_getchar([char, unicodechar])`: Gets a character from the current context. ``` -------------------------------- ### Export Audio Buffer Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Exports an audio buffer to the host project's track. Requires buffer details and track index. ```eel export_buffer_to_project(buffer, length_samples, nch, srate, track_index[, flags, tempo, planar_pitch]) -- ``` -------------------------------- ### Perform FFT/IFFT Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Functions for Fast Fourier Transform (FFT) and its inverse (IFFT). These operate on a specified range within memory. ```eel fft(start_index, size) ``` ```eel ifft(start_index, size) ``` -------------------------------- ### Perform Inverse FFT on Local Buffer Source: https://github.com/steeelydan/js2eel/blob/main/docs/api-documentation.md Use ifft() to compute the Inverse Fast Fourier Transform on data in local memory. Similar constraints to fft() apply regarding size and memory boundaries. Outputs are permuted and may require scaling. ```typescript ifft(startIndex: number, size: number): void; ``` -------------------------------- ### GFX Functions Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Functions for controlling the graphics menu and cursor. ```APIDOC ## GFX Functions ### `gfx_showmenu("str")` Displays a menu with the given string. ### `gfx_setcursor(resource_id[,"custom cursor name"])` Sets the cursor to a specified resource or a custom cursor name. ``` -------------------------------- ### GFX Text Rendering Functions Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Functions for drawing text, setting fonts, and measuring text dimensions. ```APIDOC ## GFX Text Rendering Functions ### Description Functions for rendering text and managing fonts. ### Functions - `gfx_drawnumber(n, ndigits)`: Draws a number with a specified number of digits. - `gfx_drawchar($'c')`: Draws a single character. - `gfx_drawstr(str[, flags, right, bottom])`: Draws a string with optional flags and alignment. - `gfx_measurestr(str, w, h)`: Measures the width and height of a string. - `gfx_setfont(idx[, fontface, sz, flags])`: Sets the current font. - `gfx_getfont()`: Gets the index of the current font. - `gfx_printf(str, ...)`: Formatted string printing. ``` -------------------------------- ### MIDI Functions Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Functions for sending and receiving MIDI messages and buffers. ```APIDOC ## MIDI Functions ### Description Functions to handle MIDI data transmission and reception. ### Functions - `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)` ``` -------------------------------- ### File Functions Source: https://github.com/steeelydan/js2eel/blob/main/docs/api-documentation.md Functions for file input and output operations. ```APIDOC ## file_open() ### Description 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. ### Method Function ### Parameters #### Path Parameters - **fileSelector** (any) - A variable that is bound to the respective file selector. Will be compiled to sliderXY. FIXME types ### Returns - (number) - A file handle. ``` ```APIDOC ## file_close() ### Description Closes a file opened with file_open(). ### Method Function ### Parameters #### Path Parameters - **fileHandle** (any) - The handle of the file to close. ### Returns - void ``` ```APIDOC ## file_avail() ### Description 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. ### Method Function ### Parameters #### Path Parameters - **fileSelector** (any) - The file selector to check. ### Returns - (number) - The number of remaining items or status code. ``` ```APIDOC ## file_riff() ### Description 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. 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()). ### Method Function ### Parameters #### Path Parameters - **fileHandle** (any) - The file handle. - **numberOfCh** (number) - The number of channels, or 'rqsr' for resampling. - **sampleRate** (number) - The sample rate, or the desired sample rate for resampling. ### Returns - void ``` ```APIDOC ## file_mem() ### Description Reads (or writes) the block of local memory from(to) the current file. Returns the actual number of items read (or written). ### Method Function ### Parameters #### Path Parameters - **fileHandle** (any) - The file handle. - **offset** (number) - The offset in memory. - **length** (number) - The number of items to read or write. ### Returns - (number) - The number of items read or written. ``` -------------------------------- ### Arithmetic and Power Functions Source: https://github.com/steeelydan/js2eel/blob/main/docs/api-documentation.md Functions for basic arithmetic, powers, and logarithms. ```typescript sqr(x: number): number; ``` ```typescript sqrt(x: number): number; ``` ```typescript pow(x: number, y: number): number; ``` ```typescript exp(x: number): number; ``` ```typescript log(x: number): number; ``` ```typescript log10(x: number): number; ``` -------------------------------- ### Perform Real FFT/IFFT Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Functions for performing FFT and IFFT on real-valued data. These are optimized for real inputs and outputs. ```eel fft_real(start_index, size) ``` ```eel ifft_real(start_index, size) ``` -------------------------------- ### Set Cursor with Resource ID Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Use `gfx_setcursor` to set the mouse cursor. It accepts a resource ID and an optional custom cursor name. ```javascript gfx_setcursor(resource_id, "custom cursor name") ``` -------------------------------- ### Delay Compensation Variables Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Variables for managing delay compensation in audio processing. ```APIDOC ## Delay Compensation Vars - `pdc_delay` (int): Delay compensation value. - `pdc_bot_ch` (int): Bottom channel for delay compensation. - `pdc_top_ch` (int): Top channel for delay compensation. - `pdc_midi` (int): MIDI delay compensation. ``` -------------------------------- ### Implement FFT Convolution in EEL2 Source: https://context7.com/steeelydan/js2eel/llms.txt This snippet implements FFT-based convolution for spectral processing. It requires initializing buffer sizes and performing FFT on both the source and input blocks, followed by convolution and inverse FFT. Ensure correct buffer sizes and FFT sizes are set. ```javascript config({ description: 'fft_convolver', inChannels: 2, outChannels: 2, extTailSize: 32768 }); let fftSize = 1024; let convolutionSource = new EelBuffer(1, 131072); let currentBlock = new EelBuffer(1, 65536); let lastBlock = new EelBuffer(1, 65536); let inverseFftSize; let bufferPosition = 0; let chunkSize; onInit(() => { inverseFftSize = 1 / fftSize; chunkSize = fftSize / 2; }); onBlock(() => { // Prepare convolution kernel with FFT fft(convolutionSource.start(), fftSize); // Normalize let i = 0; while (i < fftSize * 2) { convolutionSource[0][i] *= inverseFftSize; i += 1; } }); onSample(() => { if (bufferPosition >= chunkSize) { // Swap buffers lastBlock.swap(currentBlock); // Zero-pad memset(currentBlock.start() + chunkSize * 2, 0, (fftSize - chunkSize) * 2); // FFT -> Convolve -> IFFT fft(currentBlock.start(), fftSize); convolve_c(currentBlock.start(), convolutionSource.start(), fftSize); ifft(currentBlock.start(), fftSize); bufferPosition = 0; } // Process samples with overlap-add const pos2x = bufferPosition * 2; lastBlock[0][pos2x] = spl0; spl0 = currentBlock[0][pos2x]; bufferPosition += 1; }); ``` -------------------------------- ### String Manipulation Functions Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md A collection of string functions including length, copy, concatenation, comparison, and formatting utilities. ```APIDOC ## String Functions Overview ### Functions - **strlen(str)** - Returns the length of the string. - **strcpy(str, srcstr)** - Copies srcstr into str. - **strcat(str, srcstr)** - Appends srcstr to str. - **strcmp(str, str2)** - Compares two strings. - **stricmp(str, str2)** - Case-insensitive comparison of two strings. - **strncmp(str, str2, maxlen)** - Compares up to maxlen characters of two strings. - **strnicmp(str, str2, maxlen)** - Case-insensitive comparison of up to maxlen characters. - **strncpy(str, srcstr, maxlen)** - Copies up to maxlen characters from srcstr to str. - **strncat(str, srcstr, maxlen)** - Appends up to maxlen characters from srcstr to str. - **strcpy_from(str, srcstr, offset)** - Copies from srcstr to str starting at offset. - **strcpy_substr(str, srcstr, offset, maxlen)** - Copies a substring from srcstr to str. - **str_getchar(str, offset[, type])** - Gets a character from the string at the specified offset. - **str_setchar(str, offset, value[, type])** - Sets a character in the string at the specified offset. - **strcpy_fromslider(str, slider)** - Copies string data from a slider. - **sprintf(str, format, ...)** - Formats data into a string. - **match(needle, haystack, ...)** - Performs pattern matching. - **matchi(needle, haystack, ...)** - Performs case-insensitive pattern matching. ``` -------------------------------- ### GFX Drawing Functions Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Functions for setting drawing parameters, drawing lines, rectangles, pixels, and shapes. ```APIDOC ## GFX Drawing Functions ### Description Provides functions for basic 2D graphics drawing operations. ### Functions - `gfx_set(r, g, b, a, mode, dest)`: Sets drawing color, alpha, mode, and destination. - `gfx_lineto(x, y, aa)`: Draws a line to the specified coordinates with anti-aliasing. - `gfx_line(x, y, x2, y2[, aa])`: Draws a line between two points with optional anti-aliasing. - `gfx_rectto(x, y)`: Sets the current rectangle corner. - `gfx_rect(x, y, w, h)`: Draws a rectangle. - `gfx_setpixel(r, g, b)`: Sets the color of a single pixel. - `gfx_getpixel(r, g, b)`: Gets the color of a single pixel. - `gfx_circle(x, y, r[, fill, antialias])`: Draws a circle, optionally filled and anti-aliased. - `gfx_roundrect(x, y, w, h, radius[, antialias])`: Draws a rounded rectangle. - `gfx_arc(x, y, r, ang1, ang2[, antialias])`: Draws an arc. - `gfx_triangle(x1, y1, x2, y2, x3, y3[, x4, y4, ...])`: Draws a polygon (triangle or more vertices). ``` -------------------------------- ### JSFX Computation Stages Source: https://github.com/steeelydan/js2eel/blob/main/docs/api-documentation.md Lifecycle hooks that correspond to standard JSFX computation stages. ```APIDOC ## Computation Stages ### onInit() Init variables and functions here. ### onSlider() Triggered when a slider is moved. ### onBlock() Called for every audio block. ### onSample() Called for every single sample. ### eachChannel() Iterates over each channel and provides the current sample for manipulation. ``` -------------------------------- ### Implement a Lowpass Filter with EelArray Source: https://context7.com/steeelydan/js2eel/llms.txt Uses EelArray for efficient, inlined storage of filter coefficients and state variables. EelArray is limited to 16 dimensions and 16 elements per dimension. ```javascript config({ description: 'lowpass', inChannels: 2, outChannels: 2 }); let lpFreq; let lpQ; // Filter coefficients stored in object const lpCoefs = { a1x: 0, a2x: 0, b0x: 0, b1x: 0, b2x: 0 }; // EelArray(dimensions, size) - inlined, max 16x16 const lpXStore = new EelArray(2, 3); // 2 channels, 3 values each const lpYStore = new EelArray(2, 3); slider(1, lpFreq, 22000, 5, 22000, 1, 'LP Freq'); slider(2, lpQ, 0.5, 0.1, 7, 0.01, 'Q'); function setLpCoefs() { const omega = (2 * $pi * lpFreq) / srate; const sinOmega = sin(omega); const cosOmega = cos(omega); const alpha = sinOmega / (2 * lpQ); const a0 = 1 + alpha; lpCoefs.a1x = (-2 * cosOmega) / a0; lpCoefs.a2x = (1 - alpha) / a0; lpCoefs.b0x = ((1 - cosOmega) / 2) / a0; lpCoefs.b1x = (1 - cosOmega) / a0; lpCoefs.b2x = ((1 - cosOmega) / 2) / a0; } function processSample(value, ch, coefs, xStore, yStore) { yStore[ch][0] = coefs.b0x * xStore[ch][0] + coefs.b1x * xStore[ch][1] + coefs.b2x * xStore[ch][2] - coefs.a1x * yStore[ch][1] - coefs.a2x * yStore[ch][2]; yStore[ch][2] = yStore[ch][1]; yStore[ch][1] = yStore[ch][0]; xStore[ch][2] = xStore[ch][1]; xStore[ch][1] = xStore[ch][0]; xStore[ch][0] = value; return yStore[ch][0]; } onSlider(() => { setLpCoefs(); }); onSample(() => { eachChannel((sample, ch) => { sample = processSample(sample, ch, lpCoefs, lpXStore, lpYStore); }); }); ``` -------------------------------- ### Channel Sample Variable Source: https://github.com/steeelydan/js2eel/blob/main/docs/api-documentation.md Represents the sample variable for channel 1. ```typescript spl0: number; ``` -------------------------------- ### GFX Extended Retina Variable Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Enables or configures extended retina display support. ```javascript gfx_ext_retina ``` -------------------------------- ### Memory Management Functions Source: https://github.com/steeelydan/js2eel/blob/main/docs/feature-comparison.md Utility functions for memory operations, including freeing buffers, copying memory, and setting memory to a specific value. ```eel freembuf(top) ``` ```eel memcpy(dest, source, length) ``` ```eel memset(dest, value, length) ``` -------------------------------- ### Register File Selector Control Source: https://context7.com/steeelydan/js2eel/llms.txt The fileSelector() function adds a file selection control, useful for loading external assets like impulse responses. The path is relative to REAPER's data directory. ```javascript config({ description: 'cab_sim', inChannels: 2, outChannels: 2, extTailSize: 32768 }); let ampModel; let importedBuffer = new EelBuffer(1, 131072); let importedBufferChAmount = 0; let importedBufferSize; // fileSelector(sliderNumber, variable, path, defaultValue, label) fileSelector(1, ampModel, 'amp_models', 'none', 'Impulse Response'); onSlider(() => { const fileHandle = file_open(ampModel); if (fileHandle > 0) { let sampleRate = 0; file_riff(fileHandle, importedBufferChAmount, sampleRate); if (importedBufferChAmount) { importedBufferSize = file_avail(fileHandle) / importedBufferChAmount; file_mem(fileHandle, importedBuffer.start(), importedBufferSize * importedBufferChAmount); } file_close(fileHandle); } }); ``` -------------------------------- ### Manage Audio Data with EelBuffer Source: https://context7.com/steeelydan/js2eel/llms.txt EelBuffer provides a multi-dimensional memory container for storing large audio data, such as delay lines or FFT buffers. ```javascript config({ description: 'mono_delay', inChannels: 2, outChannels: 2 }); let lengthMs; let mixDb; let numSamples; let mix; let readIndex = 0; let writeIndex = 0; let bufferValue = 0; // EelBuffer(dimensions, size) const buffer = new EelBuffer(2, 400000); // 2 channels, 400000 samples each slider(1, lengthMs, 120, 0, 2000, 1, 'Delay (ms)'); slider(2, mixDb, -6, -120, 6, 1, 'Mix (dB)'); onSlider(() => { numSamples = (lengthMs * srate) / 1000; mix = Math.pow(2, mixDb / 6); }); onSample(() => { readIndex = writeIndex - numSamples; if (readIndex < 0) { readIndex += buffer.size(); } writeIndex += 1; if (writeIndex >= buffer.size()) { writeIndex = 0; } eachChannel((sample, ch) => { bufferValue = buffer[ch][readIndex]; buffer[ch][writeIndex] = sample; sample = sample + bufferValue * mix; }); }); ```