Last time out, we created the LFOur, a generative patch composed of a quartet of synchronized LFOs whose output we can use to make noise. While it's interesting to watch how the different LFO configurations make combinatoric waveforms and it's restful and instructive to watch the sliders flick and rock, it would be nice to have something to connect it to. This tutorial includes some patches that will do just that.
All LFO tutorials in this series:
- LFO Tutorial 1: The Zen of the Silent Patch
- LFO Tutorial 2: Making Some Noise
- LFO Tutorial 3: Extending Our Generators
- LFO Tutorial 4: Building Complexity
- LFO Tutorial 5: LFO Child Slight Return
- LFO Tutorial 6: Live If You Want It
- LFO Tutorial 7: Rattle and Hmmm
- LFO Tutorial 8: Valediction
The modest little LFOur_out patch is an example of how you might use some of the messages the LFOur patch sends while it's running to make some noise. This patch and uses the humble and ubiquitous DLS synth, using the LFOur patch's waveform triggers and the sampled values to trigger patterns whose pitches, velocities, and durations are generated on the fly.
The patch consists of the same basic module repeated four times. You'll notice that each of the four units has a trio of objects, each of which itself consists of the same three objects: a umenu object containing the list of outputs that the LFOur patch generates (bang messages or sampled LFO values), and a message box containing the message “set $1” connected to a receive object. This trio of objects lets you choose which of the LFOur patch's outputs you want to use. The part of the patch that lets you select note values adds an additional zl reg object; since you'll be triggering events at a faster rate than you're likely to change note values on the LFOur patch, the zl reg object serves a similar function to the Max int or float objects - it'll store the note value as a symbol and then output it whenever the zl object receives a bang message.
The trigger and sampled LFO output data is then routed to a subpatch called notemap, where all the data scaling and note generation happens. Here's what's inside of the subpatch:
This subpatch includes another of your old favorite Max objects now updated for the new ways of dealing with timing - the makenote object. Instead of specifying a time interval in milliseconds as we always used to do, we can now use a notevalue argument (4n in this case) to set the length of the output note, and the object can set new durations when it receives notevalues in its right inlet. We're just using the notevalues output by the LFOur object with no modification whatsoever.
Setting the MIDI note numbers and durations to create notes is a matter of deciding how to convert the LFO range outputs (0 - 127) into something meaningful. In this case, I used a scale object to tweak the range of velocities. While I could certainly have just taken the sampled outputs and used the 0 - 127 data for the MIDI note numbers as was, I decided that I'd rather do something that would be personally more useful: I created a coll object (you'll find it in the top-level patch. It's called coll_sequence1) with a collection of 16 different pitches, and scaled the incoming sample values to the range 0 - 15, using that number as an index into the coll object's collection of pitches.
I got a little tired of swapping back and forth between windows and the GlobalTransport window, so I added a little logic that would let me start both the Global Transport and enable audio processing in the LFOur patch, together with a little logic intended to flush out any notes that were “stuck” because I stopped the transport before a note-off message could be sent (that's why the midiflush object is there.
If you'll remember I originally added some receive objects to the LFOur patch that would let me change presets remotely, as well as enabling/disabling the data sampling and setting the notevalue rate used to sample the LFO outputs. Adding a few send objects lets me set all those values remotely.
Finally, I added some pattr awareness using the stupidly simple 4-step method described in the LFOur tutorial.
Adding a Softsynth
While the DLS synth is fine for most things, I thought it'd be nice to use my patch with one of my trusty VST synths. The only real difference that this change required was a quick look at the vst~ refpage and helpfile to determine what kind of message I had to send to a synth hosted by the vst~ object in order to play a note. As the vst~ object's help file makes clear, all I really need to do is to precede the same set of note-on/note-off messages I sent to the DLS synth with the symbols midievent 144.
The process for converting my DLS patch for use with VST synths looks kind of embarrassingly simple: here's the only bit I changed:
The noteout object has been replaced by a pack object that combines note number and note on/note off messages and one of my favorite stupid Max tricks. I've added a pak object whose arguments are midievent 144 0 0 and then sent resulting the note list from the pack object into the third inlet. Both the pak and pack objects let you send a list into any arbitrary inlet, where the items in the list will be “unpacked” inside the object. Oh, sure - I could have used two prepend objects, but why use two objects when one will suffice?
The results of all this? It'll depend on what you do with it - the rest is up to you. Fire up the LFOur patch, launch the LFOur_out and/or LFOur_vst patches, and click on the purple button to start things up. After that, it's a matter of changing parameters and listening. I'm sure there are a lot of improvements you may want to make in nearly every corner of these patches.
The thing to remember here is that all those bangs and sampled outputs are only meaningless numbers and messages being mapped to something else. You can add LFOur outputs to any patch you've got, and so on. That's up to you.
A Final Word
One final parting gift: if you're not crazy about the sequence stored in the sequence_1 coll, I've included a little patch called coll_loader that you can use to load new sequences.
Since the data space is global, you can just launch the patch while things are running and input new sequences by clicking on the button and then clicking on the kslider object 16 times. If you've got a MIDI keyboard, you can select it as an input by double-clicking on the notein object and then playing 16 notes.
Next time out, I'll add some "structure" to the proceedings by adding timed events.