Thursday, 5 July 2018

My first visit to a Bank of Oscillators...

I have always been fascinated by sound generators. Over the years, I have done a lot of dabbling into FM, AM, Ring Modulation, Granular, FFTs and many other techniques, and what I have found is that the interesting stuff is often in the detail. So my previous forays into Reaktor produced large numbers of generators exploring lots of ideas, and I sometimes reach back into that abandoned era to provide inspiration for MaxForLive devices. This brings me to my latest sound generator, whose name tells you just about everything about it: BankOSCmr0v01.

A Bank of Oscillators...

Any sound generation method that uses large numbers of oscillators has a basic problem that can be boiled down into a simple question: How do you control all of those oscillators?' Additive synthesis is a good example: lots of harmonics means lots of things to control, and creating a powerful and appropriate 'high-level' user interface can be a difficult challenge. But my current research interest is in inharmonics, and so I wanted to explore ways of working with non-harmonically related frequencies.

After poking around in some of the quieter parts of the Max object world, I found ioscbank~, and decided that this might be suitably inspiring. The Max documentation showed filling the paired frequency and amplitude controls with random values, but I like my sound generators to produce dynamic evolving sounds, not boring static timbres. So I added scanning that swept across the bank of oscillators, gradually changing the frequency and amplitude of each oscillator, and slugged the interpolation of these parameters so that they changed slowly - and I got an interesting 'big bank of oscillator' sound that had a lot of promise.

One of the techniques that I learned when creating synth patches was to explore the extremes of the available parameters, and so I experimented with the rate that updates happened, with the interpolation time, and with the range of frequencies and amplitudes. Messing about with the amplitudes did not seem very interesting, and so I abandoned that and moved to the other parameters. (Anyone who is shaking their head at this point needs to move to the follow-up article to this one, where I realise that I nearly missed something big and went back to controlling the amplitude.) After adding some filtering and some additional tweaks, I had an interesting result that could make a quite broad range of not-so-ordinary sounds: BankOSCmr0V01.



BankOSCmr0v01's user interface is dominated by the large display in the centre, and this is not interactive at all. It is purely to show you what is going on for each of the 32 sine-wave oscillators that this version uses. The display shows the 32 oscillators from left to right, and each vertical shows the frequency as an orange square and associated bar underneath, and shows the amplitude (the volume...) as a purple square and associated bar underneath. Low frequencies and amplitudes are at the bottom, and high frequencies and amplitudes are at the top.

To control the oscillators, the controls on the left affect:
- the Rate at which the update sweeps across the oscillators from left to right
- the High and Low extremes of the frequencies of the oscillators
- the Time for the frequencies and amplitudes to change to the new values from the scanning
- a 'New' button to generate a new set of random values for frequency and amplitude (If you send a MIDI note to this device when the Rate is set to the slowest time (...all the way clock-wise: 'Run' changes to 'Stop'), then this triggers the 'New' button.)

On the right, there is a simple state-variable filter that provides low-pass, high-pass, band-pass and notch transfer functions, and has Frequency and Q controls, an finally an Output control that has a deliberately large range to partially compensate for having no controls over oscillator amplitude (and I should add a second hint about the next version here as well).

And that was that. A simple bank oscillator that generates a range of sounds using a small number of controls. Nothing particularly special so far, but then there's more coming up next time... and plans beyond that as well.

Media

Several people have asked me why I never post videos of my MaxForLive devices on YouTube, and I never had a really good reason why not, so I'm posting a simple video to my YouTube channel, which is really going to surprise my 34 subscribers! I will also do my usual SoundCloud example as well.

Getting BankOSCmr0v01

You can download BankOSCmr0v01 for free from MaxForLive.com.

The YouTube video.

The SoundCloud demo.

Here are the instructions for what to do with the .amxd file that you download from MaxforLive.com:

https://synthesizerwriter.blogspot.co.uk/2017/12/where-do-i-put-downloaded-amxd.html

Modular Equivalents

In terms of modular equivalents, then reproducing this functionality in my modulars either involved 32 VCOs and four 8-step sequencers, or advanced oscillators banks or sequencers that I can't count as 'basic' modules, so I would rate this version as being about 40 ME (or 10ME if bank oscillators are allowed, or 6ME with fancy sequencers!).






Sunday, 1 July 2018

An 'Extreme' Multiplying LFO for MaxforLive


LFOLFO is an experimental 'Multiplying' LFO. It is based on the idea that being able to switch the range of an LFO can be used to generate a number of interesting audio effects, and so the design is optimised to enable easy control of the Rate and Multiply controls. The prototype was produced as a response to a question posed by Russell Alderton on the 'Max For Live Users' Group on Facebook, and it has undergone extensive development since then.

