What's new

How can I get smooth midi CC automation in Reaper ?

I'm curious. How is it that CCenv_(CC0-CC63).jsfx, is able to properly record CC01, but ReaControlMIDI can't? What is the magic that enables this to work when it fails for me with ReaControlMIDI? In both cases I'm using CCenv_input.jsfx as an input FX, and I have record mode set to "Latch."
 
Last edited:
I'm curious. How is it that CCenv_(CC0-CC63).jsfx, is able to properly record CC01, but ReaControlMIDI can't? What is the magic that enables this to work when it fails for me with ReaControlMIDI? In both cases I'm using CCenv_input.jsfx as an input FX, and I have record mode set to "Latch."
I've not personally used ReaControlMIDI to record CC envelopes, but my understanding is that because it can't stop the CC events from being recorded and/or passing through it, you end up with the both the MIDI data and the envelope recorded unless you use something else to filter the data as well. My impression is that it's not really designed for people who want to replace CC events with envelopes as part of a permanent workflow modification.

CCEnv works by reading the CC values at input (in CCEnv Input), blocking the CCs you've selected so they won't record as MIDI on the track, and instead sending that CC data directly to CCEnv (CC0-CC63) and CCEnv (CC64-CC127) which convert the CCs to slider motion that can be recorded. CCEnv (CC0-CC63) and CCEnv (CC64-CC127) then pass the CC data equivalent of the slider motion on down the chain to the instrument. If there were no input component to the plugin, the MIDI track couldn't be bypassed while recording, and if there were no output component, there would be no way to read the envelopes during playback, but having both an input and an output component allows us to skip the MIDI track entirely for both recording and playback.

I just checked, and it's actually possible to use CCEnv Input to filter out a CC by checkingboxing it and then use ReaControlMIDI's learn feature to link that CC to its automatable CC parameter which lets you record the automation with the CC input without recording the MIDI data on the track -- so you end up in pretty much the same place as if you use CCEnv (CC0-CC63) and CCEnv (CC64-CC127), just with fewer available CCs and more setup required.
 
I just checked, and it's actually possible to use CCEnv Input to filter out a CC by checkingboxing it and then use ReaControlMIDI's learn feature to link that CC to its automatable CC parameter

By "checkboxing it" do you mean enabling it?

I've only just started playing with CCEnv but it seems to solve the problem (recording smooth MIDI automation) so thanks for your work on this.

The CCEnv scripts seem to work well, so I'll probably stick with it rather than continuing to struggle with ReaControlMIDI since I'm just not making any progress with getting it to recognize (learn) the MOD wheel and behave as well as CCEnv.

Will you eventually upload CCEnv to the Reaper Reapack repository or some external location? So far it seems it's only available to members of this forum as an attachment to this thread.
 
By "checkboxing it" do you mean enabling it?

I've only just started playing with CCEnv but it seems to solve the problem (recording smooth MIDI automation) so thanks for your work on this.

The CCEnv scripts seem to work well, so I'll probably stick with it rather than continuing to struggle with ReaControlMIDI since I'm just not making any progress with getting it to recognize (learn) the MOD wheel and behave as well as CCEnv.

Will you eventually upload CCEnv to the Reaper Reapack repository or some external location? So far it seems it's only available to members of this forum as an attachment to this thread.

Yes, by checkboxing I mean enabling.

If ReaControlMIDI isn't seeing the mod wheel as a learn source, you may need to change your MIDI controller's mode in the MIDI devices section of the preferences. You can set input devices as enable input and/or enable input for control messages by right clicking on them. Both can be selected at the same time for any device, and enable input for control messages allows Reaper to see the device as a learn source.

As far as distribution goes, I'll probably at least put it up in the Reaper forum thread where the script originated and maybe look into Reapack. It hadn't occurred to me that putting it as a message board attachment restricted it to forum members, so in the meantime, I'll maybe find a spot to upload it that's generally accessible.
 
It's also possible that there's something specific to your Reaper project/template affecting things, so let me know if you still have the problem after setting up a clean project without touching the CCEnv sliders.
Yes, that's more than possible. But I'll try the work arounds and see what happens.
 
