Dear friends,
I would like to share three ideas I’ve come up with and implemented that quite proud of. I hope these will be useful to others! I welcome your feedback and suggestions of course; perhaps my solutions are needlessly complicated and I’m always open to learning better methods. (These ideas do sound a lot more complicated than they actually are in practice; implementing them took some thought and some experimentation, but once I got them working, they’re so transparent that I barely notice they’re there.)
The first idea is my answer to the question, “how can I use one sustain pedal to control multiple keyboards and multiple keyboard zones?” In my setup, one rackspace can have up to eight different instruments, each one potentially controlled from a different zone on two different keyboards. (In practice it’s usually just two, for example, piano on the lower keyboard, organ on the upper keyboard, but I’ve set up my system to accommodate as many as eight.) Obviously I don’t want an all-or-nothing sustain pedal, because there are situations where I want to sustain a pad on one instrument while playing staccato notes on another.
Here’s what I came up with, and it seems to work very well, with little or no modification needed to my usual playing style. When a sustain-on event arrives, I send it along only to those instruments that have any notes currently pressed. So, for example, I could play a chord on the strings patch, press the sustain pedal while those notes are pressed, and then play something rhythmic on the piano patch with both hands while the strings pad continues to sustain. If a sustain-on event arrives when there are no notes pressend, then I set a “sustain pending” flag, and then subsequently when a note-on event comes, I send the sustain event only to the patches to which that note-on event applies before passing on the note-on event. Thus, I can press the sustain pedal first, then play a chord or note which I want sustained on one keyboard, and then play something unsustained on the othe keyboard. When a sustain-off event arrives, I send it to every patch, rather than bothering to remember which patches got the sustain-on event. As far as I’m aware, this idea is novel. In retrospect it seems obvious, but I’ve never heard anyone else mention it before.
Here’s my second useful idea, which is my answer to the situation where a physical control (such as a slider or expression pedal) starts out at a different value than the widget which it controls. I don’t want “jump” behaviour because I don’t want the widget to jump, and I don’t want “catch” behaviour because then I have to keep track mentally of whether the widget has been “caught” yet, and because sometimes in order to catch it I’ll have to move the physical control in the opposite direction from the actualy desired movement (e.g. if the widget is at 80, and the pedal is at 50, and I want to reduce the widget value, with “catch” I would first have to push the pedal up past 80 in order to catch the widget, before then pulling it back down to the desired level.)
My solution is that when the physical control increases in value, I increase the widget value by an amount proportional to how far the control moved toward its upper extreme, and when the control decreases in value, I decrease the widget value proportionally to how far the control moved toward its lower extreme. To use the above example, if the widget is at 80 and the expression pedal is at 50, then if the player moves the expression pedal up to 75 (in other words, halfway to the top), then my code moves the widget up to 90 (also halfway to the top). If the player subsequently move the pedal down to 25 (two-thirds of the way down from 75 to 0), then my code moves the widget down to 30 (two-thirds of the way down from 90 to 0). It only takes a few pedal movements for the pedal and the widget to be nearly in sync, and even before that’s the case the movements are still logical (moving the control always causes the widget to move in the same direction as the control). To use a more extreme example, say the pedal starts out at zero and the widget starts out at 80. If I want to decrease the widget value, in this case I can’t reduce the pedal value because it’s already at zero, so I have to push the pedal upward, but even if I go halfway up (to 50), the widget will only have increased to 90 (a small and hopefully acceptable increase), and then if I pull the pedal down to 25 (half of 50) it will drag the widget down to 45 (half of 90).
I’ve placed the GPScript code for the above two ideas in my Global Rackspace script, which is also where all of the code for handling keyboard zones and incoming MIDI events lives (currently about 600 lines of code not including comments and whitespace, and still growing…)
My third contribution has to do with gain-staging and managing loudness. I find that the built-in meter widgets are quirky and not very informative; they are useful to show that there is a signal present, and vaguely how loud or quiet it is, but not very useful for detailed loudness management. This is partly due to the lack of a numerical scale (correct me if I’m wrong, but there doesn’t seem to be a way to make a backplate visible), but mostly due to the fact that they seem to be showing the peak levels (which have very little to do with perceived loudness) rather than RMS levels, so if I have a signal with a very reasonable RMS loudness of -10dBFS, the meter will often go right up into the red because it’s showing the peaks rather than the average. (Again, correct me if I’m wrong about this.)
My solution to this is to use a metering plugin that shows EBU values: integrated loudness (over the lifetime of the signal), short-term loudness (showing the last three seconds), and momentary loudness (showing the last 400ms). However, the problem then becomes how to get a widget on the panel to display these values. In the language of GP, I want a plugin that sends its measurements to the host through parameters, but that’s not the language of plugin marketing (aimed at traditional DAW users), so what should I Google? The answer is to find a plugin that can “write automation data”. And, sure enough, a Google search for loudness metering plugins that write automation data led me to “dpMeter5”, which seems to be excellent. I have yet to determine whether its CPU usage will be a problem; I currently have nine instances of the plugin in my Global Rackspace (one on the master bus and one on each of my 8 instruments). If this takes up too much processing power then I’ll add a widget to disable the metering when I don’t specifically need it, but I’m hoping it’s lightweight enough that I can just leave them running all the time.
I look forward to your comments and feedback.