The Rate (Frequency) of the LFO can be modulated via two controls: Rate and Multiply. The Rate control is a conventional frequency control, whilst the Multiply control has four modes that provide several ways to affect the frequency. A multiply value of 'x 1.' produces an output frequency as shown on the Rate control, whilst a multiply value of 'x 0.5' produces an output frequency of half the value shown on the Rate control, and a multiply value of 'x 2.' produces an output frequency of twice the value shown on the Rate control.

The Rate and Multiply controls both have their own dedicated Sub LFOs, which can be used to modulate them, and this is shown graphically in a display underneath the controls. The LFO output waveform is shown as a backdrop to the whole MaxForLive device, thus providing a 'history' of recent changes to the waveform.

Each Sub LFO has multiple output waveforms, and the waveform selection of Sub2 can be controlled by Sub1. The output waveform of the LFO itself can be selected using a vertical selector, or via two modulation modes: one that counts the number of cycles that have been output, and a second mode that uses a third Sub LFO (Sub3). Both modulation modes use a probability grid that can provide sophisticated control over the sequencing of output waveforms.

The output waveform can be further processed by three controls: Smooth, S&H and Decimate (which do what their titles suggest). Finally, Offset and Depth controls. plus an Invert button allow fine tuning of the range of effect on the controlled parameter - which is selected using the 'Map' button.

Sync

Conventional Digital Audio Workstation (DAW) LFOs are either free-running, or synched to the DAW transport. LFOLFO provides a different type of sync that is intended to explore an alternative approach. A selection from a number of timing sources can be used to reset the LFO waveform, and this provides an 'Event Sync' that gives a number of interesting ways working with musical events instead of being rigidly locked to a timebase.

The UI from left to right

LFOLFO has a lot of controls that it uses to provide a wide range of advanced functionality. The settings above are a good starting point for learning - they are a kind of 'Neutral' setting. From left to right, the controls are:

Storage

LFOLFO provides 9 'memories' that can be used to store and recall the state of all the controls. To store a setting, hold down the SHIFT key and click on one of the 9 boxes. Grey boxes are empty. Purple boxes contain a saved setting. The white box is the currently selected setting. If you over-write a box then the previous contents cannot be recovered - this is colloquially known as a 'face-palm' error.

Event Sync

The large selection box enables the selection of 'events' that can be used to reset the LFO output phase. The reset phase is set using the 'Phase' retry control that is underneath the selection box. The top selection is '=Not-Synched=' and this is the Free-Running mode. The next selection options are for MIDI Notes in the track clip:

- AnyNote resets the phase for any MIDI Note.
- AnyChange resets the phase for any new MIDI Note. Any repeated notes are ignored.
- Note0 only resets the phase for Note 0, the lowest MIDI Note. This note is not used very often...
- Note0Velo1 only resets the phase for a Note 0 MIDI Note with a Velocity of 1. A velocity value of 1 is very quiet.

The next selection options use the Sub LFOs. Sub1, Sub2 or Sub3 can be used to reset the phase of the LFO, as well as a special reset that uses Sub3 and the waveform cycle Count (shown on the far right hand side).

The reset happens as soon as the event is processed by the device, and the value can be set using he 'Phase' control. If the event frequency is less than the 'Rate' then one or more cycles of the output waveform will be output. If the event frequency is higher than the 'Rate' then cycles will not be completed because the reset will happen before the cycle can complete.

Sub1

The first sub LFO can be used to modulate the 'Rate' control. The 'Sub1' rotary control affects the rate of the Sub LFO, whilst the 'Depth' rotary control affects the amount of modulation. The selector box sets the output waveform. When Sub1 is used to modulate the 'Rate' control then a graphical display behind the rotary control will show the modulation.

The Sub1 LFO can also be used to control the output waveform of the Sub2 LFO. If the frequency of Sub1 is greater than Sub2, then Sub2 will output incomplete cycles of its waveform. The selection of the output waveform is in sequence, from top to bottom, and then repeats. No other waveform sequences are available in this version... The button has two settings: 'Off' has no effect on the Sub2 output waveform, whereas 'Mod' will repeatedly sequence through the four waveforms.

Sub1's modulation of the 'Rate' control can be used for a number of effects. Using a Sine waveform produces traditional smooth 'up and down' variation in the frequency of the LFO. The triangle waveform gives a more abrupt change of direction and gives a more synthetic effect. The two sawtooth waveforms are particularly good when Event Sync is used, because they can produce a number of 'rise' or 'drop' effects, where the frequency of the LFO rises or falls linearly. Note that one of the advantages of using Event Sync is that when the frequency of the events is less than the LFO 'Rate', then several cycles of the output waveform will be produced, whereas if the event frequency is greater than the 'Rate', then less than cycle of the waveform will be produced. So by adding MIDI Note events into the track clip, very precise control of the LFO output can be obtained. 

Sub2