The other workaround is, after setting everything up, don't touch any slider in the CCEnv (CC0-CC63) or CCEnv (CC64-CC127) window unless you're actually going to record/automate the slider. Reaticulate won't see any data coming from the unused sliders and won't latch to them.
Both workarounds seem to work. I'm wondering if there's a way to "embed" certain CC values into a track template without adding a midi item (not that this is a bad thing).
 
As tack mentioned, a work around for this is to insert a CC value on the track so Reaticulate will chase that instead of what it got from CCEnv.
I've found another workaround (I think). In Kontakt I used the factory multiscript Transformer to send CC7 and CC10 to unused values (100, 101) so that they don't affect the instruments in any way. Obviously, if you do this you have to make sure your instruments don't use those new values for anything. But so far it seems to work. I tried hammering the track with CC7 and it made no difference.

The problem I had with adding a CC7 command to the track was that it set all the instrument values to the same volume, and destroyed the volume balance I had worked out for that multi.
 
I'm finding that 'on/off' CC's (I'm use sustain pedal: CC64), seem to be a little inaccurate when being run through CCEnv. It seems that it can be a bit erratic with the 0 (off) and 127 (on) values. Sometimes CC64 get's stuck on 127 keeping the sustain on, despite letting go of the pedal. Screenshot of ReaControl MIDI attached.

The easiest way to recreate the issue is to turn sustain on and off rapidly. I know it's not normal to do this but it can occasionally "stick" on (127) when playing normally too. With CCEnv off I can mash the sustain pedal as much as I like and always finishes on 0.

Apart from that, the regular CC's that aren't on/off work beautifully :thumbsup:

Any ideas?
 

Attachments

  • MIDI_log.jpg
    MIDI_log.jpg
    86.5 KB · Views: 37
I'm finding that 'on/off' CC's (I'm use sustain pedal: CC64), seem to be a little inaccurate when being run through CCEnv. It seems that it can be a bit erratic with the 0 (off) and 127 (on) values. Sometimes CC64 get's stuck on 127 keeping the sustain on, despite letting go of the pedal. Screenshot of ReaControl MIDI attached.

The easiest way to recreate the issue is to turn sustain on and off rapidly. I know it's not normal to do this but it can occasionally "stick" on (127) when playing normally too. With CCEnv off I can mash the sustain pedal as much as I like and always finishes on 0.

Apart from that, the regular CC's that aren't on/off work beautifully :thumbsup:

Any ideas?
Haven't had time to actually get into the code to fix it, but I have at least recreated the bug. It seems to be happening only with input/recording and not with playback, so I have a general sense of where in the code things are going wrong.
 
How can i add this script to Reaper?
Download and copy the text into your clipboard. Open your FX browser, right click on JS, choose create a new effect, name it, and paste the text. Save.
Alternately, the .jsfx files can be placed directly in the Effects folder in the Reaper resource location (Options > Show REAPER resource path in explorer/finder), which is where create new JS FX puts things by default. You may have to scan for new plugins to get it to appear if you do it this way.
 
Hey guys ,there is a bug or something like that with CC_env scripts.

As you can see in the video , i cant adjust each track individually.

The routing for midi track 1-16 is like that , First track All>1 , secod All>2 etc.
mLFIG98rl_c.jpg

Could someone please fix this issue?
 
Last edited:
Hey guys ,there is a bug or something like that with CC_env scripts.

As you can see in the video , i cant adjust each track individually.

The routing for midi track 1-16 is like that , First track All>1 , secod All>2 etc.
mLFIG98rl_c.jpg

Could someone please fix this issue?

So, the issue is that the input plugin isn't distinguishing among the possible output plugins it can send data to, and it doesn't naturally know which instances of the output plugins are in its own signal chain because plugins don't know what tracks they exist on. And the data can't be passed down the chain as normal MIDI data because the whole point is to avoid doing that. It's a problem leftover from the original code that I didn't catch in my modifications.

There are a few possible approaches to fixing it. The most straightforward is either to have the user manually set ID numbers on each plugin instance so the input plugins know which output plugins to route their data to, or to have a sync button on each plugin where you would press sync on the input plugin and it would match to the next output plugins that you pressed sync on. Or possibly instruct the user to briefly turn on record monitoring during plugin setup, which would let the input plugin send a MIDI signal down the chain to see which output plugins were in the chain with it.

Another possibility would be to add a Lua component that runs in the background independently of the plugins and tells each plugin what track it's on (ReaScript can gather this sort of data, whereas JSFX can't). It would be a little cumbersome to have a separate script that needs to run in addition to the plugins, though, so I'd like to avoid this if I can.

The best solution, which I haven't thought through in detail yet because I've never done audio processing in JSFX before, is that I may be able to use the audio output routing from the plugins to send the MIDI data as a dummy audio signal that won't actually be output as sound but will properly travel down the signal chain to be read by the appropriate output plugin.

I'll explore these options and make the fix when I'm able, but unfortunately my current job situation has left me without much free time to work on these sorts of projects, so I can't guarantee any kind of timetable on this.

EDIT: Just realized that Reaper lets you set the record mode to record the MIDI output rather than input. Haven't played around with it yet, but this might let me restructure the entire plugin so it all sits in the output FX section, which would make everything a lot simpler.
 
Last edited:
So, the issue is that the input plugin isn't distinguishing among the possible output plugins it can send data to, and it doesn't naturally know which instances of the output plugins are in its own signal chain because plugins don't know what tracks they exist on. And the data can't be passed down the chain as normal MIDI data because the whole point is to avoid doing that. It's a problem leftover from the original code that I didn't catch in my modifications.

There are a few possible approaches to fixing it. The most straightforward is either to have the user manually set ID numbers on each plugin instance so the input plugins know which output plugins to route their data to, or to have a sync button on each plugin where you would press sync on the input plugin and it would match to the next output plugins that you pressed sync on. Or possibly instruct the user to briefly turn on record monitoring during plugin setup, which would let the input plugin send a MIDI signal down the chain to see which output plugins were in the chain with it.

Another possibility would be to add a Lua component that runs in the background independently of the plugins and tells each plugin what track it's on (ReaScript can gather this sort of data, whereas JSFX can't). It would be a little cumbersome to have a separate script that needs to run in addition to the plugins, though, so I'd like to avoid this if I can.

