At this point, we have a pretty useful guitar processing "rack", but it could use a little spice. This spice will come from two additional processors: a looping delay unit, and a basic reverb system. Also, to help keep the output useful, we will drop a limiter on the back end of the entire rig.
The first processor we will add is an alternative version of the delay line – one that provides tap tempo, looping and sound-on-sound functionality. Unlike our previous delay module, this one will not provide modulation (for flanging and pitch shifting effects); rather it will be focused on capturing a loop, and allowing overdubs of additional sounds.
As with any delay line, the most important setting is the delay time. We use a standard floating-point number box for entry, but it is probably most convenient to use the "tap tempo" function that is implemented. By clicking on the tap tempo button four times, you generate a delay time that will match your taps.
The tap tempo function is provided by the taptempo abstraction at the top level of the patch. It counts four incoming bang messages, determines the three intervals between the taps, takes the average and uses that for the tempo calculation. Since it is assumed that we are tapping quarter notes, but want to use a four bar measure, the result is multiplied by four to give us a delay time value. This is an area where you might want to modify the function to meet your needs – if you really want to have the delay run at the rate you tapped, you can remove the [* 4] object at the end of the processing chain.
The basic delay design, as found in the loop_handler subpatcher, is very similar to the layout of the modulating delay. The few tweaks provided are there to support the looping functions. First, when the "Freeze" button is on, the feedback is switched to 100% feedback. This gives us a standard looping function. The feedback loop has a lowpass filter in it, which will change the audio in the loop if it is not fully open. The "Input Active" button is very important – it determines if the input signal is sent into the delay path. If it is off, the only output of the delay line is whatever is currently playing – if the delay is "frozen", you will hear the loop, while with freeze off you will only hear the remaining contents of the loop line feedback. What is cool about this is that, when you freeze the delay line, you can still overlay audio parts onto the loop – giving you sound-on-sound overdubbing. I've also implemented a click track that cycles at the same speed as the delay time. This way, if you want to work up some one-bar loops, you can hear the timing (in quarter note click) even before you begin recording. Most of these concepts are classic delay techniques, but this sort of looping function is why many people get into Max/MSP in the first place. Even if you aren't into guitar processing per se, you may find this looping delay system can jump-start your Max experiments.
What would an effects processing rig be without a reverb? As is typical for any processing rack, I've installed a reverb as the last effect in the system – this way, we will get consistent reverb from both our looped and our live guitar lines. To provide reverb, I've gone to a third-party external object: Nathan Wolek's nw.gverb~. You can find this object in a the LowkeyNW package in the Max Package Manager:
I happen to like the sound of nw.gverb~ well enough, but I've wrapped it up in another abstraction so I can replace it in the future (if I decide to do that).
If you look into the subpatcher reverb_handler, you'll see that I expose the reverb time control to the top-level patch, but I also provide a reverb mix control that uses the pan2 abstraction found in Max's examples folder. This gives me a decent equal power pan – but why would I need to pan? In reality, I don't; but I can use them as equal power channel mixers as well. By using only one output of the panner, and reverse panning the live sound, I can get a decent mixing function with very little effort. This may not be the most efficient processing stream, but it sure was easy to implement!
And a Limiter at the end…
Finally, to make sure everything stays under control, I've added a limiter to the end of the processing chain. I've improved the use of the limi~ object in the io subpatcher, setting up a few parameters to make it work as expected. I also reconfigured the output section of the Presentation Mode to make everything fit a little better, but the functionality should all be familiar from previous weeks' articles.
This is the conclusion of new module additions, but far from the conclusion of this series. For my money, some of the most important information will be found in our next two articles, where we will cover preset management ('cuz I don't want to be mousing too much on-stage) and MIDI controls (using a MIDI foot controller). Get familiar with our new modules, and prepare for more fun with our next Guitar Processing entry!