1st Ever Jesusonic Tutorial

From CockosWiki

(Difference between revisions)
Jump to: navigation, search
Line 1: Line 1:
-
This is the Wiki adaption of LOSER's 1st Ever Jesusoinc Tutorial. It is transfered right now and may be unfinished at the moment.
+
This is the Wiki adaption of Michael Gruhn's 1st Ever Jesusoinc Tutorial. It is under transfere right now and therefore may be unfinished at the moment.
Line 433: Line 433:
     );
     );
  gain > seekgain ? (gain /= attack; ):(gain *= release; );
  gain > seekgain ? (gain /= attack; ):(gain *= release; );
 +
spl0 *= gain;
 +
spl1 *= gain;
 +
 +
 +
== Gate ==
 +
 +
Start with this:
 +
 +
desc:Gate
 +
 +
slider1:-10<-120,6,1>Treshold [dB]
 +
 +
Initialize the gain to 1 (=0dB):
 +
 +
@init
 +
gain=1;
 +
 +
@slider
 +
tresh = 2 ^ (slider1 / 6);
 +
 +
Calculating the constant attack and release speed:
 +
attack = 2 ^ ( (1000 / srate) / 6 );
 +
attack @ ~1000dB/Sec
 +
 +
release = 2 ^ ( (30 / srate) / 6 );
 +
release @ ~30dB/Sec
 +
 +
Set gain to 1 after slider move tp 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 treshold
 +
maxsamples > tresh ?
 +
    (
 +
if about treshold set seekgain = 1 (~0dB)
 +
        seekgain = 1;
 +
    ) : (
 +
if about treshold 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 gain falling to 0 (Zero)
 +
and MAY therefore break the algorithm (which consists of division and multiplication)
 +
    gain /= release + 0.00000000000001;
 +
):(
 +
    gain *= attack + 0.00000000000001;
 +
);
 +
 +
Apply the gain
 +
spl0 *= gain;
 +
spl1 *= gain;
 +
 +
 +
Full code:
 +
 +
desc:Gate
 +
 +
slider1:-10<-120,6,1>Treshold [dB]
 +
 +
@init
 +
gain=1;
 +
 +
@slider
 +
tresh = 2 ^ (slider1 / 6);
 +
attack = 2 ^ ( (1000 / srate) / 6 );
 +
release = 2 ^ ( (30 / srate) / 6 );
 +
gain = 1;
 +
 +
@sample
 +
maxsamples = max(abs(spl0),abs(spl1));
 +
maxsamples > tresh ?
 +
    (
 +
        seekgain = 1;
 +
    ) : (
 +
        seekgain = 0;
 +
    );
 +
gain > seekgain ? (
 +
    gain /= release + 0.00000000000001;
 +
):(
 +
    gain *= attack + 0.00000000000001;
 +
);
  spl0 *= gain;
  spl0 *= gain;
  spl1 *= gain;
  spl1 *= gain;

Revision as of 18:30, 11 February 2007

This is the Wiki adaption of Michael Gruhn's 1st Ever Jesusoinc Tutorial. It is under transfere right now and therefore may be unfinished at the moment.


Contents

Mute

This FX will be a simple FX that mutes the output. So the describtion will be 'Mute'. To define a describltion you just add 'desc:' and after that you 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 writing them isn't required, when you don't need them.

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

@sample

To mute 'spl0' (left sample) and 'spl1' (right sample) we just set them to zero, by typing 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 adjust 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 just 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 the 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.

To do this we use 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 just type:

volume = 2 ^ ( slider1 / 6 );

What this conversion does, is to convert
0 dB To 1
-6 dB To 0.5
6 dB To 2
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 put 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 add this:

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


Full code:

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

@slider
volume = 2 ^ ( slider1 / 6 );

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


Stereo channel swap

This FX will swap the stereo channels

desc:Stereo Channel Swap

not needed stuff omited

@sample