The second sub LFO can be used to modulate the 'Multiply' control. The 'Sub2' rotary control affects the rate of the Sub LFO, whilst the 'Depth' rotary control affects the amount of modulation. The selector box sets the output waveform. When Sub2 is used to modulate the 'Multiply' control then a graphical display behind the rotary control will show the modulation.

There are four modulation modes for the Multiply rotary control, selected using the horizontal selector box on the lower edge of the device:

- Linear is a conventional modulation where the modulation increases linearly.
- Power increases the modulation in powers of 2.
- PowerHalf increases the modulation in quantised half powers of 2.
- PowerQnt increases the modulation in quantised powers of 2 (0.25, 0.5, 1, 2, 4 8, 16...)

Rate

The Rate road control is the main control of the frequency of the LFO. The output frequency is shown in Hertz. The modulation is shown graphically underneath the control.

Multiply

The Multiply control is a secondary control for the frequency of the LFO. It is rather like a 'range' control, but it can be modulated, and the rate and character of the jumps in LFO frequency can be controlled via the waveforms and the Sub1-Sub2 modulation button. Careful use of the Multiply control is the key to making the most of the functionality provided by a Multiplying LFO. Yes, you can use LFOLFO to vary a parameter with slow, smooth up and down changes, but this does not exploit the device to its full potential.

Try increasing the Multiply rotary control in each of these modes to see the effect on the 'Multiply' value. The 'PowerQnt' mode is specifically designed to change the rate in powers of 2: x .125, x .25, x .5, x 1, x 2, x 4, x 8, x16...

Vertical bar

The vertical bar shows the LFO output at the current time, and is not a control.

Waveform

The large selector box in the centre of the device serves two purposes, dependent on the mode set by the 'Waveform Mode' selector on the right - which has three modes: Select, which allows direct control of the LFO's output waveform via the selector box; plus Count and Mod3, which both use the grid in the middle of the device to choose waveforms, and the selector box then becomes an indication of which waveform is currently being output. In the Select mode, the grid, plus the Columns, Sub3 and Count rotary controls all do nothing. In the Count mode, the Columns and Count controls set the number of columns in the grid, and the number of cycles of waveform output that need to happen before the waveform changes (controlled by the cursor moving across the grid). In the Mod3 mode, then the Columns and Mod3 rotary controls are active, setting the number of columns and the rate at which the cursor moves across the grid.

The Grid

The grid is only active in Count and Mod3 modes, and allows the sequencing of waveforms to be specified. White squares indicate which waveform will be output when the cursor is in each column, an the vertical Waveform selector box shows which waveform is currently being output. If more than one square in a vertical column in the grid is white, then the output is randomly chosen from the white squares. So if there are two white squares in a vertical column, then the corresponding waveform will be chosen 50% of the time, on average. If there are three white squares, then each waveform will be output 33% of the time, on average. In the example shown above, there is just one white square in each of the two active columns, and so the corresponding waveform is chosen 100% of the time. This means that in Count or Mod3 modes, the first waveform to be output will be the Saw Down, followed by the Saw Up.

If you draw a line of white squares from the top left hand corner of the grid to the lower right hand corner, then each waveform will be played in sequence, just as in version 04. If you draw the opposite line, then the sequence will be reversed. The grid allows you to specify any sequence of waveforms, plus it allows probabilistic control over waveforms, which allows long complex waveform outputs. In summary, LFOLFO provides humungous power for creating output waveforms!

Once the waveform has been controlled using one of the three modes, then further processing can be carried out on it. This happens in the darker vertical box containing the 'Smooth', 'S&H' and 'Decimate' rotary controls. 

Smooth

The Smooth rotary control is a low pass filter that removes the sharp edges in the output waveform, but it also reduces the amplitude - so you may need to use the 'Depth' control to increase the size of the LFO output waveform. Remember that the 'Depth' control affects the output amplitude of the LFO waveform before the Smooth control.

S&H

The S&H rotary control adjusts the rate at which the LFO outputs its waveform. This has the interesting side effect of slowing down the scrolling speed of the background waveform display - but it does not change the rate or frequency of the LFO!

Decimate

The Decimate rotary control adjusts the resolution of the LFO output waveform. In the '0' position, then the LFO waveform is smooth, whilst increasing decimation values makes the output increasingly jagged until at '2.0' then there are only two values (maximum and minimum). You can still use the Smooth and S&H controls on a decimated waveform, so these three controls should be seen as a flexible way of adjusting the output waveform to your specific requirements.

Once the final waveform has been set, then the final section (on the right) does the mapping of the LFO waveform to the parameter that is going to be controlled by the LFO.

'Normal' or 'Invert' button

This button controls how the parameter is controlled by the LFO output. 'Normal' is the same as the vertical bar, whilst 'Invert' is turned upside down, so that high values of the vertical bar give low parameter values.

Offset

