Saturday 9 February 2019

Modulated Sine Waves Two Ways - A Recipe in Two Parts (Part 2)

In the first part of this post, I covered the 'gen' part of how I made an FM drone generator based on the Rebel Technology Tutorial Workshop at Somerset House, London, in December. In this second part, I look at taking the gen code and turning it into a Max For Live device.

My starting point was as generic an FM sound generator as I could produce, using the many workshop attendee examples as the starting points (so the underlying examples in the workshop are a strong influence here). The gen~ code and the block diagram for what I made as my underlying oscillator module looked like this:

Now Gen is part of Max, and I was still running Max 7.3.5 at the time, because I'm a cautious updater rather than a b/leading edger. My plan was to leave the gen~ code alone and just put it inside a Max For Live device, which is where things got interesting...

So here's the gen~ module inside a Max For Live wrapper, with added spectrum display and rotary controls. 

Now you may have seen a social media post reporting that some versions of Live 10 and Max 8 doesn’t do exactly what you might expect with gen~. I saw it, so I contacted Cycling’ 74 and Ableton (which, btw, is always the best route: social media can sometimes be unreliable) and found that the Live 10.0.6 release should be fine with editing gen~ if you are using the full licensed Max 7 or Max 8. 

As a related sideline, I also learned something very interesting: Max 8 introduces a new object called ‘gen’ that works for events. Despite the name, that lack of a squiggly tilda is very significant. The underlying technology that you see in all of the gen~ patchers that I have been showing is called Gen, and it provides access to ‘lower level’ objects than the ones you get in Max, as well as embedded code. In this example, I’m working with audio signals, and so I'm using the gen~ object, not the ‘gen’ object.

Now  I wasn't aware of the new ‘gen’ object, and it is always good to take a look at new things in Max. So to find the differences between the gen and the gen~ objects, I looked at the help pages inside Max:

So rather than try and explore unknown territory with Live 10.0.2 (and more recently 10.0.5) I decided to update from Max 7.3.5 to Max 8.0.2, and to convert from using gen~ to just Max so that I could leave exploring using gen~ inside Max For Live for later on, when Live 10.0.6 is released (which now seems to be part 3 of this two-part blog post). So not quite the easy 'write it in gen~ and use it anywhere' that I was going to do, but at least I had learnt a lot, and I was now slightly more cautious about my planned next step follow-up, which was to explore the possibilities of the 'gen~-to-VST’ process (part 4!).

So the new 'first' task for a Max For Live version was now to turn this 'gen~' code into Max For Live for each of the bits that were inside the gen~ object in the grey screenshot several shots above.

This is the top level of the gen~ code, directly translated from gen~ into Max. Because Max has a toggle button already, then all of the DIY code to create a toggle button isn't needed here! The number of oscillators has also been increased: 10 pairs giving 20 oscillators here.

The 'spreader' code is almost exactly the same! Now I know that in Max 8, there are built-in functions to allow you to create 'spread' parameters for the multiple instances of a patch that you get by using the 'mc' object, but that would completely wipe out the 'gen~-to-Max' theme that I started with, and will be something I will look at in a future post! (Also, the spread functionality is in Max, and not in gen~, and so it won't work for projects that can only use gen~, as is the case with devices like those from Rebel technology.

As in the gen~ code, in the translation-to-Max, there are two oscillators, one detuned by 1.001 (I didn't spend any time optimising this!) and a straight-forward LFO-driven anti-phase panning circuit. Above this, there is the modulation section, which has another LFO (that can also run at audio frequencies...) and uses a selectable '+' or '*'object to do the modulation. The '+' gives 'linear' 'vibrato-style' FM and the '*' 'multiply' object gives 'multiply' FM (FM = frequency modulation). In this implementation (with these frequencies and modulation indexes), then 'Linear/vibrato' gives a milder sound, whilst 'Multiply/FM' is much brighter in timbre. Having two different sound source timbres is always good, and in Max For Live it is easy to add a switch for it. In hardware devices like the OWL Pedal, then adding a toggle switch isn't quite as straight-forward - but I have done it and this is described in a previous post in this blog.

One final translation is something which I've long wondered about why there isn't a pre-made object like this in Max. The 'dc-block' gen~ object stops DC voltages from getting into the audio output, and for an FM-based sound generator, then it should be very useful for avoiding 'clicky' speaker-stressing audio signals.

The contents of the DC-block patcher aren't complex - it is just that the parameters are tricky to remember!

Anyway, the final MAX-ified version has three repetitions of the 20-oscillator 'grey screenshot' above, and so provides 60 oscillators across three separate 'parts'. This gives some very interesting sound generation possibilities. Finally, I added MIDI input for pitch, so this is now a simple monophonic instrument for making drone sounds with various timbres and frequency content. Enjoy!


You can download INSTsineATMOSPHERE for free from

If you drag the .amxd file that you download from into the 'Third Party Packs' folder in 'Places' in the Brower panel on the left-hand side of Live, then you will be able to find it easily when you need it.

Modular Equivalents

In terms of modular equivalents, then reproducing this functionality using just basic modules in my modulars just required lots of VCOs and LFOs. But 60 VCOs is a lot of modules, and when you add LFOS it gives a modular equivalent of 120 ME, with a lot more modules required for the panning... If I throw away the 'you can only use basic modules' requirement, then things are different, but then we lose any basis of comparison.

Buy me a coffeeBuy me a coffee

No comments:

Post a Comment