To swap 'spl0' with 'spl1' we store 'spl0' in a temporary variable 'tmp' (the name doesn't matter)

tmp = spl0;

Now since we have the value of 'spl0' saved in 'tmp' we can assign 'spl0' the value of 'spl1'

spl0 = spl1;

and now we assign 'spl1' the value of 'tmp' (since we can't use 'spl0' anymore).

spl1 = tmp;


Full code:

desc:Stereo Channel Swap

@sample

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


Echo

Start with the settings:

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

Converting from ms (i.e. milliseconds) to samples

echolength = slider1 / 1000 * srate ;

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

@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 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 incrementing our buffer offset 'bufpos'

bufpos = bufpos + 1 ;

Now 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.

Just write this in order to mix 'spl0' with the buffer

spl0 = spl0 + bufpos[0] ; 

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 = .125 * sin(2*$pi*440*t);

Note: '.125' is just a volume scaling factor ('cause I gotta hear All this while typing this.)

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. f (here '440') is the frequency and 't' is the time in seconds (actually our count variable 't')

Counting: Special here: we count with '1/srate' ('srate' = current samplerate), so 't' will count the seconds. Important to make the above formula work.

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>Treshold [dB]
@slider
tresh = 2 ^ ( slider1 / 6 );

You should be familiar with the above :)

@sample

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

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

So lets investigate the code: First we prevent it from getting a too big negative value. So we add 'max(spl0,-tresh)'. This will return us values that are either '-tresh' or bigger. No as the values must be greater than '-tresh' we must prevent them from getting bigger than 'tresh'. We do this by setting up 'min(MAX,tresh)' (MAX=max(spl0,-tresh). This will return values that are smaller or even to 'tresh' but never above.

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

spl1 = min( abs(spl1),tresh ) * 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 'tresh'. Now since we have the absolute value of 'spl1' we use 'sign()' to get the sign (-1, 0 , 1) of 'spl1', so we can recreate its real value from the absolute value by multiplying it with 'sign(spl1)'.


Full code:

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

@slider
tresh = 2 ^ ( slider1 / 6 );

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


Pitch-Shifting

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

Buffering samples

bpos[0]=spl0;

Using an offset of 'srate/8' (our buffer length) for storing 'spl1' samples

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) ];

The '-floor(bpos*slider1/(srate/8))*(srate/8)' in the buffer brackets makes theReading From buffer always jump back to the start when ever 'bpos*slider1' is breaching 'srate/8' (in case of pitch greater 1).

Right channel analog

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 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>Treshold [dB]
slider2:3<1,10,1>Ratio
@init

Initialize the gain to 1 (=0dB)

gain=1;

@slider
tresh = 2 ^ (slider1 / 6) ;
ratio = slider2 ;

Calculating the constant attack and release speed

attack = 2 ^ ( (2000 / srate) / 6 );

Attack @ ~2000dB/Sec

release = 2 ^ ( (60 / srate) / 6 );

Release @ ~60dB/Sec

@sample

Tracking the maximum of the left and right samples

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

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

maxsamples > tresh ?
   (
       seekgain = tresh + (maxsamples - tresh) / ratio; 
   ) : (
       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>Treshold [dB]
slider2:3<1,10,1>Ratio

@init
gain=1;

@slider
tresh = 2 ^ (slider1 / 6) ;
ratio = slider2 ;
attack = 2 ^ ( (2000 / srate) / 6 );
release = 2 ^ ( (60 / srate) / 6 );

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


Gate

Start with this:

desc:Gate

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

Initialize the gain to 1 (=0dB):

@init
gain=1;
@slider
tresh = 2 ^ (slider1 / 6);

Calculating the constant attack and release speed:

attack = 2 ^ ( (1000 / srate) / 6 );

attack @ ~1000dB/Sec

release = 2 ^ ( (30 / srate) / 6 );

release @ ~30dB/Sec

Set gain to 1 after slider move tp 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 treshold

maxsamples > tresh ?
    (

if about treshold set seekgain = 1 (~0dB)

        seekgain = 1; 
    ) : (

if about treshold 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 gain falling to 0 (Zero) and MAY therefore break the algorithm (which consists of division and multiplication)

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

Apply the gain

spl0 *= gain;
spl1 *= gain;


Full code:

desc:Gate

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

@init
gain=1;

@slider
tresh = 2 ^ (slider1 / 6);
attack = 2 ^ ( (1000 / srate) / 6 );
release = 2 ^ ( (30 / srate) / 6 );
gain = 1;

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


MIDI Transpose

Okay, 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 idea about how MIDI works. 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

    );

 );
);