The Offset rotary control adjusts the output of the LFO. Normally this will be left in the default '0' position, but some parameters and other settings may require it to be changed. The output waveform display that forms the background to the device is the key to using the Offset control - you should adjust the offset so that the waveform is not clipped at the top of the bottom. (although you can use this as a deliberate effect if you wish)

Depth

The Depth rotary control adjusts the size of the LFO output (which is why it is the right-most control!), and 100% is at the middle position, so you can deliberately output larger values that will be clipped. The Depth and Offset controls will often be used together to get the exact parameter changes that are required. 

Unmap and Map

The Unmap button is only available when a parameter has been mapped using the Map control. The Map button is easy to use - just click on it and then select the parameter that you want the LFO to control. A good starting point is filter cut-off frequency in the 'Auto Filter' device. When you have correctly mapped a parameter then the name of the parameter will replace the 'Map' text in the button, and the 'Unmap' button will become available. If you click on the 'Unmap' button then the mapping to that parameter will be lost - and the only way to remap it is to carry out the mapping process again.

Getting LFOLFO

You can download LFOLFO 0v06 for free from MaxForLive.com.

Here are the instructions for what to do with the .amxd file that you download from MaxforLive.com:

https://synthesizerwriter.blogspot.co.uk/2017/12/where-do-i-put-downloaded-amxd.html

Modular Equivalents

In terms of modular equivalents, then reproducing this functionality in my modulars took anything from 10 to 14 separate 'basic' modules, with lots of patch chords (and some limitations and compromises), so I would rate this version as being about 12 ME.


Sunday, 29 April 2018

Four-Step Sequencer in Gen for the OWL Pedal

Normally this blog talks about an investigation that I have done, or describes the design and features of some software that I have produced. This posting is slightly different from this because I've finally got around to delving into Gen the 'next level deeper' bit of MaxForLive or Max, and I'm going to show you how I used Gen to create a simple four-step sequencer patch. Instead of just telling you about what I have made, this time I'm going to show you how I programmed it as well - so 'next level deeper' two ways! This is just an experiment, so what happens next depends on the feedback that I get, or don't get.

Okay, so I have known about Gen for a long time (since it was called gen~, in fact), and I have always kind of overlooked it. I'm sure I'm not the only person who glances at it and thinks that learning to program in it is going to require time to learn it, and given the plethora of programming languages that I already know, acquiring yet another one is revisiting that 'start at the bottom yet again and claw your way up to the point when you can actually program things that almost do some of what you intended' learning curve that I have climbed many times before.

Just as in writing a novel, learning Gen requires something that breaks the hero/heroine of the story out of their normal humdrum ordered world, and forces them to go out and have an interesting adventure instead. In my case, the trigger was a casual conversation with a name producer, who said that what they really wanted was something that would let them do [possible subject of a future blog posting]. I made the mistake of saying that you could easily do that as a MaxForLive plug-in, and they pointed out that in this particular application, they had to be DAW-less, and so the trap was set. I then said that there were ways of doing this without needing a laptop or computer, and they said: 'You're on!' The trap was sprung and I was caught. I was committed to going on an adventure...

At the back of my mind, driving my confident assertion: 'there are ways', were the various hardware platforms that let you program them, not in Max, but in Gen. Things like the MOD Duo, or the Rebel Technology OWL Pedal. After comparing the specifications and the prices, I went for the OWL Pedal as my first test development platform, leaving the MOD Duo as a potential future addition to my portfolio.


Rebel Technology OWL Pedal

Rebel Technology describe themselves as a London based tech collective creating radically innovative music electronics since 2009', so they immediately sounded interesting - and they were at the 2017 SynthFest UK in Sheffield too! Alongside a variety of Eurorack modular stuff, they also do a completely programmable microcontroller-based development platform called OWL, that is available as a pedal or as a rack module (and more variations coming up soon). I went for the OWL pedal, and after the usual 'wait for the postman' delay, I soon had one. Having a piece of hardware kind of ups the commitment level, so I read all the documentation, watched their YouTube videos, and generally immersed myself in Gen. [Montage of time passing whilst being immersed in Gen...] 

What I discovered was interesting, and there was an annoying little 'told you so!' voice at the back of my mind that kept reminding me what Cycling '74 have always said about Gen: that it isn't as scary as people think, and that it enables you to do amazing things, but that the one enabling thing you need to learn is a different way of looking at programming. In the case of Gen, that 'different way' is having to think about doing everything at the sampling rate, and that's quite a fundamental change in the way you conceptualise things. It's a bit like learning to hand-craft web-pages using only HTML, and then discovering that you've done it all wrong because you should have been using CSS for the layout, and HTML for the content.

