tags: jsfx reaper eel title: Introduction to Reaper JSFX This introduction will largely pick apart a few very simple JSFX scripts to see how they work. My comments are preceded by a lot of slashes, e.g. `///////` # Volume ``` // This effect Copyright (C) 2004 and later Cockos Incorporated // License: LGPL - http://www.gnu.org/licenses/lgpl.html ////// the desc: line is what defines the name that appears in Reaper's FX browser desc: Volume Adjustment //tags: utility gain //author: Cockos /////// slider format: // sliderN:defaultValueName // see below how to use a slider slider1:6<-150,150,0.1>Adjustment (dB) slider2:0<-150,150,0.1>Max Volume (dB) /////// input configuration for 2-in 2-out in_pin:left input in_pin:right input out_pin:left output out_pin:right output ////// @init section is run once when plugin is loaded @init //// use varName = value; to set a value //// note that all statements end with a semicolon ext_tail_size = -2; ////// the @slider section is run whenever a slider is moved @slider ///// ^ is used for exponention, this converts from dB to linear values adj1=2 ^ (slider1/6); adj2=2 ^ (slider2/6); doseek < 0 ? doseek = 1; //// this is so that changes aren't abrupt ////// @block is run once per block of samples (e.g. 256 samples at a time) ////// you'll tend to do MIDI processing here @block ///// if/else takes the form (inspired by C's ternary operator) ///// condition ? what-to-do-if-true : what-to-do-if-false ; ///// statements are grouped with brackets doseek > 0 ? ( dadj=(adj1-adj1_s)/samplesblock; ):( dadj=0; adj1_s=adj1; ); doseek = -1; ////// @sample is run once per sample, DSP goes here @sample ////// the min(max(...)) is used to clamp the values to a max amplitude spl0=min(max(spl0*adj1_s,-adj2),adj2); spl1=min(max(spl1*adj1_s,-adj2),adj2); adj1_s+=dadj; ``` ## Functions See [the docs](https://www.reaper.fm/sdk/js/userfunc.php) ``` function getSampleRate() ( srate; // return srate ); function mySine(x) ( // taylor approximation x - (x^3)/(3*2) + (x^5)/(5*4*3*2) - (x^7)/(7*6*5*4*3*2) + (x^9)/(9*8*7*6*5*4*3*2); ); function calculateSomething(x y) ( x += mySine(y); x/y; ); ``` ## MPE Example This allocates notes to the first available channel. This will probably fail if more than 15 simultaneous notes are played. ``` desc: JDA Midi Mpe Allocator 1 @init alloc_base = 100; // channel => pitch alloc_chan = 200; // pitch => channel alloc_i = 0; loop(i=0;16,alloc_base[i]=-1;i+=1); function off(offset,nch,p,v) ( alloc_chan[p] = 0; alloc_base[nch] = -1; midisend(offset,0x80|nch,p,v); ); @block while(midirecv(offset,m1,m2,m3)) ( cmd = m1 >> 4; ch = m1 & 0xF; ( cmd == 0x8 || ( cmd == 90 && m3 == 0 ) ) ? ( nch = alloc_chan[m2]; off(offset,nch,m2,( cmd == 0x80 ? v : 0)); ) : ( cmd == 0x9 ) ? ( nch = alloc_chan[m2]; nch > 0 ? ( off(offset,nch,m2,0); ); fch = 0; i=1; while(i<16 && fch == 0) ( ( alloc_base[i] == -1 ) ? ( fch = i; tmx1 = i; ); i += 1; ); alloc_chan[m2] = fch; alloc_base[fch] = m2; midisend(offset,0x90|fch,m2,m3); ) : ( midisend(offset,m1,m2,m3); ) ); ```