 |
|
|
09-05-2016, 08:42 PM
|
#1
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
ReaRack Modular Synth
Edit 12/12/2017
Version 2.0 release. See message here for details - https://forum.cockos.com/showpost.ph...&postcount=140
Edit 9/8/2017
Update 1.4, see message here for details - https://forum.cockos.com/showpost.ph...9&postcount=96
Original post:
It's taken me a while, but my JSFX learning project is now complete, I think. I have been attempting to create a modular synth system. It is fairly basic in that there are no provisions to prevent aliasing apart from the ocsillator being hard limited at just below the Nyquist frequency. IMHO the system seems to work surprisingly well and could be useful for learning about sound synthesis. It is capable of subtractive, additive and rudimentary FM synthesis. It's here in the stash for anyone interesting in trying it out (there may still be bugs in it):
https://stash.reaper.fm/28403/ReaRack-ModularSynth.zip
The description reads as follows:
--------
A bunch of JSFX modules that can be used for modular synthesis. ReaRack is a MIDI controlled digital synth system modeled on voltage controlled analog hardware synths. It is a monophonic system but polyphony is possible using the included poly splitter module.
Three example projects are included in the zip file.
Currently there are 9 modules: Oscillator, LFO, Envelope generator,Filter, Amplifier, CC mixer, Trigger, Poly splitter and Key follower. Some modules (used for multiple voices) have a master/slave function so that certain parameters can be linked for ease of setup. Key module parameters can be modulated directly using the MIDI CC inputs, for those that can't, if need be, use REAPERS's parameter modulation. Modules receive MIDI on all channels. MIDI output can be directed to individual channels. For input channel filtering, use the REAPER track routing.
-------
Further to the description, I should add that to help with additive synthesis, there is a provision in the oscillator to select a harmonic of the fundamental as the oscillator pitch.
I have also included an 'Audio Modulation' section on the oscillator, whereby any preceding audio can be used for modulation in one of three ways:
1. The input audio and the oscillator output can be multiplied together to create a ring modulation effect.
2. The input audio can be used to modulate the frequency of the oscillator (FM synthesis).
3. The oscillator can be used to modulate the amplitude of any incoming audio.
Last edited by Time Waster; 12-12-2017 at 06:02 AM.
Reason: Notice of Update
|
|
|
09-06-2016, 12:09 AM
|
#2
|
Human being with feelings
Join Date: Jun 2008
Posts: 4,923
|
excited to try this!
once you are happy please consider making available via ReaPack...
|
|
|
09-06-2016, 01:52 AM
|
#3
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
Quote:
Originally Posted by semiquaver
....
once you are happy please consider making available via ReaPack...
|
How do I do that? Are there instructions somewhere?
|
|
|
09-06-2016, 02:10 AM
|
#4
|
Human being with feelings
Join Date: Jul 2016
Posts: 92
|
|
|
|
09-06-2016, 07:25 PM
|
#5
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
Quote:
Originally Posted by xbitz_
|
I'm not currently using Github, but I will look into it.
|
|
|
09-06-2016, 07:27 PM
|
#6
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
To anyone who has tried out ReaRack, is it self explanatory, or do I need to write a manual?
|
|
|
09-06-2016, 09:52 PM
|
#7
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 13,773
|
IMHO, a manual is always necessary. Hopefully ReaPack allows managing manuals together with the code and prides se4arch functions to allow potential users to find what he is searching for based on keywords provided in the docks (manuals) of any JSFX.
-Michael
|
|
|
09-06-2016, 11:13 PM
|
#8
|
Human being with feelings
Join Date: Apr 2007
Posts: 370
|
Hey this is super cool !!! Played with it a bit, nice possibilities esp with FM stuff.
Thanks !!
|
|
|
09-07-2016, 04:31 AM
|
#9
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
Thanks for trying it out. I would be interested to know if anyone has issues with aliasing when using the FM function. I'm probably to deaf to hear it.
|
|
|
09-07-2016, 04:58 AM
|
#10
|
Human being with feelings
Join Date: Apr 2007
Posts: 370
|
Oh Im not the one to ask, I would be pretty happy with ton of aliasing, 4bit resolution and super distorted output
|
|
|
09-07-2016, 05:19 AM
|
#11
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
I tend to agree with you, but it's an issue for some. One of my favorite VSTi's is 'Mr Alias' by The Piz. I don't actually use it much, but it's very funny.
|
|
|
09-07-2016, 02:05 PM
|
#12
|
Human being with feelings
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
|
8bit 4bit 1bit music is much fun. Reminds me of my Sinclair ZX81 and Z80 assembly code... squarish sounds
For people that care about aliasing, oversampling is an option.
Here is a thread that describes some recipe:
http://forum.cockos.com/showthread.php?t=178543
The other option is to use a higher sampling rate for the project if your soundcard and CPU can support it.
|
|
|
09-07-2016, 04:57 PM
|
#13
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
A manual is on the way, but it could take a few days.  In the meantime, here is an excerpt which outlines my self imposed design guidelines:
MIDI messaging:
•MIDI is transmitted generally once per block. This is to maintain compatibility with hardware devices.
•The modules receive MIDI on all channels. There is no provision for input channel filtering. This helps when setting up polyphonic voicing. Each voice is created on a separate track and is a copy of the original voice setup, i.e. the original track is duplicated according to how many voices you require (up to 16). Each voice track is then set to receive midi on only one MIDI channel, which is a lot easier than having to set the input for channel for every module. The Poly Splitter module is used to direct overlapping notes to separate channels.
•The modules can be set to transmit MIDI data on individual channels, or on All channels, as required
•All unmodified MIDI messages are passed through, so any one set of CC messages can be used to control multiple modules.
Slider Value Sharing:
Slider values can be communicated across instances of the same module (using global memory). This is achieved by a ‘class’ system. There are three class states; Master, Slave and None. There is also a ‘Class Group’ option to allow multiple groups of the same module to share differing sets of slider values. Each group has one instance of the module designated as the Master and the rest are designated as Slaves. Any slider adjustments made on the Master are duplicated on the slaves.
Not all slider values are communicated, only those that are required for voicing. On the slider names, shared are marked with an asterisk *. Slider value sharing is not mandatory, generally it is only necessary for modules used for voicing on polyphonic setups.
Slider Layout:
Starting from the top:
•MIDI CC Input selection sliders
•MIDI CC Output selection sliders
•MIDI Output Channel selection slider
•
•Module specific sliders
•
•Class slider
•Class Group slider
Not all modules have all of these sets of sliders, and some may have none, but any that exist are placed in the same order for user interface consistency.
Graphics:
•Each module has some simple graphics to provide visual feedback.
Last edited by Time Waster; 09-07-2016 at 07:50 PM.
Reason: Forgot to add the bit about slider value sharing.
|
|
|
09-08-2016, 08:45 AM
|
#14
|
Human being with feelings
Join Date: Dec 2012
Posts: 7,122
|
May I ask what's the difference between this...
Quote:
1. The input audio and the oscillator output can be multiplied together to create a ring modulation effect.
|
...and this...
Quote:
3. The oscillator can be used to modulate the amplitude of any incoming audio.
|
???
|
|
|
09-08-2016, 04:04 PM
|
#15
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
In amplitude modulation the modulator is converted into a unipolar wave form (the values are always positive), whereas in ring modulation the modulator has both positive and negative values. Amplitude modulation is basically a high frequency tremelo effect. Ring modulation was famously used for the Dalek voices in the Dr Who series. They are similar sounding effects, but not the same.
|
|
|
09-09-2016, 08:47 AM
|
#16
|
Human being with feelings
Join Date: Dec 2012
Posts: 7,122
|
^^^^When I first read that, I was thinking full-wave rectified, but now I think I understand you mean like DC offset and probably attenuated. Like 0.5x + 0.5, no? Yup, that'll be a bit different from true ring mod. Probably should have been obvious to begin with. Sorry.
I guess it'd be an interesting feature and maybe convenient to have it on the osc module, but it does beg the question of how modular you want to get. In the end, this could be accomplished with a seperate VCA and/or ring mod module, both of which could be used elsewhere for other things. With plugins we can literally instantiated as many as we want/need without having to worry about running out of space in our rack. Like, if you need another VCA, you don't have to go buy one, just click a couple of times. I kind of hate redundant code.
|
|
|
09-10-2016, 05:03 AM
|
#17
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
Quote:
Originally Posted by ashcat_lt
I guess it'd be an interesting feature and maybe convenient to have it on the osc module, but it does beg the question of how modular you want to get. In the end, this could be accomplished with a seperate VCA and/or ring mod module, both of which could be used elsewhere for other things. With plugins we can literally instantiated as many as we want/need without having to worry about running out of space in our rack. Like, if you need another VCA, you don't have to go buy one, just click a couple of times. I kind of hate redundant code.
|
You are right that it could be done with another module. However I needed to do the frequency modulation in the oscillator module, to avoid having to do FFT or whatever to with a separate module (I don't understand the maths behind more than very basic level DSP). Once I had figured out how to use the audio input for the FM, I realised that I could easily add the ring and amplitude modulation, without needing any additional sliders.
Last edited by Time Waster; 09-11-2016 at 07:32 AM.
|
|
|
09-10-2016, 10:29 AM
|
#18
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
I have added a new operation to the CC Mixer module. I called it 'Overlay'. It just takes the maximum value of the two CC inputs. I also fixed a graphics bug. I will get around to uploading it to the stashb ut in the meantime, here is the revised code:
Code:
version: 1.1.0
desc:ReaRack - CC Mixer
author: Malcolm Smith
changelog: Added the Overlay operation option. Fixed a graphics bug.
/*Version 1.0.0 (2/9/2016) Initial release.
Version 1.1.0 (9/9/2016) Added the Overlay operation option. Fixed a graphics bug.
Copyright(C) 2016 and later, Malcolm Smith (username 'Time Waster' on REAPER forums).
License: LGPL - http://www.gnu.org/licenses/lgpl.html
*/
slider1:20<0,127,1{0 Bank Sel M,1 Mod Wheel M,2 Breath M,3,4 Foot P M,5 Porta M,6 Data Entry M,7 Vol M,8 Balance M,9,10 Pan M,11 Expression M,12 Ctrl 1 M,13 Ctrl 2 M,14,15,16 GP Slider 1,17 GP Slider 2,18 GP Slider 3,19 GP Slider 4,20,21,22,23,24,25,26,27,28,29,30,31,32 Bank Sel L,33 Mod Wheel L,34 Breath L,35,36 Foot P L,37 Porta L,38 Data Entry L,39 Vol L,40 Balance L,41,42 Pan L,43 Expression L,44 Ctrl 1 L,45 Ctrl 2 L,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 Hold P sw,65 Porta sw,66 Sustenuto sw,67 Soft P sw,68 Legato P sw,69 Hold 2 P sw,70 S.Variation,71 S.Timbre,72 S.Release,73 S.Attack,74 S.Brightness,75 S.Ctrl 6,76 S.Ctrl 7,77 S.Ctrl 8,78 S.Ctrl 9,79 S.Ctrl 10,80 GP B.1 sw,81 GP B.2 sw,82 GP B.3 sw,83 GP B.4 sw,84,85,86,87,88,89,90,91 Effects Lv,92 Trem Lv,93 Chorus Lv,94 Celeste Lv,95 Phaser Lv,96 Data B. Inc,97 Data B. Dec,98 NRP L,99 NRP M,100 RP L,101 RP M,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127}>CC Input 1
slider2:21<0,127,1{0 Bank Sel M,1 Mod Wheel M,2 Breath M,3,4 Foot P M,5 Porta M,6 Data Entry M,7 Vol M,8 Balance M,9,10 Pan M,11 Expression M,12 Ctrl 1 M,13 Ctrl 2 M,14,15,16 GP Slider 1,17 GP Slider 2,18 GP Slider 3,19 GP Slider 4,20,21,22,23,24,25,26,27,28,29,30,31,32 Bank Sel L,33 Mod Wheel L,34 Breath L,35,36 Foot P L,37 Porta L,38 Data Entry L,39 Vol L,40 Balance L,41,42 Pan L,43 Expression L,44 Ctrl 1 L,45 Ctrl 2 L,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 Hold P sw,65 Porta sw,66 Sustenuto sw,67 Soft P sw,68 Legato P sw,69 Hold 2 P sw,70 S.Variation,71 S.Timbre,72 S.Release,73 S.Attack,74 S.Brightness,75 S.Ctrl 6,76 S.Ctrl 7,77 S.Ctrl 8,78 S.Ctrl 9,79 S.Ctrl 10,80 GP B.1 sw,81 GP B.2 sw,82 GP B.3 sw,83 GP B.4 sw,84,85,86,87,88,89,90,91 Effects Lv,92 Trem Lv,93 Chorus Lv,94 Celeste Lv,95 Phaser Lv,96 Data B. Inc,97 Data B. Dec,98 NRP L,99 NRP M,100 RP L,101 RP M,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127}>CC Input 2
slider3:22<0,127,1{0 Bank Sel M,1 Mod Wheel M,2 Breath M,3,4 Foot P M,5 Porta M,6 Data Entry M,7 Vol M,8 Balance M,9,10 Pan M,11 Expression M,12 Ctrl 1 M,13 Ctrl 2 M,14,15,16 GP Slider 1,17 GP Slider 2,18 GP Slider 3,19 GP Slider 4,20,21,22,23,24,25,26,27,28,29,30,31,32 Bank Sel L,33 Mod Wheel L,34 Breath L,35,36 Foot P L,37 Porta L,38 Data Entry L,39 Vol L,40 Balance L,41,42 Pan L,43 Expression L,44 Ctrl 1 L,45 Ctrl 2 L,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 Hold P sw,65 Porta sw,66 Sustenuto sw,67 Soft P sw,68 Legato P sw,69 Hold 2 P sw,70 S.Variation,71 S.Timbre,72 S.Release,73 S.Attack,74 S.Brightness,75 S.Ctrl 6,76 S.Ctrl 7,77 S.Ctrl 8,78 S.Ctrl 9,79 S.Ctrl 10,80 GP B.1 sw,81 GP B.2 sw,82 GP B.3 sw,83 GP B.4 sw,84,85,86,87,88,89,90,91 Effects Lv,92 Trem Lv,93 Chorus Lv,94 Celeste Lv,95 Phaser Lv,96 Data B. Inc,97 Data B. Dec,98 NRP L,99 NRP M,100 RP L,101 RP M,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127}>CC Output
slider4:0<0,15,1{All,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}>MIDI Output Channel
slider5:1<0,1>Input 1 Limit
slider6:1<0,1>Input 2 Limit
slider7:0<0,2,1{Multiply,Add,Overlay}>Operation
in_pin:none
out_pin:none
@slider
ccIn1 = slider1;
ccIn2 = slider2;
ccOut = slider3;
chanOut = slider4-1;
lev1 = slider5;
lev2 = slider6;
op = slider7;
@block
while (midirecv(offset, msg1, msg2, msg3))
(
// Extract message type
modstatus = msg1;
status = msg1 & $xF0;
//Is it not a controller event?
status != $xB0 ? midisend(offset, msg1, msg2, msg3);//Pass thru
//Is it not either input CC?
msg2 != cc1in || cc2in ? midisend(offset, msg1, msg2, msg3);//Pass thru
// Is it a controller event?
// Is it the right CC for input 1?
status == $xB0 && msg2 == ccIn1 ?
(
val1 = msg3;
ccIn1 != ccOut ? midisend(offset, msg1, msg2, msg3);
);
// Is it a controller event?
// Is it the right CC for input 2?
//channel == chanIn2 &&
status == $xB0 && msg2 == ccIn2 ?
(
val2 = msg3;
ccIn2 != ccOut ? midisend(offset, msg1, msg2, msg3);
);
);
op == 0 ?
(
// Multiply values together
val1att = (1-(lev1*(1-(val1/127))));
val2att = (1-(lev2*(1-(val2/127))));
val3 = floor((127*(val1att*val2att))+0.5);
);
op == 1 ?
(
// Add values together
val1att = (val1*lev1)/127; //used @gfx
val2att = (val2*lev2)/127; //used @gfx
val3 = floor((min((val1*lev1)+(val2*lev2),127))+0.5);
);
op == 2 ?
(
// Overlay Values
val1att = (val1*lev1)/127; //used @gfx
val2att = (val2*lev2)/127; //used @gfx
val3 = floor((max(val1*lev1,val2*lev2))+0.5);
);
//Send new CC message
chanout == -1 ? (
n = 0;
loop(16,
midisend(offset,$xB0+n,ccOut,val3);
n += 1;
);
):(
midisend(offset,$xB0+chanOut,ccOut,val3);
);
@gfx 400 180
gfx_r = 0;
gfx_g = 1;
gfx_b = 0;
gfx_a = 1;
////////////////////input 1 meter///////////////////
gfx_x=50;
gfx_y=25+127;
gfx_lineto(50,(25+127)-(val1att*127));
gfx_lineto(60,(25+127)-(val1att*127));
gfx_lineto(60,(25+127));
////////////////////input 2 meter///////////////////
gfx_x=150;
gfx_y=25+127;
gfx_lineto(150,(25+127)-(val2att*127));
gfx_lineto(160,(25+127)-(val2att*127));
gfx_lineto(160,(25+127));
////////////////////output meter////////////////////
gfx_x=250;
gfx_y=25+127;
gfx_lineto(250,(25+127)-val3);
gfx_lineto(260,(25+127)-val3);
gfx_lineto(260,(25+127));
////////////////////////level lines/////////////////
gfx_r = 1;
gfx_g = 0;
gfx_a = 0.5;
gfx_x = 25;
gfx_y = 25;
gfx_lineto(25+(260),25);
gfx_x = 25;
gfx_y = 25+127;
gfx_lineto(25+(260),25+127);
gfx_x=50;
op == 0 ?
(
gfx_y=25+127-(127-(lev1*127));
gfx_lineto(100,25+127-(127-(lev1*127)));
gfx_x=150;
gfx_y=25+127-(127-(lev2*127));
gfx_lineto(200,25+127-(127-(lev2*127)));
)
:
(
gfx_y=25+127-(lev1*127);
gfx_lineto(100,25+127-(lev1*127));
gfx_x=150;
gfx_y=25+127-(lev2*127);
gfx_lineto(200,25+127-(lev2*127));
);
////////////////////////text////////////////////////
gfx_a =1;
gfx_x = 13;
gfx_y = 20;
gfx_drawstr("1");
gfx_x = 13;
gfx_y = 20+127;
gfx_drawstr("0");
gfx_x = 25+265;
gfx_y = 20;
gfx_drawstr("(127)");
gfx_x = 25+265;
gfx_y = 20+127;
gfx_drawstr("(0)");
gfx_a = 1;
op == 0 ?
(
gfx_x=65;
gfx_y=25+117-(127-(lev1*127));
gfx_drawstr("Min.");
gfx_x=165;
gfx_y=25+117-(127-(lev2*127));
gfx_drawstr("Min.");
)
:
(
gfx_x=65;
gfx_y=25+117-(lev1*127);
gfx_drawstr("Max.");
gfx_x=165;
gfx_y=25+117-(lev2*127);
gfx_drawstr("Max.");
);
gfx_r = 0;
gfx_g = 1;
gfx_a = 1;
gfx_x = 35;
gfx_y = 30+127;
gfx_drawstr("Input 1 ");
op == 0 ? gfx_drawstr("x"):gfx_drawstr("+");
gfx_drawstr(" Input 2 = Output");
|
|
|
09-10-2016, 10:32 AM
|
#19
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
I also found a bug in the Trigger module which was preventing it from triggering on a CC value of 0. Again, here is the revised code:
Code:
version: 1.0.1
desc:ReaRack - Trigger
author: Malcolm Smith
changelog: Fixed a timing bug at 0 and 127 cc values
/* 1.0.0 (2/9/2016) Initial Release.
1.0.1 (9/9/2016) Fixed a timing bug at 0 and 127 cc values.
Copyright(C) 2016 and later, Malcolm Smith (username 'Time Waster' on REAPER forums).
License: LGPL - http://www.gnu.org/licenses/lgpl.html
*/
slider1:20<0,127,1{0 Bank Sel M,1 Mod Wheel M,2 Breath M,3,4 Foot P M,5 Porta M,6 Data Entry M,7 Vol M,8 Balance M,9,10 Pan M,11 Expression M,12 Ctrl 1 M,13 Ctrl 2 M,14,15,16 GP Slider 1,17 GP Slider 2,18 GP Slider 3,19 GP Slider 4,20,21,22,23,24,25,26,27,28,29,30,31,32 Bank Sel L,33 Mod Wheel L,34 Breath L,35,36 Foot P L,37 Porta L,38 Data Entry L,39 Vol L,40 Balance L,41,42 Pan L,43 Expression L,44 Ctrl 1 L,45 Ctrl 2 L,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 Hold P sw,65 Porta sw,66 Sustenuto sw,67 Soft P sw,68 Legato P sw,69 Hold 2 P sw,70 S.Variation,71 S.Timbre,72 S.Release,73 S.Attack,74 S.Brightness,75 S.Ctrl 6,76 S.Ctrl 7,77 S.Ctrl 8,78 S.Ctrl 9,79 S.Ctrl 10,80 GP B.1 sw,81 GP B.2 sw,82 GP B.3 sw,83 GP B.4 sw,84,85,86,87,88,89,90,91 Effects Lv,92 Trem Lv,93 Chorus Lv,94 Celeste Lv,95 Phaser Lv,96 Data B. Inc,97 Data B. Dec,98 NRP L,99 NRP M,100 RP L,101 RP M,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127}>CC Input
slider2:1<0,15,1{All,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}>MIDI Output Channel
slider3:0<0,1,1{Rising Edge,Falling Edge}>Trigger on:
slider4:0<0,127,1>Trigger CC Value
slider5:69<0,127,1>Output Note
slider6:127<0,127,1>Velocity
slider7:0.1<0.1,10,0.001>Trigger Hold (seconds)
in_pin:none
out_pin:none
options:gmem=ReRackTrig
@init
rsent = 0;
fsent = 0;
holdon = 0;
preccval = 0;
note[1] = "C";
note[2] = "C#";
note[3] = "D";
note[4] = "D#";
note[5] = "E";
note[6] = "F";
note[7] = "F#";
note[8] = "G";
note[9] = "G#";
note[10] = "A";
note[11] = "A#";
note[12] = "B";
@slider
ccin = slider1;
outChan = slider2-1;
edge = slider3;
trigval =slider4;
noteval = slider5;
notevel = slider6;
holdsec = slider7;
gnoteval = noteval % 12;
gnote = note[gnoteval+1];
goctave = (noteval - gnoteval)/12;
@block
hold = holdsec*(srate/samplesblock);
while (midirecv(offset, msg1, msg2, msg3))
(
// Extract message type
status = msg1 & $xF0;
// Is it a controller event?
status == $xB0 ?
(
// Is it the right CC?
msg2 == ccin ?
(
ccval = msg3;
);
);
// Pass thru
midisend(offset, msg1, msg2, msg3);
);
preccval < ccval ? rise = 1;
preccval > ccval ? rise = 0;
prerise - rise == 1 ? rsent = 0;
prerise - rise == -1 ? fsent = 0;
rise == 0 && ccval == 0 ? (rsent = 0; rise = 1);
rise == 1 && ccval == 127 ? (fsent = 0; Rise = 0);
edge == 0 ?
(
ccval >= trigval && rise == 1 && rsent == 0 ?
(
outChan == -1 ?
(
n = 0;
loop(16,
midisend(offset,$x90+n,noteval,notevel);
n += 1;
);
) : (
midisend(offset,$x90+outChan,noteval,notevel);
);
rsent = 1;
holdon = 1;
blockcount = 0;
);
);
edge == 1 ?
(
ccval <= trigval && rise == 0 && fsent == 0 ?
(
outChan == -1 ?
(
n = 0;
loop(16,
midisend(offset,$x90+n,noteval,notevel);
n += 1;
)
) : (
midisend(offset,$x90+outChan,noteval,notevel);
;
);
fsent = 1;
holdon = 1;
blockcount = 0;
);
);
preccval = ccval;
prerise = rise;
blockcount >= hold ?
(
holdon == 1 ?
(
chanout == -1 ?
(
n = 0;
loop(16,
midisend(offset+n,$x80+n,noteval);
n += 1;
)
) : (
midisend(offset,$x80&outChan,noteval);
);
holdon = 0;
);
);
blockcount += 1;
@gfx 400 150
gfx_x = 225;
gfx_y = 17;
gfx_r = 1;
gfx_g = 0;
holdon == 1 ?
(
gfx_rectto(238,30);
):(
gfx_lineto(238,17);
gfx_lineto(238,30);
gfx_lineto(225,30);
gfx_lineto(225,17);
);
gfx_x = 243;
gfx_y = 20;
gfx_r = 0;
gfx_g = 1;
gfx_drawstr("Note: ");
gfx_printf(gnote);
gfx_drawnumber(goctave,0);
gfx_x=50;
gfx_y=25+127;
gfx_lineto(50,(25+127)-(ccval));
gfx_lineto(60,(25+127)-(ccval));
gfx_lineto(60,(25+127));
gfx_r = 1;
gfx_g = 0;
gfx_a = 0.5;
gfx_x = 30;
gfx_y = 25;
gfx_lineto(30+(50),25);
gfx_x = 30;
gfx_y = 25+127;
gfx_lineto(30+(50),25+127);
gfx_a =1;
gfx_x = 30;
gfx_y = 25+127-trigval;
gfx_lineto(30+(50),25+127-trigval);
gfx_x = 5;
gfx_y = 20;
gfx_drawstr("127");
gfx_x = 18;
gfx_y = 20+127;
gfx_drawstr("0");
gfx_r = 0;
gfx_g = 1;
gfx_x =30+55;
gfx_y = 20+127-trigval;
gfx_drawstr("Trigger: ");
gfx_drawnumber(trigval,0);
|
|
|
09-11-2016, 07:11 AM
|
#20
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
I made a small change to the LFO to improve the timing accuracy. Revised code follows:
Code:
version: 1.0.1
desc:ReaRack - LFO
changelog: Added counter to calculate block offset, for improved timing accuracy.
/* 1.0.0 (2/9/2016) Initial Release.
1.0.1 (11/9/2016) Added counter to calculate block offset, for improved timing accuracy.
Copyright(C) 2016 and later, Malcolm Smith (username 'Time Waster' on REAPER forums).
License: LGPL - http://www.gnu.org/licenses/lgpl.html
*/
slider1:20<0,127,1{0 Bank Sel M,1 Mod Wheel M,2 Breath M,3,4 Foot P M,5 Porta M,6 Data Entry M,7 Vol M,8 Balance M,9,10 Pan M,11 Expression M,12 Ctrl 1 M,13 Ctrl 2 M,14,15,16 GP Slider 1,17 GP Slider 2,18 GP Slider 3,19 GP Slider 4,20,21,22,23,24,25,26,27,28,29,30,31,32 Bank Sel L,33 Mod Wheel L,34 Breath L,35,36 Foot P L,37 Porta L,38 Data Entry L,39 Vol L,40 Balance L,41,42 Pan L,43 Expression L,44 Ctrl 1 L,45 Ctrl 2 L,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64 Hold P sw,65 Porta sw,66 Sustenuto sw,67 Soft P sw,68 Legato P sw,69 Hold 2 P sw,70 S.Variation,71 S.Timbre,72 S.Release,73 S.Attack,74 S.Brightness,75 S.Ctrl 6,76 S.Ctrl 7,77 S.Ctrl 8,78 S.Ctrl 9,79 S.Ctrl 10,80 GP B.1 sw,81 GP B.2 sw,82 GP B.3 sw,83 GP B.4 sw,84,85,86,87,88,89,90,91 Effects Lv,92 Trem Lv,93 Chorus Lv,94 Celeste Lv,95 Phaser Lv,96 Data B. Inc,97 Data B. Dec,98 NRP L,99 NRP M,100 RP L,101 RP M,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127}>CC Output
slider2:1<0,16,1{All,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}>MIDI Ouput Channel
slider3:1<0,11,1{Off,8,4,2,1,1/2,1/4,1/8,1/16,1/32,1/64}>Sync (Off/Note Value)
slider4:0<0,2,1{Off,Duplet,Triplet}>Tuplet
slider5:1<0.1,24,0.01>Frequency
slider6:0<0,3,1{Sine,Saw - Triangle (PW),Square (PW),Random Step}>Wave Shape
slider7:0<-0.9922,0.9922,0.01>Shape Control
slider8:0<-0.5,0.5>Phase
in_pin:none
out_pin:none
@init
syncval == slider3;
tupval == slider4;
freqval == slider5;
tupval == 0 ? tuplet = 1:
tupval == 1 ? tuplet = (2/3):
tupval == 2 ? tuplet = (3/2);
tau = $pi*2.0;
adj = tau/(srate/samplesblock);
(syncval == 0) ? (
freq = freqval;
)
:
(
freq = ((2^(syncval-4))/(60*4/tempo))*tuplet;
);
inbeatpos = beat_position % 1;
pos = freq % inbeatpos;
prephase = 0;
@slider
modcc = slider1;
chanout = slider2-1;
syncval = slider3;
tupval = slider4;
freqval = slider5;
shape = slider6;
pw = slider7 * $pi + $pi;
phase = slider8*tau;
phaseadj = (slider8*tau)-prephase;
phaseshift = 1;
tupval == 0 ? tuplet = 1:
tupval == 1 ? tuplet = (2/3):
tupval == 2 ? tuplet = (3/2);
@block
offset = 0;
modstatus = $xB0|chanout;
tol = 1.1*samplesblock/srate;
(syncval == 0) ? (
freq = freqval;
)
:
(
freq = ((2^(syncval-4))/(60*4/tempo))*tuplet;
);
@sample
adj = tau*freq/srate;
(shape == 0) ? (
// sine
rawccval = 63.5+(sin(pos)*63.5);
(rawccval % 1) < tol ?
ccval = floor(rawccval);
) :
(shape == 1) ? (
// triangle
k = pw - ((pos<pw) ? 0 : tau);
x = pos - ((pos<pw) ? 0 : tau);
rawccval =(127*(x/k + 1))-127;
(rawccval % 1) < tol ?
ccval = floor(rawccval);
) :
(shape == 2) ? (
// square
ccval = (pos<pw) ? 127 : 0;
) :
(
//Random step
pos >= pw && step == 1 ?
(
pos1 = 10;
step = 2;
);
pos < pos1 ? ccval = floor(rand(127)+0.5);
pos1 = pos;
);
//Send CC message
chanout == -1 ?
(
preccval != ccval ?
(
n = 0;
loop(16,
midisend(offset,$xB0+n,modcc,ccval);
presentcc = preccval;
n += 1;
);
)
):(
preccval != ccval ?
(
midisend(offset,modstatus,modcc,ccval);
presentcc = preccval;
);
);
phaseshift == 1 ?
(
pos=pos+adj+phaseadj;
prephase = phase;
phaseshift = 0;
):(
pos=pos+adj;
);
pos >= tau ?
(
pos -= tau;
step = 1;
);
preccval = ccval;
offset +=1;
@gfx 400 150
gfx_r = 0;
gfx_g = 1;
gfx_b = 0;
gfx_a = freq < 10 ? 0.666+(sin(pos)/3):0.75;
(shape == 0) ? (
// sine
gpos = 0;
gfx_x = 25;
gfx_y = 80;
while (gpos < tau)(
gfx_lineto(25+(20*gpos),80-(40*(sin(gpos))));
gpos+=.05;
);
) : ( // else
(shape == 1) ? (
// triangle
gfx_x = 25;
gfx_y = 120;
gfx_lineto(25+(20*pw),40);
gfx_lineto(25+(20*tau),120);
) : (
(shape == 2) ? (
// square
gfx_x = 25;
gfx_y = 120;
gfx_lineto(25,40);
gfx_lineto(25+(20*pw),40);
gfx_lineto(25+(20*pw),120);
gfx_lineto(25+(20*tau),120);
) : (
(shape == 3) ? (
// random
gfx_a = 1;
gfx_x = 25;
gfx_y = 120;
step == 1 ?
(
gfx_lineto(25,120-(ccval/1.5875));
gfx_lineto(25+(20*pw),120-(ccval/1.5875));
gfx_lineto(25+(20*pw),120);
gfx_lineto(25+(20*tau),120);
):(
gfx_lineto(25,120-(presentcc/1.5875));
gfx_lineto(25+(20*pw),120-(presentcc/1.5875));
gfx_lineto(25+(20*pw),120-(ccval/1.5875));
gfx_lineto(25+(20*tau),120-(ccval/1.5875));
gfx_lineto(25+(20*tau),120);
);
);
);
);
);
gfx_x=gfx_y=5;
gfx_lineto(gfx_x, gfx_y,0);
gfx_r=gfx_b=0;
gfx_g=gfx_a=1;
gfx_drawstr("Frequency = ");
gfx_drawnumber(freq,2);
gfx_drawstr(" Hz");
gfx_r = 1;
gfx_g = 0;
gfx_a = 0.5;
gfx_x = 25;
gfx_y = 40;
gfx_lineto(25+(20*tau),40);
gfx_x = 25;
gfx_y = 120;
gfx_lineto(25+(20*tau),120);
phase >= 0 ?
(
gfx_x = 25+(20*phase);
gfx_y = 40;
gfx_lineto(25+(20*phase),120);
):(
gfx_x = 25+(20*tau)+(20*phase);
gfx_y = 40;
gfx_lineto(25+(20*tau)+(20*phase),120);
);
gfx_a =1;
gfx_x = 1;
gfx_y = 35;
gfx_drawstr("127");
gfx_x = 13;
gfx_y = 115;
gfx_drawstr("0");
|
|
|
09-11-2016, 07:31 AM
|
#21
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
Quote:
Originally Posted by ashcat_lt
.......I guess it'd be an interesting feature and maybe convenient to have it on the osc module, but it does beg the question of how modular you want to get.....
|
I was thinking about this in the shower this morning and I remembered a bit more of my reasoning for having the ring modulation feature in the oscillator. I had initially considered a separate module, but it turns out to be a bit complicated in terms of audio routing. The ring modulation effect needs two audio sources. I would need to put the oscillators on separate tracks and the ring modulation module on a third track. The audio from one module would need to be panned hard left, and the other hard right in the ring mod track, so that the audio sources could be input separately. Another possible solution was to have a slider on the oscillator module so that you could pan the output directly, in which case all three modules could be on the same track, but it still seemed a bit messy. This is assuming using the default stereo track setup. One of my goals with ReaRack is that you don't need to do any complicated audio routing to get it to work. From the this point of view, I think the 'in oscillator' solution is better.
I wanted to have ring modulation in the system because my old hardware Korg MS20 has it. The MS20 has two oscillators and one of them has a ring modulation setting. When selected, the two oscillators modulate each other to produce the ring modulation effect. The ring modulation method in ReaRack is therefore similar to the one in the MS20.
Last edited by Time Waster; 09-11-2016 at 07:38 AM.
|
|
|
09-11-2016, 10:01 AM
|
#22
|
Human being with feelings
Join Date: Dec 2012
Posts: 7,122
|
Pin connectors are. Sends can send to/from single channels.
But isn't that what a modular synth is?!? It requires relatively complex routings to get much of anything useful out of them.
I think it's pretty obvious by now that we have somewhat different philosophies on the subject. My main goal is to exploit as many of Reaper's native features as possible in order to save on code and keep everything as agnostic as possible. I'm not looking to build a proprietary "modular system" that kind of only works with the plugs I've written for it. I want to grab any plugin and press it into service. For the most part, it's already possible, but I want to be able to use the audio engine for CV, and that can't work quite right until Parameter Modulation is sample accurate.
I'm not trying to say that what you're doing is wrong. If it works for you, that's great. Part of the fun of JS is that you can build that one thing that only you need or want. (Not saying that's what this is.) You seem to be learning things in the process. Heck I'm learning things following your threads! I haven't actually looked at this collection yet, but I wouldn't be surprised if I found several useful bits in there.
|
|
|
09-11-2016, 05:31 PM
|
#23
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
The reason I chose to live with the limitations of MIDI is to keep it an open system. All the patching is done with MIDI rather than needing a deeper knowledge of REAPER's audio routing or parameter modulation. But there is nothing stopping anyone from using those with the system as well. In theory, the modules could be converted into VSTs and used in any DAW that supports MIDI. I think that is a less proprietary approach than designing something that can only be used in REAPER.
I decided to create the modules because I couldn't find any else where that were basic enough, or that weren't too basic. I could have left out the MIDI patching system and just used parameter modulation to control the sliders, but as you point out, it's not really up to it and I just think that the MIDI patching is easier. If it's not easy, no one will use it, not even me.
|
|
|
09-12-2016, 05:37 AM
|
#26
|
Human being with feelings
Join Date: Mar 2007
Posts: 3,685
|
Hello Time Waster,
great work, thank you for modular synth and also manual.
Quote:
Originally Posted by Time Waster
|
But the manual cannot be "downloaded", it can be only viewed from within Dropbox (for non logged-in user).
It shows red coloured info text on top of the page when clicking Download button:
"There was an error downloading your file."
Although this edited link will directly download the file:
https://www.dropbox.com/s/kcetwno67f...anual.pdf?dl=1
akademie
Last edited by akademie; 09-12-2016 at 06:04 AM.
Reason: correction of mistyping
|
|
|
09-12-2016, 06:56 AM
|
#27
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
Thanks akademie, I should have tested the link.
|
|
|
09-12-2016, 07:10 AM
|
#28
|
Human being with feelings
Join Date: Mar 2007
Posts: 3,685
|
No problem Time Waster. You're welcome.
akademie
P.S.: I have just listened to your "The Wasters of Time" music on Soundcloud and I like it a lot, really nice (non-commercial non-pop) 80's vibe.
Last edited by akademie; 09-12-2016 at 07:32 AM.
|
|
|
09-12-2016, 07:40 AM
|
#29
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
Thanks akademie. I hope you have some fun with the modular synth.
|
|
|
09-12-2016, 09:25 AM
|
#30
|
Human being with feelings
Join Date: Nov 2015
Location: Germany
Posts: 999
|
Quote:
Originally Posted by akademie
...But the manual cannot be "downloaded", it can be only viewed from within Dropbox (for non logged-in user)...
|
I noticed that too but in this case right click "Save as..." helps!
But it's fixed anyway...
Thanks Time Waster!
|
|
|
09-12-2016, 10:17 AM
|
#31
|
Human being with feelings
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
|
Quote:
Originally Posted by ashcat_lt
... For the most part, it's already possible, but I want to be able to use the audio engine for CV, and that can't work quite right until Parameter Modulation is sample accurate.
...
|
Hello AshCat,
I started, with other contributorsn a project a few years ago that consisted in using multiple audio channels to transmit controls to chained modules.
See the very old thread here:
http://forum.cockos.com/showthread.p...ght=monosynthy
The problem is that it is not really easy to use. It is much like the bus system of a ARP2500
Yes, it is lovely and vintage, but, trust me, it is not handy at all.
@Time Waster, nowadays, jsfx allows namespace and it is possible to make programming a little more object oriented. That makes the idea of jsfx module an interesting one. The difficulty is that there is no scheme to make some standard "modules".
Tale, myself and many others have already designed our own "libraries" each with our favourite tricks and coding habits. But i don't think it is possible to make it "standard"... especially for coding unusual modules.
I think that the more viable and handy solution is to make MIDI controlled modules. A granularity much similar to what you have in the hardware world as Eurorack modules.
|
|
|
09-12-2016, 10:33 AM
|
#32
|
Human being with feelings
Join Date: Dec 2012
Posts: 7,122
|
ST - That it pretty much exactly what I'm trying to avoid. I don't want to have to code the part that connects audio channels to faders in each module partly because redundancy and partly because it precludes the use of other people's plugs. As it stands now, we would need a plug that wiggles sliders based on audio input and then to link those sliders to module parameters. I'm cool with that because it works for every plug out there. But that parameter linking happens once per block, which can work for slower control signals if the plugs themselves have parameter smoothing, but...
...we need sample accurate Parameter Modulation! I'm gonna keep saying it every chance I get.
|
|
|
09-12-2016, 11:10 AM
|
#33
|
Human being with feelings
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
|
If you need audio rate controls why not simply use audio channels (as in the old monosynthy project).
Sample accurate time stamped controls are a pain in the back to handle for DSP coders.
|
|
|
09-12-2016, 11:24 AM
|
#34
|
Human being with feelings
Join Date: Dec 2012
Posts: 7,122
|
Quote:
Originally Posted by Smashed Transistors
If you need audio rate controls why not simply use audio channels (as in the old monosynthy project).
|
Then what? My code has to know what to do with those audio inputs. Some other dude's plugin probably won't. So I can't use his plugin?
Quote:
Sample accurate time stamped controls are a pain in the back to handle for DSP coders.
|
JS sliders can and will change every sample. Automation is sample accurate for plugins that can handle it. Parameter Modulation should be also. Nobody has ever explained to me why it can't be. I've heard lots of reasons other people don't think it's necessary, but...
|
|
|
09-12-2016, 01:50 PM
|
#35
|
Human being with feelings
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
|
[QUOTE=ashcat_lt;1729432]Then what? My code has to know what to do with those audio inputs. Some other dude's plugin probably won't. So I can't use his plugin?
[QUOTE]
Have a look to the old thread.
|
|
|
09-12-2016, 02:15 PM
|
#36
|
Human being with feelings
Join Date: Dec 2012
Posts: 7,122
|
Quote:
Originally Posted by Smashed Transistors
Have a look to the old thread.
|
What did I miss? Where is my question addressed? What I'm seeing there is people building the CV into the plugs themselves. How do you apply any of this to plugins which aren't built to your standards?
|
|
|
09-12-2016, 04:25 PM
|
#37
|
Human being with feelings
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
|
As you said Reaper allows to route any input/output of the plugins to any audio channel thanks to the connection matrix.
The in_pin: and out_pin: allows the coder to give them explicit names.
And yes, you need standards to interconnect stuff.
As far as i know, the only practical standard for control is MIDI.
That's why i don't think that a modular system that implements something under the MIDI level is viable.
|
|
|
09-12-2016, 04:38 PM
|
#38
|
Human being with feelings
Join Date: Dec 2012
Posts: 7,122
|
If PM was sample-accurate...
...anything with a gain control could be a VCA. We could use ReaEQ for a VCF. We could add smoothing to JS and VST3 plugs that don't have it and eliminate MIDI controller zipper noises without re-writing the original plug...
Every exposed parameter on every plugin in Reaper can already be manipulated by MIDI and audio*, but until it's sample accurate, we are limited.
Last edited by ashcat_lt; 09-12-2016 at 05:13 PM.
|
|
|
09-12-2016, 07:58 PM
|
#39
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
I would be interested to know how parameter modulation works? I had assumed that it mimics the action of the mouse manipulating the slider or knob on the screen. If that is is the case, you are relying on the third party underlying code to translate those actions into smooth parameter changes. Perhaps parameter modulation works more directly than that, but even so, there will be a point where the third party code takes over and that is outside of REAPER's control. Knobs and sliders designed as a UI don't necessarily have to be sample accurate. There is no onus on the third party developer to make it so.
|
|
|
09-16-2016, 10:19 AM
|
#40
|
Human being with feelings
Join Date: Aug 2013
Location: Bowral, Australia
Posts: 1,587
|
Bug Fix.
Well, not really a bug, just an oversight on my part. I have updated the envelope generator module (in the same zip file in the stash) to fix an issue with overlapping notes in monophonic mode. The issue was that the envelope generator didn't keep track which note on event the note off belongs to. This was an easy fix for notes of dissimilar value, and that is what I have done for now.
However, if the overlapping notes are of the same value (which shouldn't really happen, but could), there is no easy way to keep track of which is which. I assume I would have to set flags or something? I have ignored the same note overlapping issue for now. Is this reasonable? Should I attempt to deal with this or is it up to the person generating the MIDI to avoid overlapping same value notes?
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 11:40 PM.
|