My learning style hasn't changed much over the years. From the Intel 8080 onwards, my first program has always been a 'Hello World!' type of simple test, and then I have iteratively added bells and whistles (sometimes literally) until I eventually get to that 'do some of what you wanted' point. This method works for the small projects that I tend to work on, but there are lots of other ways of learning and programming that may suit you better. Whatever works for you.

So as my first patch, I wrote a patch for the OWL pedal (and it should work on the modular rack module too) that used an Expression pedal connected to the OWL Pedal to control the volume of an audio signal passing through the OWL pedal. Yep, 'Hello World!' for audio on the OWL pedal. Here's the basic patch, written in Gen:


Now it isn't immediately apparent when you first look at the patch, but there's something really interesting happening here: all of this is audio signals sampled at 48 kHz. So there are two audio inputs (in 1 and in 2 for the left and right input channels of the pedal), and these are connected to two multiply boxes (which contain just '*') and the output of the multiply boxes are connected to the two audio outputs (out 1 and out 2 for the left and right output channels of the pedal). So for every sample (48 thousand times per second), the in 1 audio input sample value is multiplied by the multiply box and the output goes to the out 1 audio output. If you multiply something by zero then you get nothing out, and if you multiply something by one then you just get the original value out. The source of this 'multiply' value is the Expression pedal (Exp). So this means that 48 thousand times a second, the position of the Expression pedal is sampled, and that sample value (between 0 and 1) is used to multiply the audio sample value from in 1 and in 2, an the outputs get sent to out 1 and out 2. That's 96 thousand multiplies happening per second inside the Owl pedal so that the volume of the inputs can be changed by the Expression pedal. Also, it means that if the Expression pedal potentiometer is even slightly imperfect, then we aren't going to get a smooth volume change, because the Expression pedal is sampled for each and every sample! Any noise or bad connection in the potentiometer is going to give the wrong value for the multiply value, and the output will jump up and down in volume. This patch design has lots of scope for improvement!

I followed this with a second patch that used the Expression pedal to pan the audio signal from left to right, and which used one of the OWL pedal's four control knobs to set the 'pan' law so that you had some control over how abruptly or smoothly the panning happened. Here's the basic patch:


This patch sorts out some of the problems in the first patch by adding a few extra boxes - compare the two patches first so that you can see what the changes are... The Expression pedal is now passed through a 'slide' box. This smooths the value so that any sudden jumps don't appear at the output. The final outputs from the multiply boxes are now limited to +1/-1, so if the multiply value somehow gets bigger than 1, then we aren't going to get excessively loud outputs - just distortion limited to +1/-1. The previous patch treated the two channels the same, but here we want to pan from one channel to the other, and so the smoothed Expression pedal sample is inverted for the in 1/out 1 (left) channel using the box with '!- 1.' in it. What this box does is subtract the Expression pedal value from 1, so a value of 0 outputs a 1, and a value of 1 outputs a 0. (This is just a weirdness of the way that Max does this type of function - just think of it as 'inverting' the value) So as the Expression pedal goes from 0 to 1, then the two channels will get opposite multiply values.

Unfortunately, pan isn't quite as straightforward as this in practice. So here's a revised version that sounds much better - and notice the extra multiply boxes, two new boxes and a new control...


What those boxes do is change the 'pan' law - the amount of overlap as the audio is panned across the stereo image. What happens is that the smoothed D' control knob on the OWL pedal is used to control if the law is linear or uses a quarter sine wave 'non-linear' law. (this is what the 'expo' box is doing). This isn't a perfect way of doing this, and there are much better ways of doing it, but it is simple and works quite well for my ears.

(Don't worry about going back and re-reading this explanation as you trace through the patch diagram  - there's a lot happening here, and as I have said too many times already, it all happens 48 thousand times per second!)

Having said that Gen is a 'deeper level' than Max, then it is probably time to show how Gen fits into the Max programming environment. Here's the Max patch that the Gen code is 'inside':


As you can see, the Gen code looks just like any other Max object, and the programming environment is familiar. It's just that things work a little bit different inside the 'gen' object... At the level of the Max patch, then we set up the inputs and outputs, and you can see that I have left a couple of number boxes and 'scope' objects in the patch, ready for using to view what is happening inside the Gen object -
which is the little box on the mid left hand side that I have put a purple rectangle around.


Gen doesn't provide the same depth of assistance as Max does, and so you need to do a bit more work to monitor what is happening inside a Gen object by using extra in or out objects. I think of it as a bit like trying to do things through the letterbox in a front door... I will try to show how this works as we go along, because it is one of the key skills to have when developing Gen, and it is easy to overlook when concentrating on the Gen code itself...