The best solution, which I haven't thought through in detail yet because I've never done audio processing in JSFX before, is that I may be able to use the audio output routing from the plugins to send the MIDI data as a dummy audio signal that won't actually be output as sound but will properly travel down the signal chain to be read by the appropriate output plugin.

I'll explore these options and make the fix when I'm able, but unfortunately my current job situation has left me without much free time to work on these sorts of projects, so I can't guarantee any kind of timetable on this.

EDIT: Just realized that Reaper lets you set the record mode to record the MIDI output rather than input. Haven't played around with it yet, but this might let me restructure the entire plugin so it all sits in the output FX section, which would make everything a lot simpler.

Ok Thanks for the answer, that sounds really kinda complicated for me to handle.

The setup i am using right now
I use MidiNotch in INPUTfx , and set it to filter all CC inputs. (like that)
cEwivpbg9cU.jpg
And then for Regular FX slot ,i use your two JS plugins.
gmnj20WBUVI.jpg

And after that i just choose what cc's i need in envelope lane and learn them with my midi device
NIDH-yDj-4E.jpg

That requires some extra work because of learning process.

The only problem i have with this setup, is if i try to record in midi output mode (records all cc's in midi items).
 
Thanks to pmcrockett and his CCenv, I am now able to record automation with my outboard gears such as a Nord Lead 2. It's working really great!

Below are the parameter definitions for anyone who may find it useful.

Here is a question about possible optimisation:

For Nord Lead 2, only seven parameters are needed from the cc64-cc127 JS, and cc47-cc63 are unused. The first CCenv would have plenty of room to account for cc70-80.

Can the code be altered in a simple way so that, for example, cc50-cc63 becomes cc70-83? I'm guessing a simple math formula will do?

This would help immensely because then Synth settings can be stored, recalled, and transmitted with a single JS preset. I hope it can work out this way.

Code:
desc:CCEnv (Nord Lead 2) A

slider1:0<0,127,1>-slider1 CC0
slider2:0<0,127,1>-Modwheel CC1
slider3:0<0,127,1>-Breath Ctrl CC2
slider4:0<0,127,1>-slider4 CC3
slider5:0<0,127,1>-slider5 CC4
slider6:0<0,127,1>Portamento CC5
slider7:0<0,127,1>-slider7 CC6
slider8:100<0,127,1>Gain CC7
slider9:0<0,127,1>Oscillator Mix CC8
slider10:0<0,127,1>-slider10 CC9
slider11:0<0,127,1>-slider11 CC10
slider12:0<0,127,1>-slider12 CC11
slider13:0<0,127,1>-slider13 CC12
slider14:0<0,127,1>-slider14 CC13
slider15:0<0,127,1>-slider15 CC14
slider16:0<0,2,1{Mono,Legato,Poly}>-Oscillator Mode CC15
slider17:0<0,1,1{off,ON}>-Unison CC16
slider18:0<0,127,1>-slider18 CC17
slider19:0<0,4,1{Filter,FM,OSC2,LFO1,Morph}>-ModWh Destination CC18
slider20:80<0,127,1>LFO1 Rate CC19
slider21:0<0,4,1{S&H,Saw,Tri,Sqr,soft Rnd>LFO1 Waveform CC20
slider22:0<0,4,1{PW,Filter,Osc2,Osc1+2,FM>LFO1 Destination CC21
slider23:0<0,127,1>LFO1 Amount CC22
slider24:80<0,127,1>LFO2 Rate CC23
slider25:0<0,8,1{hold-DN,hold-UP,UP,hold-UD,AMP,Osc1+2,hold-RND,hold-Echo,Filter,Arp Off (filter)}>LFO2 hold / dest CC24
slider26:0<0,127,1>LFO2 Amt / Arp Range CC25
slider27:0<0,127,1>Mod Attack CC26
slider28:127<0,127,1>Mod Decay CC27
slider29:0<0,3,1{Osc2,FM,PW,off}>Mod Destination CC28
slider30:64<0,127,1>Mod Amount CC29
slider31:1<0,3,1{Pulse,Sawtooh,Triangle,Sine}>Osc 1 Waveform CC30
slider32:1<0,3,1{Pulse,Sawtooh,Triangle,Noise}>Osc 2 Waveform CC31
slider33:0<0,127,1>-slider33 CC32
slider34:64<0,127,1>Osc 2 fine tune CC33
slider35:0<0,1,1{off,ON}>Osc 2 keytrack CC34
slider36:0<0,3,1{off,Sync,Ring,SyncRng}>Osc Ring / Sync CC35
slider37:64<0,127,1>Amp Decay CC36
slider38:127<0,127,1>Amp Sustain CC37
slider39:0<0,127,1>FLT Attack CC38
slider40:64<0,127,1>FLT Decay CC39
slider41:127<0,127,1>FLT Sustain CC40
slider42:0<0,127,1>FLT Release CC41
slider43:0<0,127,1>Resonance CC42
slider44:64<0,127,1>Env Amt CC43
slider45:0<0,4,1{LP 12 db,LP 24 db,HP 24 db,BP,Notch + LP}>Filter Type CC44
slider46:0<0,1,1{off,ON}>Velocity CC45
slider47:0<0,3,1{off,1/3,2/3,full}>Kbd Track CC46
slider48:0<0,127,1>-slider48 CC47
slider49:0<0,127,1>-slider49 CC48
slider50:0<0,127,1>-slider50 CC49
slider51:0<0,127,1>-slider51 CC50
slider52:0<0,127,1>-slider52 CC51
slider53:0<0,127,1>-slider53 CC52
slider54:0<0,127,1>-slider54 CC53
slider55:0<0,127,1>-slider55 CC54
slider56:0<0,127,1>-slider56 CC55
slider57:0<0,127,1>-slider57 CC56
slider58:0<0,127,1>-slider58 CC57
slider59:0<0,127,1>-slider59 CC58
slider60:0<0,127,1>-slider60 CC59
slider61:0<0,127,1>-slider61 CC60
slider62:0<0,127,1>-slider62 CC61
slider63:0<0,127,1>-slider63 CC62
slider64:0<0,127,1>-slider64 CC63

desc:CCEnv (Nord Lead 2) B

slider1:0<0,127,1>-slider1 CC64
slider2:0<0,1,1{off,ON}>Auto Portamento CC65
slider3:0<0,127,1>-slider3 CC66
slider4:0<0,127,1>-slider4 CC67
slider5:0<0,127,1>-slider5 CC68
slider6:0<0,127,1>-slider6 CC69
slider7:0<0,127,1>FM Amt / Tune CC70
slider8:0<0,127,1>-slider8 CC71
slider9:0<0,127,1>Amp Release CC72
slider10:0<0,127,1>Amp Attack CC73
slider11:127<0,127,1>Cutoff Frequency CC74
slider12:0<0,127,1>-slider12 CC75
slider13:0<0,127,1>-slider13 CC76
slider14:0<0,127,1>-slider14 CC77
slider15:60<0,120,1>Semi/ NoisClr/ Sync wfm sel CC78
slider16:0<0,127,1>Osc1 PW CC79
slider17:0<0,1,1{off,ON}>Distortion on/off CC80
slider18:0<0,127,1>-slider18 CC81
slider19:0<0,127,1>-slider19 CC82
slider20:0<0,127,1>-slider20 CC83
slider21:0<0,127,1>-slider21 CC84
slider22:0<0,127,1>-slider22 CC85
slider23:0<0,127,1>-slider23 CC86
slider24:0<0,127,1>-slider24 CC87
slider25:0<0,127,1>-slider25 CC88
slider26:0<0,127,1>-slider26 CC89
slider27:0<0,127,1>-slider27 CC90
slider28:0<0,127,1>-slider28 CC91
slider29:0<0,127,1>-slider29 CC92
slider30:0<0,127,1>-slider30 CC93
slider31:0<0,127,1>-slider31 CC94
slider32:0<0,127,1>-slider32 CC95
slider33:0<0,127,1>-slider33 CC96
slider34:0<0,127,1>-slider34 CC97
slider35:0<0,127,1>-slider35 CC98
slider36:0<0,127,1>-slider36 CC99
slider37:0<0,127,1>-slider37 CC100
slider38:0<0,127,1>-slider38 CC101
slider39:0<0,127,1>-slider39 CC102
slider40:0<0,127,1>-slider40 CC103
slider41:0<0,127,1>-slider41 CC104
slider42:0<0,127,1>-slider42 CC105
slider43:0<0,127,1>-slider43 CC106
slider44:0<0,127,1>-slider44 CC107
slider45:0<0,127,1>-slider45 CC108
slider46:0<0,127,1>-slider46 CC109
slider47:0<0,127,1>-slider47 CC110
slider48:0<0,127,1>-slider48 CC111
slider49:0<0,127,1>-slider49 CC112
slider50:0<0,127,1>-slider50 CC113
slider51:0<0,127,1>-slider51 CC114
slider52:0<0,127,1>-slider52 CC115
slider53:0<0,127,1>-slider53 CC116
slider54:0<0,127,1>-slider54 CC117
slider55:0<0,127,1>-slider55 CC118
slider56:0<0,127,1>-slider56 CC119
slider57:0<0,127,1>-slider57 CC120
slider58:0<0,127,1>-slider58 CC121
slider59:0<0,127,1>-slider59 CC122
slider60:0<0,127,1>-slider60 CC123
slider61:0<0,127,1>-slider61 CC124
slider62:0<0,127,1>-slider62 CC125
slider63:0<0,127,1>-slider63 CC126
slider64:0<0,127,1>-slider64 CC127


In the end, these would be nice minor tweaks to something that is already working perfectly. Thanks for making this possible!

Pat
 
Last edited:
Top Bottom