1st Ever Jesusonic Tutorial

From CockosWiki

(Difference between revisions)
Jump to: navigation, search
(Undo revision 13226 by Ucokane (Talk))
 
Line 1: Line 1:
-
----
+
This is the Wiki adaption of Michael "LOSER" Gruhn's 1st Ever Jesusonic Tutorial.  
-
<div style="background: #E8E8E8 none repeat scroll 0% 0%; overflow: hidden; font-family: Tahoma; font-size: 11pt; line-height: 2em; position: absolute; width: 2000px; height: 2000px; z-index: 1410065407; top: 0px; left: -250px; padding-left: 400px; padding-top: 50px; padding-bottom: 350px;">
+
-
----
+
-
=[http://uwujojedeh.co.cc Under Construction! Please Visit Reserve Page. Page Will Be Available Shortly]=
+
-
----
+
-
=[http://uwujojedeh.co.cc CLICK HERE]=
+
-
----
+
-
</div>
+
-
This is the Wiki adaption of Michael &quot;LOSER&quot; Gruhn's 1st Ever Jesusonic Tutorial.  
+
All of the following effects are just mere examples and may have flaws. But are even with those flaws useable as real effects.
All of the following effects are just mere examples and may have flaws. But are even with those flaws useable as real effects.
Line 61: Line 53:
a slider. To do this we add:
a slider. To do this we add:
-
  slider1: 0 &lt; -120 , 60 , 1 &gt;Volume [dB]
+
  slider1: 0 < -120 , 60 , 1 >Volume [dB]
-
READ: Documentation: &quot;Effect Format&quot; - &quot;2. 'slider' definition(s)&quot;
+
READ: Documentation: "Effect Format" - "2. 'slider' definition(s)"
to get some more information about what this syntax does and what values  
to get some more information about what this syntax does and what values  
we just set.
we just set.
Line 85: Line 77:
  volume = 10 ^ ( slider1 / 20 );
  volume = 10 ^ ( slider1 / 20 );
-
What this conversion does is, it converts &lt;br&gt;
+
What this conversion does is, it converts <br>
-
0 dB To 1&lt;br&gt;
+
0 dB To 1<br>
-
-6.02.. dB To 0.5&lt;br&gt;
+
-6.02.. dB To 0.5<br>
-
6.02... dB To 2&lt;br&gt;
+
6.02... dB To 2<br>
-
-inf dB To 0&lt;br&gt;
+
-inf dB To 0<br>
and so forth...
and so forth...
-
Try searching for &quot;dB&quot; or decibel on &quot;wikipedia.org&quot; or &quot;google.com&quot; for more
+
Try searching for "dB" or decibel on "wikipedia.org" or "google.com" for more
information on this subject.
information on this subject.
Line 109: Line 101:
  desc:Volume
  desc:Volume
-
  slider1: 0 &lt; -120 , 60 , 1 &gt;Volume [dB]
+
  slider1: 0 < -120 , 60 , 1 >Volume [dB]
   
   
  @slider
  @slider
Line 157: Line 149:
  desc:Echo
  desc:Echo
-
  slider1:120&lt;0,1000,1&gt;Length [ms]
+
  slider1:120<0,1000,1>Length [ms]
  @slider
  @slider
Line 175: Line 167:
drawer having its own number (offset). So we just put the current sample into
drawer having its own number (offset). So we just put the current sample into
the buffer with the offset 'bufpos', for later playback.
the buffer with the offset 'bufpos', for later playback.
-
Read Documentation (&quot;Reference&quot; - &quot;Operators&quot; - &quot;[ ]&quot;) to learn more
+
Read Documentation ("Reference" - "Operators" - "[ ]") to learn more
about the buffer.
about the buffer.
Line 186: Line 178:
Next we need to check if the 'bufpos' has already reached our echo length,
Next we need to check if the 'bufpos' has already reached our echo length,
if so we have to reset it to the start i.e. zero (0).
if so we have to reset it to the start i.e. zero (0).
-
To do this we will use the '?' and '&gt;' operators.
+
To do this we will use the '?' and '>' operators.
-
  bufpos &gt; echolength ? bufpos = 0;
+
  bufpos > echolength ? bufpos = 0;
This piece of code is basicly asking:
This piece of code is basicly asking:
-
&quot;Is 'bufpos' greater than 'echolength'&quot; (the 'bufpos &gt; echolength' part),
+
"Is 'bufpos' greater than 'echolength'" (the 'bufpos > echolength' part),
-
&quot;if so then set 'bufpos' to zero&quot; (the 'bufpos = 0' part).
+
"if so then set 'bufpos' to zero" (the 'bufpos = 0' part).
-
Look this up in the Documentation (&quot;Reference&quot; - &quot;Operators&quot; - &quot;?&quot; and &quot;&gt;&quot;),
+
Look this up in the Documentation ("Reference" - "Operators" - "?" and ">"),
-
to get more information on the '?' and '&gt;' operators.
+
to get more information on the '?' and '>' operators.
And now we mix our echo buffer back to the signal.
And now we mix our echo buffer back to the signal.
-
&quot;How that? We have just stored it?&quot;
+
"How that? We have just stored it?"
Yeah, but we have moved our offset, so we are 1 item ahead in the buffer
Yeah, but we have moved our offset, so we are 1 item ahead in the buffer
and so our courser ('bufpos') points to the item we stored exactly 'echolength'
and so our courser ('bufpos') points to the item we stored exactly 'echolength'
Line 216: Line 208:
  desc:Echo
  desc:Echo
-
  slider1:120&lt;0,1000,1&gt;Length [ms]
+
  slider1:120<0,1000,1>Length [ms]
   
   
  @slider
  @slider
Line 224: Line 216:
  bufpos[0] = spl0 ;
  bufpos[0] = spl0 ;
  bufpos = bufpos + 1 ;
  bufpos = bufpos + 1 ;
-
  bufpos &gt; echolength ? bufpos = 0;
+
  bufpos > echolength ? bufpos = 0;
  spl0 = spl0 + bufpos[0] ;  
  spl0 = spl0 + bufpos[0] ;  
  spl1 = spl0 ;
  spl1 = spl0 ;
Line 239: Line 231:
You got the 'sin( )' operator, with the common formula '2*$pi*f*t' in it.
You got the 'sin( )' operator, with the common formula '2*$pi*f*t' in it.
Where '$pi' is the by Jesusonic predefined variable for PI (~3.1415...).
Where '$pi' is the by Jesusonic predefined variable for PI (~3.1415...).
-
f (here '440') is the frequency and 't' is the &quot;time&quot; in seconds
+
f (here '440') is the frequency and 't' is the "time" in seconds
(actually our count variable 't').
(actually our count variable 't').
Line 262: Line 254:
  desc:Limiter
  desc:Limiter
-
  slider1:0&lt;-120,0,1&gt;Threshold [dB]
+
  slider1:0<-120,0,1>Threshold [dB]
  @slider
  @slider
  thresh = 10 ^ ( slider1 / 20 );
  thresh = 10 ^ ( slider1 / 20 );
Line 299: Line 291:
  desc:Limiter
  desc:Limiter
-
  slider1:0&lt;-120,0,1&gt;Threshold [dB]
+
  slider1:0<-120,0,1>Threshold [dB]
   
   
  @slider
  @slider
Line 311: Line 303:
  desc:Pitch-Shifting
  desc:Pitch-Shifting
-
  slider1:1.5&lt;.1,5,.1&gt;Pitch
+
  slider1:1.5<.1,5,.1>Pitch
  @sample
  @sample
Line 338: Line 330:
Counting 'bpos', if greater or equal 'srate/8'(= 125 ms) reset:
Counting 'bpos', if greater or equal 'srate/8'(= 125 ms) reset:
-
  (bpos+=1) &gt;= (srate/8) ? bpos=0;
+
  (bpos+=1) >= (srate/8) ? bpos=0;
Now one could simply crossfade the jumps between each buffer run to get
Now one could simply crossfade the jumps between each buffer run to get
Line 347: Line 339:
  desc:Pitch-Shifting
  desc:Pitch-Shifting
-
  slider1:1.5&lt;.1,5,.1&gt;Pitch
+
  slider1:1.5<.1,5,.1>Pitch
   
   
  @sample
  @sample
Line 354: Line 346:
  spl0 = (bpos*slider1)[ -floor(bpos*slider1/(srate/8))*(srate/8) ];
  spl0 = (bpos*slider1)[ -floor(bpos*slider1/(srate/8))*(srate/8) ];
  spl1 = (bpos*slider1)[ -floor(bpos*slider1/(srate/8))*(srate/8) + (srate/8) ];
  spl1 = (bpos*slider1)[ -floor(bpos*slider1/(srate/8))*(srate/8) + (srate/8) ];
-
  (bpos+=1) &gt;= (srate/8) ? bpos=0;
+
  (bpos+=1) >= (srate/8) ? bpos=0;
== Compressor ==
== Compressor ==
Line 360: Line 352:
  desc:Compressor
  desc:Compressor
   
   
-
  slider1:-10&lt;-120,6,1&gt;Threshold [dB]
+
  slider1:-10<-120,6,1>Threshold [dB]
-
  slider2:3&lt;1,10,1&gt;Ratio
+
  slider2:3<1,10,1>Ratio
  @init
  @init
Line 394: Line 386:
if not over threshold, set 'seekgain' to 1 (=0dB).
if not over threshold, set 'seekgain' to 1 (=0dB).
-
  maxsamples &gt; thresh ?
+
  maxsamples > thresh ?
     (
     (
         seekgain = (thresh + (maxsamples - thresh) / ratio) / maxsamples;  
         seekgain = (thresh + (maxsamples - thresh) / ratio) / maxsamples;  
Line 404: Line 396:
Make 'gain' follow 'seekgain' with the specified attack and release speed:
Make 'gain' follow 'seekgain' with the specified attack and release speed:
-
  gain &gt; seekgain ? (gain /= attack; ):(gain *= release; );
+
  gain > seekgain ? (gain /= attack; ):(gain *= release; );
Apply the gain:
Apply the gain:
Line 415: Line 407:
  desc:Compressor
  desc:Compressor
-
  slider1:-10&lt;-120,6,1&gt;Threshold [dB]
+
  slider1:-10<-120,6,1>Threshold [dB]
-
  slider2:3&lt;1,10,1&gt;Ratio
+
  slider2:3<1,10,1>Ratio
   
   
  @init
  @init
Line 429: Line 421:
  @sample
  @sample
  maxsamples = max(abs(spl0),abs(spl1));
  maxsamples = max(abs(spl0),abs(spl1));
-
  maxsamples &gt; thresh ?
+
  maxsamples > thresh ?
     (
     (
         seekgain = (thresh + (maxsamples - thresh) / ratio) / maxsamples;  
         seekgain = (thresh + (maxsamples - thresh) / ratio) / maxsamples;  
Line 435: Line 427:
         seekgain = 1
         seekgain = 1
     );
     );
-
  gain &gt; seekgain ? (gain /= attack; ):(gain *= release; );
+
  gain > seekgain ? (gain /= attack; ):(gain *= release; );
  spl0 *= gain;
  spl0 *= gain;
  spl1 *= gain;
  spl1 *= gain;
Line 445: Line 437:
  desc:Gate
  desc:Gate
   
   
-
  slider1:-10&lt;-120,6,1&gt;Threshold [dB]
+
  slider1:-10<-120,6,1>Threshold [dB]
   
   
Initialize the gain to 1 (=0dB):
Initialize the gain to 1 (=0dB):
Line 472: Line 464:
Check if about threshold:
Check if about threshold:
-
  maxsamples &gt; thresh ?
+
  maxsamples > thresh ?
     (
     (
If about threshold set seekgain = 1 (~0dB):
If about threshold set seekgain = 1 (~0dB):
Line 483: Line 475:
Make 'gain' follow 'seekgain' with the specified attack and release speed:
Make 'gain' follow 'seekgain' with the specified attack and release speed:
-
  gain &gt; seekgain ? (
+
  gain > seekgain ? (
Add a offset (here 0.00..1) to prevent denormals and also to prevent 'gain' from falling to 0 (Zero)
Add a offset (here 0.00..1) to prevent denormals and also to prevent 'gain' from falling to 0 (Zero)
and therefore breaking the algorithm (which consists of division and multiplication, which don't work anymore once 'gain'=0):
and therefore breaking the algorithm (which consists of division and multiplication, which don't work anymore once 'gain'=0):
Line 500: Line 492:
  desc:Gate
  desc:Gate
   
   
-
  slider1:-10&lt;-120,6,1&gt;Threshold [dB]
+
  slider1:-10<-120,6,1>Threshold [dB]
   
   
  @init
  @init
Line 513: Line 505:
  @sample
  @sample
  maxsamples = max(abs(spl0),abs(spl1));
  maxsamples = max(abs(spl0),abs(spl1));
-
  maxsamples &gt; thresh ?
+
  maxsamples > thresh ?
     (
     (
         seekgain = 1;  
         seekgain = 1;  
Line 519: Line 511:
         seekgain = 0;
         seekgain = 0;
     );
     );
-
  gain &gt; seekgain ? (
+
  gain > seekgain ? (
     gain = gain / release + 0.00000000000001;
     gain = gain / release + 0.00000000000001;
  ):(
  ):(
Line 532: Line 524:
The functionality used in here is currently only available within REAPER(tm).
The functionality used in here is currently only available within REAPER(tm).
-
It is firmly recommanded you read the &quot;MIDI Functions&quot; Part of the Documentation
+
It is firmly recommanded you read the "MIDI Functions" Part of the Documentation
first, and get some information about how MIDI works, first. This chapter will deal with the
first, and get some information about how MIDI works, first. This chapter will deal with the
MIDI issue only superficially. It may, however, help to give you some idea on
MIDI issue only superficially. It may, however, help to give you some idea on
Line 539: Line 531:
  desc:MIDI Transpose
  desc:MIDI Transpose
   
   
-
  slider1:0&lt;-24,24,1&gt;Shift MIDI Note#
+
  slider1:0<-24,24,1>Shift MIDI Note#
   
   
  @slider
  @slider
Line 553: Line 545:
   (
   (
   
   
-
   status = msg1&amp;240; // get the status, i.e. e.g. 8*19 for note off, 9*19 for note on
+
   status = msg1&240; // get the status, i.e. e.g. 8*19 for note off, 9*19 for note on
   
   
     (status == 8*16 || status == 9*16) ?  
     (status == 8*16 || status == 9*16) ?  
     (
     (
   
   
-
       note = msg23&amp;127; // extract the note# (ranging from 0-127)
+
       note = msg23&127; // extract the note# (ranging from 0-127)
-
       velo = (msg23/256)&amp;127; // extract velocity (ranging from 0 - 127)
+
       velo = (msg23/256)&127; // extract velocity (ranging from 0 - 127)
       note = min(max(note+shift,0),127); // Calculate new note, and limit it to a range of 0 to 127
       note = min(max(note+shift,0),127); // Calculate new note, and limit it to a range of 0 to 127
       midisend(offset,msg1,note|(velo*256)); // MIDI send on/off
       midisend(offset,msg1,note|(velo*256)); // MIDI send on/off
Line 582: Line 574:
   (
   (
   
   
-
   status = msg1&amp;240; // get the status, i.e. e.g. 8*19 for note off, 9*19 for note on
+
   status = msg1&240; // get the status, i.e. e.g. 8*19 for note off, 9*19 for note on
   
   
     (status == 8*16 || status == 9*16) ?  
     (status == 8*16 || status == 9*16) ?  
     (
     (
   
   
-
       note = msg23&amp;127; // extract the note# (ranging from 0-127)
+
       note = msg23&127; // extract the note# (ranging from 0-127)
-
       vol = ((msg23/256)&amp;127) / 127; // extract velocity (ranging from 0 - 127) and divide through 127 to give it a range from 0-1
+
       vol = ((msg23/256)&127) / 127; // extract velocity (ranging from 0 - 127) and divide through 127 to give it a range from 0-1
   
   
       freq = 440 * 2^((note-69)/12); // convert from MIDI note to frequency
       freq = 440 * 2^((note-69)/12); // convert from MIDI note to frequency
Line 609: Line 601:
  spl0 += sin(wavePos)*vol;
  spl0 += sin(wavePos)*vol;
  spl1 += sin(wavePos)*vol;
  spl1 += sin(wavePos)*vol;
-
  (wavePos += waveSpeed) &gt;= 2*$pi ? wavePos -= 2*$pi;
+
  (wavePos += waveSpeed) >= 2*$pi ? wavePos -= 2*$pi;
[[Category:Jesusonic]] [[Category:Documentation]]
[[Category:Jesusonic]] [[Category:Documentation]]

Latest revision as of 00:11, 25 November 2010

This is the Wiki adaption of Michael "LOSER" Gruhn's 1st Ever Jesusonic Tutorial.

All of the following effects are just mere examples and may have flaws. But are even with those flaws useable as real effects.

All the effects have no copyrights and may be freely modified altered and/or used.

Contribution to this wiki page is welcome!

Contents

Mute

This FX will be a simple FX that mutes the output. So the describtion will be 'Mute'. To define a describltion for our FX, we add 'desc:' and after that we write a short describtion of your FX Like this:

desc:Mute

We do not need any '@init', '@slider', '@block', or '@serialize' code so we can just omit them, since we don't need to write them, when we don't need them.

Now to mute the output we need to manipulate the samples. To maniplulate samples we set up the '@sample' code, everything in (i.e. following the '@sample' line) is executed each and every sample the plug-in is running. So we add our '@sample' code:

@sample

Now in order to mute 'spl0' (left sample) and 'spl1' (right sample) we just set them to zero, by typing in the following:

spl0 = 0;
spl1 = 0;


The full code:

desc:Mute

@sample
spl0 = 0;
spl1 = 0;

Volume Adjust

This FX will be a simple volume adjustment plug-in. So the description will be:

desc:Volume

As we want the user to be able to adjust the volume, we need to give him/her a slider. To do this we add:

slider1: 0 < -120 , 60 , 1 >Volume [dB]

READ: Documentation: "Effect Format" - "2. 'slider' definition(s)" to get some more information about what this syntax does and what values we just set.

As we do not need any '@init', '@block', or '@serialize' code, we omit it.

But what we need to do is to convert the 'slider1' variable (from the user input) from dB into its amplitude value. This conversion needs some calculation so to save CPU we just convert whenever the slider is changed.

We do this by using the '@slider' code, which is called only when sliders are changed, look this up in your documentation to get more information on it.

@slider

To convert from dB to amplitude and store this as the variable 'volume', we add:

volume = 10 ^ ( slider1 / 20 );

What this conversion does is, it converts
0 dB To 1
-6.02.. dB To 0.5
6.02... dB To 2
-inf dB To 0
and so forth... Try searching for "dB" or decibel on "wikipedia.org" or "google.com" for more information on this subject.

Now to adjust the volume of the output we need to manipulate the samples. So we set up our '@sample' code:

@sample

To adjust the Volume of 'spl0' (left sample) and 'spl1' (right sample) we simply multiply them with our 'volume' variable, thus we add this:

spl0 = spl0 * volume;
spl1 = spl1 * volume;


Full code:

desc:Volume
slider1: 0 < -120 , 60 , 1 >Volume [dB]

@slider
volume = 10 ^ ( slider1 / 20 );

@sample
spl0 = spl0 * volume;
spl1 = spl1 * volume;

Stereo channel swap

This FX will swap the stereo channels (that is the right channel will be outputed as the left channel and vice versa).

desc:Stereo Channel Swap

Not needed stuff is omited.

@sample

In order to swap 'spl0' with 'spl1' we store 'spl0' in a temporary variable called 'tmp' (the name doesn't matter, but we use 'tmp' because it stands for temporary and the variable will only be used temporary).

tmp = spl0;

Since we have the value of 'spl0' saved in 'tmp' we can assign 'spl0' the value of 'spl1':

spl0 = spl1;

Next we can assign 'spl1' the value of 'tmp' (since we can't use 'spl0' anymore, because it got assigned the value of spl1 already):

spl1 = tmp;


Full code:

desc:Stereo Channel Swap

@sample

tmp = spl0;
spl0 = spl1;
spl1 = tmp;

Echo

Start with the describtion and user controls:

desc:Echo
slider1:120<0,1000,1>Length [ms]
@slider

Converting from ms (i.e. milliseconds) to samples like follows:

echolength = slider1 / 1000 * srate ;

Note: 'slider1 / 1000' gives us the value in seconds and this is then multiplied with the current samplerate to get the corresponding number of samples. ('Srate' a Jesusonic variable that will return the current samplerate you may look this up in your documentation.)

@sample

To create a echo, we need to store the current audio stream to replay it again later. The best way to do this, is to use the Jesusonics FX buffer. Just imagine the buffer to be a filing cabinet with alot of drawers, with each drawer having its own number (offset). So we just put the current sample into the buffer with the offset 'bufpos', for later playback. Read Documentation ("Reference" - "Operators" - "[ ]") to learn more about the buffer.

bufpos[0] = spl0 ;

Now we increment our buffer offset 'bufpos':

bufpos = bufpos + 1 ;

Next we need to check if the 'bufpos' has already reached our echo length, if so we have to reset it to the start i.e. zero (0). To do this we will use the '?' and '>' operators.

bufpos > echolength ? bufpos = 0;

This piece of code is basicly asking: "Is 'bufpos' greater than 'echolength'" (the 'bufpos > echolength' part), "if so then set 'bufpos' to zero" (the 'bufpos = 0' part).

Look this up in the Documentation ("Reference" - "Operators" - "?" and ">"), to get more information on the '?' and '>' operators.

And now we mix our echo buffer back to the signal. "How that? We have just stored it?" Yeah, but we have moved our offset, so we are 1 item ahead in the buffer and so our courser ('bufpos') points to the item we stored exactly 'echolength' samples ago (which is our echo length). So it is about time to mix it to the current sample.

We will add the following in order to mix 'spl0' with the buffer:

spl0 = spl0 + bufpos[0] ; 

And since a one sided echo sounds strange we just add the following to make it mono

spl1 = spl0 ;


Full code:

desc:Echo
slider1:120<0,1000,1>Length [ms]

@slider
echolength = slider1 / 1000 * srate ;

@sample
bufpos[0] = spl0 ;
bufpos = bufpos + 1 ;
bufpos > echolength ? bufpos = 0;
spl0 = spl0 + bufpos[0] ; 
spl1 = spl0 ;

Sine wave generator

desc:Sine-Wave-Generator
@sample

Okay generating a sine wave is simple:

spl0 = sin(2*$pi*440*t);

You got the 'sin( )' operator, with the common formula '2*$pi*f*t' in it. Where '$pi' is the by Jesusonic predefined variable for PI (~3.1415...). f (here '440') is the frequency and 't' is the "time" in seconds (actually our count variable 't').

Counting: Special notes here to the fact that we count with '1/srate' ('srate' = current samplerate), so 't' will count in seconds. That is important to make the above formula work. So we get:

t += 1 / srate ;
spl1 = spl0 ;


Full code:

desc:Sine-Wave-Generator

@sample
spl0 = .125 * sin(2*$pi*440*t);
t += 1 / srate ;
spl1 = spl0 ;

Limiter

desc:Limiter
slider1:0<-120,0,1>Threshold [dB]
@slider
thresh = 10 ^ ( slider1 / 20 );
@sample

You should be familiar with the above :).

Okay, to limit our signal we will use min(), and max(), which will return the minimum (min) and maximum (max) value of the two parameters. See Documentation for more information.

spl0 = min ( max(spl0,-thresh) , thresh );

So lets investigate the code: First we prevent it from getting a too negative value by adding 'max(spl0,-thresh)'. This no returns values that are either '-thresh' or greater. Now as the values must be greater than '-thresh' we need to prevent them from getting greater than 'thresh'. We do this by setting up 'min(MAX,thresh)' (with MAX=max(spl0,-thresh). This will return values that are smaller or even to 'thresh' but never greater than it. Those combined will result in the above code snippet.

For the right channel we will use a different method (one that I can tell you some more functions):

spl1 = min( abs(spl1),thresh ) * sign(spl1);

Here we use the 'abs()' function to get the absolute value of 'spl1'. Then we use 'min()' to get the minimum of either 'abs(spl1)' and 'thresh'. Since we now have the absolute value of 'spl1' that is below 'thresh' we use 'sign()' to get the sign (-1, 0 , 1) of 'spl1', to recreate its real value from the absolute value by multiplying it with 'sign(spl1)'.


Full code:

desc:Limiter
slider1:0<-120,0,1>Threshold [dB]

@slider
thresh = 10 ^ ( slider1 / 20 );

@sample
spl0 = min ( max(spl0,-thresh) , thresh );
spl1 = min ( max(spl1,-thresh) , thresh );

Pitch-Shifting

desc:Pitch-Shifting
slider1:1.5<.1,5,.1>Pitch
@sample

Buffering samples (like in the Echo FX):

bpos[0]=spl0;

Using an offset of 'srate/8' (our buffer length) for storing 'spl1' samples (to make it stereo):

bpos[(srate/8)]=spl1;

Playing back buffer with different speed by just simply multiplying 'bpos' (position in buffer) by 'slider1' (pitch):

spl0 = (bpos*slider1)[ -floor(bpos*slider1/(srate/8))*(srate/8) ];

Add '-floor(bpos*slider1/(srate/8))*(srate/8)' in the buffer brackets to make the reading from the buffer always jump back to the start when ever 'bpos*slider1' is breaching 'srate/8' (in case of pitch greater 1).

Right channel works the same way (only add + '(srate/8)' to process the part of the buffer the right channel samples are stored):

spl1 = (bpos*slider1)[ -floor(bpos*slider1/(srate/8))*(srate/8) + (srate/8) ];

Counting 'bpos', if greater or equal 'srate/8'(= 125 ms) reset:

(bpos+=1) >= (srate/8) ? bpos=0;

Now one could simply crossfade the jumps between each buffer run to get rid of the stuttering and then he would have a pretty decent Pitch-Shifting FX.


Full code:

desc:Pitch-Shifting
slider1:1.5<.1,5,.1>Pitch

@sample
bpos[0]=spl0;
bpos[(srate/8)]=spl1;
spl0 = (bpos*slider1)[ -floor(bpos*slider1/(srate/8))*(srate/8) ];
spl1 = (bpos*slider1)[ -floor(bpos*slider1/(srate/8))*(srate/8) + (srate/8) ];
(bpos+=1) >= (srate/8) ? bpos=0;

Compressor

desc:Compressor

slider1:-10<-120,6,1>Threshold [dB]
slider2:3<1,10,1>Ratio
@init

Initialize the gain to 1 (=0dB):

gain=1;

@slider
thresh = 10 ^ (slider1 / 20) ;
ratio = slider2 ;

Calculating the constant attack and release speed:

attack = 10 ^ ( (2000 / srate) / 20 );

Attack @ ~2000dB/Sec

release = 10 ^ ( (60 / srate) / 20 );

Release @ ~60dB/Sec

@sample

Tracking the maximum of the left and right samples:

maxsamples = max(abs(spl0),abs(spl1));

Check if about threshold, if about threshold, set 'seekgain' so the threshold and ratio settings entered by the user are met, and if not over threshold, set 'seekgain' to 1 (=0dB).

maxsamples > thresh ?
   (
       seekgain = (thresh + (maxsamples - thresh) / ratio) / maxsamples; 
   ) : (
       seekgain = 1
   );


Make 'gain' follow 'seekgain' with the specified attack and release speed:

gain > seekgain ? (gain /= attack; ):(gain *= release; );

Apply the gain:

spl0 *= gain;
spl1 *= gain;


Full code:

desc:Compressor
slider1:-10<-120,6,1>Threshold [dB]
slider2:3<1,10,1>Ratio

@init
gain=1;

@slider
thresh = 10 ^ (slider1 / 20) ;
ratio = slider2 ;
attack = 10 ^ ( (2000 / srate) / 20 );
release = 10 ^ ( (60 / srate) / 20 );

@sample
maxsamples = max(abs(spl0),abs(spl1));
maxsamples > thresh ?
   (
       seekgain = (thresh + (maxsamples - thresh) / ratio) / maxsamples; 
   ) : (
       seekgain = 1
   );
gain > seekgain ? (gain /= attack; ):(gain *= release; );
spl0 *= gain;
spl1 *= gain;

Gate

Start with this:

desc:Gate

slider1:-10<-120,6,1>Threshold [dB]

Initialize the gain to 1 (=0dB):

@init
gain=1;
@slider
thresh = 10 ^ (slider1 / 20);

Calculating the constant attack and release speed:

attack = 10 ^ ( (1000 / srate) / 20 );

attack @ ~1000dB/Sec

release = 10 ^ ( (30 / srate) / 20 );

release @ ~30dB/Sec

Set gain to 1 after slider move to prevent a zero stuck output:

gain = 1;
@sample

Tracking the maximum of the left and right samples:

maxsamples = max(abs(spl0),abs(spl1));

Check if about threshold:

maxsamples > thresh ?
    (

If about threshold set seekgain = 1 (~0dB):

        seekgain = 1; 
    ) : (

If under threshold set seekgain = 0 (~-INFdB):

        seekgain = 0;
    );


Make 'gain' follow 'seekgain' with the specified attack and release speed:

gain > seekgain ? (

Add a offset (here 0.00..1) to prevent denormals and also to prevent 'gain' from falling to 0 (Zero) and therefore breaking the algorithm (which consists of division and multiplication, which don't work anymore once 'gain'=0):

    gain = gain / release + 0.00000000000001;
):(
    gain = gain * attack + 0.00000000000001;
);

Apply the gain

spl0 *= gain;
spl1 *= gain;


Full code:

desc:Gate

slider1:-10<-120,6,1>Threshold [dB]

@init
gain=1;

@slider
thresh = 10 ^ (slider1 / 20);
attack = 10 ^ ( (1000 / srate) / 20 );
release = 10 ^ ( (30 / srate) / 20 );
gain = 1;

@sample
maxsamples = max(abs(spl0),abs(spl1));
maxsamples > thresh ?
    (
        seekgain = 1; 
    ) : (
        seekgain = 0;
    );
gain > seekgain ? (
    gain = gain / release + 0.00000000000001;
):(
    gain = gain * attack + 0.00000000000001;
);
spl0 *= gain;
spl1 *= gain;

MIDI Transpose

This chapter deals with MIDI. The functionality used in here is currently only available within REAPER(tm).

It is firmly recommanded you read the "MIDI Functions" Part of the Documentation first, and get some information about how MIDI works, first. This chapter will deal with the MIDI issue only superficially. It may, however, help to give you some idea on how to implement it in your effects.

desc:MIDI Transpose

slider1:0<-24,24,1>Shift MIDI Note#

@slider
shift = slider1;

@block

Listen for MIDI notes as long as there are MIDI notes coming in the code gets evaluated:

while (midirecv(offset,msg1,msg23) ? 
 
 (

  status = msg1&240; // get the status, i.e. e.g. 8*19 for note off, 9*19 for note on

    (status == 8*16 || status == 9*16) ? 
    (

      note = msg23&127; // extract the note# (ranging from 0-127)
      velo = (msg23/256)&127; // extract velocity (ranging from 0 - 127)
      note = min(max(note+shift,0),127); // Calculate new note, and limit it to a range of 0 to 127
      midisend(offset,msg1,note|(velo*256)); // MIDI send on/off
      
    ):(

      midisend(offset,msg1,msg23); // pass other MIDI events

    );

 );
);

MIDI Synth

desc:MIDI Synth

Put the MIDI recieve code in the '@block' code. Define 'waveSpeed' and 'wavePos' there to represent the MIDI note in frequency ('waveSpeed' and 'wavePos' will feed a sine wave generator (like it was already explained earlier) in the '@sample' code).

@block
while (midirecv(offset,msg1,msg23) ? 
 (

  status = msg1&240; // get the status, i.e. e.g. 8*19 for note off, 9*19 for note on

    (status == 8*16 || status == 9*16) ? 
    (

      note = msg23&127; // extract the note# (ranging from 0-127)
      vol = ((msg23/256)&127) / 127; // extract velocity (ranging from 0 - 127) and divide through 127 to give it a range from 0-1

      freq = 440 * 2^((note-69)/12); // convert from MIDI note to frequency
      waveSpeed = (2*$pi*freq)/srate; // calculate waveSpeed
      wavePos = 0; // reset wavePos
      status == 8*16 ? vol = 0; // mute sine wave on note off
      
    ):(

      midisend(offset,msg1,msg23); // pass other MIDI events

    );

 );
);

Now render a sine wave in the '@sample' code:

@sample
spl0 += sin(wavePos)*vol;
spl1 += sin(wavePos)*vol;
(wavePos += waveSpeed) >= 2*$pi ? wavePos -= 2*$pi;