(It is also important to point out here that the OWL Pedal is only going to do the stuff inside that 'gen~' box. Some of the standard Max functionality isn't implemented in Gen for a variety of reasons, and so you need to approach things slightly differently - so it isn't just a case of putting standard Max objects inside that gen~ box, and you can't add Max objects outside of the gen~ box and expect them to work. 'Inside the gen~ box' is the key to this.)

My next patch took one of my old MaxForLive patches, and turned it into Gen. I had to do quite a bit of user interface simplification in order to cope with only having four control knobs, an Expression pedal and a pushbutton, but the result was quite encouraging: a stereo delay box with an unconventional way of doing things, and some quite unusual sounds. Rather than bore you here with yet another 'unique' delay patch (for some reason, the world is full of delay patches whose creators think are amazingly different),  then it felt like time for some more novel writing 'advance the plot' activity. If you are interested, then you can find the patch in the online library for the OWL devices - I'm called 'registration' because that's the email account name that I used. I'm also going to upload it to my Github repository at some stage...

Anyway, having told you about all of this preparatory work, it was now time for the next step nearer to what I had been so confident I could make for that producer. I took an idea and turned it into a patch, without basing it on a tutorial. This patch is the real topic of this blog post!

Four Step Sequencer

The OWL pedal has four control knobs, so it makes a four-step sequencer an obvious choice, and I wanted to make something self-contained: a step sequencer plus a simple sound generator. Using the pushbutton as a tap tempo source leaves just the Expression pedal as a possible timbal control. So if you have only one control, what gives the widest range of sounds?

After a bit of experimentation... Okay, after a lot of messing about... I dragged myself away from my modulars and decided on a slightly unconventional approach influence by Reaktor-style sound generators (Look up 'Flintpope' for some amazing examples!). I would use that single remaining control to set the rate of an LFO that sweeps a resonant low-pass filter past a pair of detuned oscillators, which is quite a lot of indirection... This means that this patch is more self-contained, and a bit more like a factory demo than a generically useful patch (and I've done various bits of paid 'impressive demo'-oriented work over the years), but as a learning patch, as something for people to tweak, to derive other patches from, then I think there is huge value in demo patches, especially when they aren't buried in reverb.

So how do you do timing in a the world of Gen? If everything is happening 48 thousand times per second, how do you work at a slower rate? The solution I chose is to just use a counter so that we slow down those thousands of times per second into something that works at a more human-oriented rate. You can do this in gen~ by using the 'phasor' object, which is a counter that counts from 0 to 1 at a rate set by a clock rate derived from the processors chip's master clock. There are lots of other ways to do timing in Gen - using the 'phasor' object is just how I did it in this case. Let's start by looking at the whole finished patch:


Okay, so there's lots more happening in this patch! So let's break it down into sections and look at each of those in isolation.


Top right deals with the timing, and that's where we will start. Across on the top left is the sequencer, and the lower half is the audio section.

Let's start with the timing. There are two linked timings that we need: one to produce the 4 steps that we will use for the sequencer timing, and another one to produce the envelope timing for the notes played by the sequencer. The sequencer timing is the easier of these to understand, so let's start with that.

Step sequencer



The box at the top right is the illuminated push-button in the centre of the OWL pedal - not to be confused with the big chunky foot-switch that can be used to bypass the pedal, in standard guitar-pedal style. The little pushbutton outputs zeroes normally, and ones whenever it is pressed. This appears at point (A) in the Gen code, and on the timing diagram below.


The output of the push-button goes into a pre-prepared 'encapsulated' gen~ object (from a Rebel Technology tutorial example) that measures how many 48 kHz clocks happen between presses of the push-button ('taps' in tap-tempo-speak) - a 'tap-tempo' box. The 48 kHz clock is the master timing source in the microprocessor used inside the OWL pedal, so this is how fast we sample those push button presses, and the measurement of the number of clocks that this gives us is thus the 'time' between buttons presses - in other words: beats.

We will be using the Max/Gen 'phasor' object to do our timing. The 'phasor' object produces a sawtooth waveform at a rate set by a 'frequency' input. Essentially, it is just a counter that starts at zero and counts upwards. But the 'phasor' Gen object that we are going to use to produce all our timing requires a frequency input, and all we have from the tap tempo is a time - so how do we convert time to frequency?

By dividing the 'time between push button presses (beats)' by the 48 kHz sample rate (Gen's variable for this is called 'samplerate'!), then you get the frequency of pressing the push-button. Assuming four beats per bar when the push-button was tapped, then this frequency is four times too fast, so we need to have a division by 4 - this will give the correct frequency for a complete bar from the phasor object.

Here's a quick aside about tempo and frequency.

Unfortunately, tempo isn't expressed in frequency - it is normally in beats per minute, and our frequency is going to be in Hertz. Let's go through this with some real-world numbers. Suppose the time between taps is 1 second, This means we are tapping at 60 beats per minute, because that's once every second for 60 seconds to fill the minute. 60 taps per second is 1 Hz, or one cycle per second. If we tapped twice as quickly, then the time between taps would be half a second, and in the 60 seconds in a minute, we would have tapped 120 times. 120 taps per second is 2 Hz.

The last thing we need to think about to produce the frequency for the phasor object is the length of a bar. So far we have figured out that 120 bpm is 2Hz, but if we have 4 beats per bar, then the bars per minute is going to be a quarter of 120, which is 30 bars per minute. We want the phasor object to produce one sawtooth per bar, so that's why we want to set the phasor object to run at a quarter of the beat frequency that we have measured using the tap tempo.

If you plot the time from the output of the tap tempo against the frequency that we need to drive the phasor for one sawtooth per bar, then it looks like this:

tap tempo time per beatphasor frequency
2.00.125
1.00.25
0.50.5
0.251.0
0.1252.0



And this shows us how time and frequency are related: it is called an 'inverse' relationship. As the time between taps gets longer, the frequency goes down, whereas as the time between taps gets shorter, the frequency goes up.

And back to the sequencer...

The conversion of the beat frequency to what the phasor needs is done by the box that contains '!/ 0.25'. 0.25 is 1/4, which takes care of the 4 beats per bar.



The 'phasor' object in Gen works much the same as in Max - it outputs a rising count at a rate that depends on the input. In this case, the rate is set by the tempo, and so we get a sawtooth (rising count) that resets every bar, starting at 0, and rising up to 1 (I'm going to totally ignore the internal representation of numbers inside the OWL pedal - because you don't need to know about 'floating point representations' and 'this number of bits' to program in Gen.). Multiplying this sawtooth by 8 gives us a minimum of 0, and a maximum of 8 (it just makes the 'height' of the sawtooth bigger), and this is used for timing elsewhere in this patch. For a four step sequencer then we need it to go from 0 to 4, and this time I'm gong to do it sensibly - by multiplying by a half!

(Notice that when I multiply the 'time between taps' measurement, then this affects the tempo, but multiplying the sawtooth waveform that the phasor object produces just changes its size (or amplitude in tech-speak).)

The sawtooth that goes from 0 to 4 once every bar is at point (J) in the Gen code and in the timing diagram. The final object of the 'ceil' box, and this just converts the sawtooth into the integer equivalent. It does this rather generously, and so it outputs 1 whilst the sawtooth goes up from 0 to 1, then 2 whilst the sawtooth goes up from 1 to 2, and so on. 'Ceil' is shorthand for 'ceiling', which explains why it takes the high value! Notice that it never outputs 0, so all the time that the sawtooth is less than 1, the 'ceil' object is outputting 1.


So at point (K), the output of the 'ceil' box only has four direct values: 1,2,3 and 4. We will use these to make the step sequencer choose values from the four rotary controls. The 'selector' object box is like a four-way switch: only one input is connected to the output at one time, and the control input (on the left hand side) controls which switch is closed. So when we connect the four rotary controls to the inputs of the 'selector' object and connect the 1,2,3,4 stepped sawtooth waveform into the control input, then the selector switch will scan across the four rotary controls at a rate set by the tap tempo.



I have to apologise at this point. In their most basic form, sequencers really are exactly this simple. They repeatedly scan across a number of controls, getting the value from each control, and outputting it. Look at the Gen code and follow the text above again if you aren't sure that the code is just a direct translation of what a sequencer does.

Debugging

I mentioned earlier that I would show how debugging works in Gen, and you probably wondered how I know what the waveforms at points A, J and K actually look like... To do this, you just add extra outputs ('out' objects) in the Gen code, and then connect these outputs to scope or number objects in the Max environment, so that you can look at the waveforms.

So here's a close up of the J and K points:


So the point that I have labelled as 'J' previously is now connected to an added 'out' object: 'out3' in this case, and the 'K' point is connected to 'out4'. In the Max environment, then we just use scope~ objects to see what the waveforms look like:


The 'out3' output shows the sawtooth waveform output of the phasor object, and so is connected to a 'scope~' object so we can see what it looks like. (I then turned this into the diagrams used earlier).

The 'out4' output is also connected to a number box, so that I can double-check that the 'ceil' object only outputs 1,2,3 and 4. I didn't show that bit of the Gen code, but there's also an 'out5' being used here, but the scope~ object for that is cropped off the bottom of the screenshot.

So that's how you see what is happening inside the Gen code, and this is one way to debug as you develop your design. When you don't need the debugging any longer, then you just delete all the added 'out' objects in the Gen code.

Main timing (envelope)




The timing for the envelopes uses the same phasor object, but this time I wanted to have envelopes lasting half of the step lengths: so 1/8th notes. This is why the phasor is multiplied so that it goes from 0 to 8. You can see this at point C.

If we use the 'wrap' object, then that 0 to 8 sawtooth gets 'wrapped' into the space between 0 and 1, and we get the waveform at point D. This is a sawtooth running at 8 times the bar length, and twice the step sequencer rate: in other words - 1/8th notes. Unfortunately, the 'phasor' object outputs a rising sawtooth, and percussive sounds require a falling sawtooth, so we invert it by multiplying by -1 (the  '*-1' object ) to give point E, and then we add 1 to it ( '+ 1' ) to get point F. This is a falling 'ramp' at twice the step sequencer rate, so we need to do some more processing to get four ramps to match the step sequencer.

This is achieved by using the 'ceil' object again, and this turns the unwrapped 0-8 sawtooth into a series of numbers: 1, 2, 3, 4, 5, 6, 7, and 8, and then using the '==1' object to produce a 'gating' signal. The '==1' object is normally 0, and goes high when the input is equal to 1 - hence the '==1'. So by putting four '==' objects in parallel, we can produce gates that go to 1 for the 1st, 3rd, 5th and 7th falling ramps. Using these gates on the falling sawtooth will give us just four 1/8th note falling ramps which are perfect for using as percussive envelopes, and which are locked in sync with the step sequencer - you can see this is you compare all of the points:



So if you look at K, the the four percussive envelopes in H match exactly to the four steps in K.

Note that if you change the '==' numbers, then you can choose different timings for these notes.  I will leave it to you to work out the limitations of this approach...

Here's a screenshot from actual debugging during development, showing points B, C, G and H, all output using 'out' objects into four scope~ objects in Max.


LFO and Frequency control


The Expression control (an eternal control pedal plugged into the OWL pedal) is used to control the rate of an LFO that modulates the cut-off frequency of the 'VCF' in the audio section. This time, instead of the phasor object, the 'cycle~' object is a better choice, because it outputs a sine wave, and the smooth waveform is perfect for slow filter modulation. The Expression pedal output (from 0 to 1) is adjusted to a suitable range of rates for the LFO, and the output of the LFO (-1 to +1) is scaled and has an offset added so that it output a sine wave that goes from 0 to 1.

Audio section


The audio section takes the four pitches from the step sequencer and uses them to drive two slightly detuned sawtooth oscillators made using 'phasor' objects. These are then mixed together and fed into two low-pass resonant filters in series. The percussive envelopes from point H are fed into the same 'slide' object that has been used to 'smooth' all of the rotary control knobs and the Expression pedal input, but this time it is used to lengthen the release time by lengthening the ramp. If you change the 'i 1' object to a higher value number (e.g. i 50), then the attack time will lengthen and you won't have as percussive a sound. The LFO sine wave and the percussive envelope are scaled (LFO sweeps a 5000Hz range, whilst the envelope only sweeps through 1000Hz) and are used to control the cut-off frequency of the filters. The '1 0.8' box sets th resonance of the filter at 80% - mainly because resonant filter sweeps are a classic sound, but you can change the value if you want - although going to close to '1' will cause the filters to self-oscillate, which isn't good in this type of application (unless you want a siren effect!).

The percussive envelope is also used to drive a VCA that envelopes the output of the series of filters. A DC-blocking filter prevents any problems with very low frequencies, and the final output goes to the two main stereo outputs of the OWL pedal: called 'Out1' and 'out2'.

Conclusion

Let's go back to the beginning of this blog, and review the progress. We started by implementing a simple guitar expression/volume pedal, and we ended with a 4-step sequencer driving two detuned sawtooth 'VCOs', into a resonant 'VCF' with an AD envelope and a sine wave LFO driving the cutoff frequency, followed by a 'VCA' driven by an AD envelope. All in a tiny pedal box, and there isn't very much code - there are just 57 of those little Gen object boxes at the op level, and the 'Tap Tempo' adds a few more.

For me, the hardest bit was figuring out how to compile the finished code and get it into the OWL pedal, which involves going to the Rebel Technology site and using a web interface. Once you've got the hang of it, that isn't difficult either - and Rebel Technology have lots of video tutorials on YouTube so you can see what to do.

So what was the best bit? Actually, figuring out how to do all of the timing by using phasor-based sawtooth waveforms was my favourite activity. Putting those extra 'out n' objects into the Gen patch and then looking at the waveforms in the outer Max patch was just like probing a circuit with an oscilloscope. Most amazing of all - working at 48 kHz wasn't anywhere near as scary as I expected!

I hope that you have been inspired to consider looking at programming an OWL. There is a lot of information on the Rebel Technology web-site, and the forum is full of people who can help. Have fun!

Links

Things mentioned in this blog posting:

Cycling '74 Gen

Mod Devices MOD Duo

Rebel Technology OWL Pedal

Rebel Technology OWL Modular

SynthFest UK

Native Instruments Reaktor

Flintpope

Compelling problems - making things happen in novels

Hello World!

And finally!

If you have got this far down the page, then you  might be interested in the previous blog posting on the OWL pedal - How to add a footswitch input!