Showing posts with label MAX. Show all posts
Showing posts with label MAX. Show all posts

Tuesday, 30 March 2021

MIDI Pitch Bend - A Tiny Inconsistency

Sometimes 'The Bears' really are lurking, ready to get you if you step on the cracks between the paving stones... 

One of the things that has been beaten into me, over many years of working with hardware, firmware and software, is a rule that has many forms, but which boils down to something like:

"Question everything. Measure everything at least twice. Always ask: 'Why?"

It is an expanded version of the 'Never Assume Anything' rule. It has served me well. But you must never let your guard down...

Ever...

Photo by Synthesizerwriter

The MIDI Pitch Bend Inconsistency

As with all unexpected things, it crept up on me silently, unannounced, from a direction I wasn't expecting. When you have spent a long time with something, then you think you know about it. Since I got my first copy of the original MIDI Specification back in the mid 1990s, then I have read it carefully and repeatedly. I spotted some of the things that were put in there by knowledgable hardware people who really knew their stuff, like what a MIDI Clock message actually looks like 'on the wire' of a 5-pin DIN cable, and why it was defined like that. And since you are now intrigued, I'm going to leave that until another post...

So the original MIDI Specification 1.0 (1996) has a section for Channel Voice MIDI Messages, starting with Note On (0x8n in modern formatting, but shown in mid 90's style as 8nH, where 'H' means Hexadecimal and 'n' is the MIDI channel (0x00-00xF or 00H-0FH for 1-16)), then Note Off (0x9n, 9nH), through to Pitch Bend (0xEn, EnH). After that you have the System Common MIDI Messages, which all start with '0xF'. So all of the 'highest bit set' values are specified, from 0x9 to 0xF.

The Pitch Bend message is the last of the Channel Voice messages to be specified, and the specification  contains just two paragraphs - the second of which is just two sentences and is just clarification about sensitivity. Here's that first paragraph:  

This function is a special purpose pitch change controller, and messages are always sent with 14 bit resolution (2 bytes). In contrast to other MIDI functions, which may send either the LSB or MSB, the Pitch Bender message is always transmitted with both data bytes. This takes into account human hearing which is particularly sensitive to pitch changes. The Pitch Bend Change message consists of 3 bytes when the leading status byte is also transmitted. The maximum negative swing is achieved with data byte values of 00, 00. The center (no effect) position is achieved with data byte values of 00, 64 (00H, 40H). The maximum positive swing is achieved with data byte values of 127, 127 (7FH, 7FH).

There are quite a few important take-aways in this paragraph. Firstly: Pitch Bend messages are ALWAYS 14 bit resolution. Now I've done quite a lot of Max and MaxForLive devices, and Max is a very useful general purpose tool for exploring MIDI... In Max, there are two basic objects that are used specifically for receiving Pitch Bend messages (there are other, more generic MIDI 'parsing' objects...): 'bendin' and 'xbendin'. 'bendin' is the 'basic' object, and it returns 7-bit values for pitch bend of 0-127 (a single MIDI data byte), whilst 'xbendin' is the 'extra precision' object, and it returns 14-bit values from 0-16,383 (two MIDI data bytes)). 

7-bit and 14-bit Pitch Bend objects in Max

The next important thing here is that the 'bendin' object is throwing away the second byte, the Least Significant Byte (LSB), so the values that you get are just the raw 7-bit values (0-127) that are in the Most Significant Byte (MSB). As I'm sure you know already, individual MIDI 'bytes' only have 7 bits available for data, which is why the value doesn't have the range of 0-255. You need multiple MIDI 'bytes' in a message to get extra resolution. In the 14-bit-oriented way that MIDI represents higher resolution numbers, then for a value represented with two 'bytes', the MSB is the top 7 bits, and the LSB is the bottom 7 bits. So the range covered by the LSB is from 0x0000 to 0x007F (0 to 127) in steps of 1, whilst the MSB is from 0x0000 to 0x3FFF, in steps of 128. Now 0x3FFF is 16,383, so that's where the full MIDI Pitch Bend resolution of 0-16,383 comes from.

Note. I need to point out that Pitch Bend messages, by design, should include 14-bit 'extra precision' values - as noted by the MIDI Specification - because pitch bend is a 'special purpose' controller. Max and MaxForLive provide access to the 7-bit lower resolution value only because that value can then be used for other things, anywhere in MIDI or Ableton Live, or even externally if you convert it to a Control Voltage. For the control of pitch, then 14-bits are a much better idea, because this will give you nice smooth changes of pitch.

Ok. All sorted.

Not quite. There's a problem. 

Pitch Bend is bipolar: it can be positive or negative. In MIDI, the 'no bend', middle, detented position is defined as being a value of 8,192 (0x4000 or 4000H), which would be output as a value of 64 from Max's 'bendin' object and as a value of 8,192 from Max's 'xbendin' object. Max does provide another special object, called 'xbendin2', and this outputs the two 7-bit Bytes separately, so you can see the actual MSB and LSB if you want to. 

So negative Pitch Bend is the 64 values from 0 to 64 when we are talking 7-bit resolution, and the 8,192 values from 0 to 8,192 for 14-bit values. All perfectly fine and reasonable. But the positive Pitch Bend is slightly different. it can only go from 64 to 127, which is 63 values, because the highest 7-bit value MIDI allows is 127. yes there are 128 possible values in 7 bits, but if you start at 0, then you end up at 127. There are 128 values between 0 and 127. Max's 'bendin' object only provides 7-bit values for controlling other 7-bit parameters, and you would not use it for actually bending the pitch of a note - you would hear the steps! But the smaller numbers do make it very clear what is happening...

In 14-bits, then it goes from 8,192 to 16,383, and there are only 8,191 values, because 16,384 is ever so slightly larger than you can represent in a 14-bit number. 

The MIDI Specification 1.0 doesn't hide this. That final sentence of the first paragraph says:  

The maximum positive swing is achieved with data byte values of 127, 127 (7FH, 7FH).

The previous two sentences in the paragraph define the centre position and the maximum negative swing - but most people don't notice that 0->64->127 and 0->8,192->16,383 aren't symmetric. There is one less positive number than negative, and it is not hidden, it is in plain sight, printed in the specification. Unfortunately, the big numbers (16,383, and 8,191) tend to obscure what is actually happening...

In other words:

If no pitch bend at all has a value of zero, then the most negative pitch bend value is -8192. But the most positive pitch bend is 8191. (14-bit values are used here because these are what pitch bend applies to!)

Yep, The Bears just got us. 

The MIDI Pitch Bend Message doesn't allow us to bend up by the full amount. We can bend down and produce 64 7-bit messages or 8,192 14-bit messages (assuming our MIDI Controller outputs every value as a message, but that's another story). But when we bend up, then there are only 63 7-bit or 8,191 14-bit messages that can be output. That final value (8,192) is just outside of what MIDI allows. 

This means that if you set your PitchBend sensitivity to be 1 octave, then you can bend down by exactly one octave, but you will only be able to bend up by slightly less than one octave. The Owner's Manuals for MIDI Controllers, synthesizers and any other devices that output MIDI Pitch Bend messages generally say it exactly like it is - they say what the maximum positive output is. What they tend not to mention is that this is slightly less than what you need to do a pitch bend up that has the same range as a pitch bend down. And with 14-bits of pitch resolution, then the difference is very tiny. Miniscule.

In fact, I would guess that you've never noticed it...

So if you want exact pitch bend that utilises the end-stop of the Pitch Bend wheel or lever, then you should only bend downwards. This applies to any device that uses MIDI 1.0, regardless of age, firmware, operating system or manufacturer. Oh, and MIDI 2.0 is... different, because it has even higher resolution available.

Actually, there's another solution, and that is to not use the limits of the Pitch Bend wheel or lever (or push pad, or however it is implemented on your device), and that is to set the range to one note more than you require, and then to only move the wheel, lever, etc. by the amount required to get the bend you actually require. So for an octave, you might set the range to 13 notes up and down, and then only ever bend up or down by 12 notes. This gives perfect pitch bending, albeit with slightly less than the resolution of 16,384 values that were intended by the MIDI specifiers (but only very slightly less!). It does mean that you can't use the end stops of the wheel, lever, etc, but that's a minor inconvenience, and Pitch Bend by ear is so much better than relying on mechanics...

Oh, yes, and if you are thinking that this is a tiny difference in the pitch bend, and that it doesn't matter, then re-read that section in the MIDI Specification 1.0. It says that the MIDI Pitch Bend messages always use 14-bits resolution BECAUSE '...human hearing... is particularly sensitive to pitch changes.' I will gloss over the fact that it then goes on to define positive MIDI Pitch Bend so that it isn't perfect in precisely the place where human hearing is particularly sensitive. 

Not an Error

Actually, there is no error at all here. Nothing to see. This isn't a mistake by the people who wrote the MIDI Specification 1.0. It is nothing more than a consequence of the way that number work in these particular circumstances. Image the simplest pitch bend controller: three positions, No Pitch Bend (in the middle), Full negative (at one end of the travel of the wheel, lever...), and Full positive (at the other end of the travel). So these could be represented by -1, 0 , and +1. But this gives a jerky pitch change, of course!

If we increase the resolution by 5 times, something interesting happens. The range is now -5 to 0 to +5, and there are 11 values instead of the 3 values that we had for -1, 0, and +1. So if we start with the most negative value (-5) and assign it to 0 on the pitch wheel, then the middle (zero) value will be at 6 on the pitch wheel, and the most positive value will be at 11. Aha!: We have a Marshall Amplifier 'goes up to 11' situation. Unfortunately, no matter how the range and the resolutions are set, there will always be an odd number of values, consisting of the negative numbers, plus the negative numbers, plus that zero in the middle. So we need a controller with an odd number of values (which would also be very useful for that Marshall amp!)...

The binary world of computer is even. The basic counting system (binary) is based on two values: 0 and 1. So if you have just one bit to represent a number then there are two possible values: 0 and 1. Two bits gives four values: 00, 01, 10, and 11, which are 0, 1, 2, 3, and 4 in decimal number form. Any number of bits used will always give an even number of possible values. MIDI's 7-bit numbers have 128 different values, which are normally shown from zero: 0 to 127.  MIDI's 14-bit numbers have 16,384 different values, and if we show them from zero they go from 0 to 16,383. 

(Decimal numbers are even as well! So are pairs, dozens...) 

When we take these even numbers of possible values and try to map them on to a Pitch Bend wheel, lever, etc. then there's a problem, because we now know that the total number of pitch bend values are always odd since there has to be a zero in the middle. The positive and negative values are symmetric and have the same range, but the need to have a zero position in the middle adds an extra number and we get an odd number of values. No matter how hard you try, if you have an even number of drawers and an odd number of things to put in those drawers, there will always be at least one empty drawer or thing left over (each drawer will hold only one thing, of course, in this scenario - which matches the way that numbers work very nicely!). 5 drawers and 4 things? One drawer will be empty. 4 drawers and 5 things? One thing will be left over, because all the drawers will be full. 

One possible solution is to have two zeroes! If you assign two of the values in the middle to zero, then you can have perfect matching! 

In the case of MIDI Pitch Bend, the design puts a single 'no pitch change' zero value at 8,192, full negative at 0, and full positive at 16,383. So the negative range has 8192 different values (0 to 8,192), and the positive range has 8,191 different values (8,192 to 16,383, which is 8,191). There is no value of 16,384 because that would require a 15-bit number, and we only have 14-bits. 


So the biggest negative pitch bend message value is -8,192, and the biggest positive pitch bend message is +8,191. The biggest possible positive pitch bend is always going to to be 1/8192th smaller than the biggest negative pitch bend message value. And it is a teeny, tiny value! Nothing to worry about. It is a minute pitch difference.

But it is an inconsistency!  

  







---


If you find my writing helpful, informative or entertaining, then please consider visiting this link:

Synthesizerwriter's Store (New 'Modular thinking' designs now available!)

Buy me a coffeeBuy me a coffee (Encourage me to write more posts like this one!)




 



Sunday, 7 March 2021

Emulating Turning a Circuit On and Off...

On the Discord channel of the Music Hackspace, @MeLlamanHokage asked about simulating power failure in a circuit using Max. I replied:

For audio circuitry then you would need to implement things like: a low-pass filter with a falling cut-off frequency, an increasing noise floor, rising (or falling) gain, falling clipping levels (eventually to zero volts), rising intermodulation distortion, a changing dc offset...

(Here's a sneak peak of what was in my head - scroll down for more details):


And so I idly wondered if it would be possible to do this in Max - actually MaxForLive, because I realised that this might be a perfect addition to the Synthesizerwriter M4L Tape (etc.) Suite. In much the same way as you record release 'tails' or 'triggers' on a piano, so that you capture the sound made when a key is released and returns to its 'resting' position, then I realised that an M4L emulation of a circuit turning off (and on again) could be used to add in the sound of Guitar Effects Pedals being switched in and out of circuit, or having their power removed. 

This was hugely reinforced when Christian Henson @chensonmusic (of Pianobook and Spitfire Audio fame) did a performance using just a piano sample loop and his pedal board with 23-ish pedals in a recent YouTube video (there are three Moog pedals off to the right of the screenshot, btw):

https://www.youtube.com/watch?v=yF6VKqpC-nA

Imagine @chensonmusic Christian Henson's head and arm hovering over a massed array of guitar pedal goodness...
Christian Henson @chensonmusic 'plays' his pedal-board...

That's two nudges in the same direction, so I stopped dithering, and started coding...

Now I know that the Effect/Bypass switches in guitar effect pedals are designed to not introduce any glitches or noise into the audio stream, and I know that they don't turn the power on and off to the pedal (well, not usually)! But not all of them will function perfectly, and power supplies do fail! I have had several synths, groove boxes and drum machines that made interesting sounds as you turned them off, and I would venture that this may be an obscure and under-utilised area of sampling. See the 'Reminder...' section near the end of this blog post for more thoughts on this...

Are the sounds made by foot-switches on guitar pedals part of a performance? That's an interesting question... So how can I make it easier for everyone to explore this aspect as well?

Free Samples...

Whilst there may be little actual sonic effect on audio signals from a modern foot-switch, there's also the very characteristic sound that guitar pedal foot-switches make in the real world: definitely something to sample and use as a drum sound. (I notice that the BBC overdubbed the sound of a gun being cocked to replace the sound of a seat belt clicking in a recent 'edgy' trail...) So I did some sampling of switches from a variety of sources*, and this turned into an editing session, and you can get the results here for free:


These samples were created by me, and are released into the public domain with a CC0 licence. There are the sounds of foot-switches, and lots more. 'Footswitch14' and 'Footswitch Toggle 14' are what I think of as the classic guitar pedal foot-switch sound, but you may have your own preference...

As always, let me know if you want more of this type of content.

*Sources: Eventide H9 Dark, EHX Oceans 12, EHX SuperEgo+, Poly Digit, Donner DT-1, MIDI Fighter Twister, Rebel Technology OWL, and some other obscure stuff...

ON Off Emulation

But back to the main topic! I hasten to say that my original reply wasn't based on having already seen something that emulated a circuit being turned on and off. Instead it was me quickly thinking about what happens when you remove power from a circuit. So now that Christian Henson had inspired me to  actually design something, I jotted down some more concrete ideas about what 'turning something on and off' actually meant, as well as what sorts of things would happen to the circuits.

The first thing I thought about was a state diagram. At first sight, this is obvious. There are only two states: On and Off. Duh! (And there's the trap, sprung...)

But, with a little more analytical thinking, it is slightly more complex than this. There are actually four states: Off, Turning On, On, and Turning Off. The 'Turning On' and 'Turning Off' states normally happen so quickly that we don't notice them, but the longer they are, the more you notice them. One example where I've done this type of thing before was in a few MaxForLive devices that I programmed where the volume can be set to rise or fall slowly. The 'generic' version is called '3rd Hand' because it almost gives you a third (and very steady) hand to control rising or falling volume...

http://blog.synthesizerwriter.com/2018/07/slow-fades-in-live-performance.html - 3rd Hand

What was really interesting was that when I included an automatic volume control in a device: https://maxforlive.com/library/device/5258/instsineatmosphere then the only feedback comment that I received was that it didn't make any sound, which was exactly what happened with an earlier 'Generator' device where you had to click on a button to get a sound, so since then I have not included this feature in many devices. Please let me know if you would like it to be included!

But back to 'states'...

This '4 states' approach is very useful for live performance where you want something to evolve slowly: like an audio drone that gradually evolves over minutes, or tens of minutes, or longer. If you've ever gone to a 'Drone' performance by William Basinski (there are other audio drone specialists) then you will know the power of a slow rising, changing sound. I saw/heard him when he performed at Ableton Loop 2017...there's something about live performance!

In a drone performance, then there's a lot of slow evolution of sounds, timbres, volume... (the 'Turning On' and 'Turning Off' states) and very little time when the soundscape is static ('the 'On' or 'Off' states). To revisit the old saying about music typically being made up of 'sound and silence', then a better recipe might be that music is effective when it contains interesting/evolving/changing sounds seasoned with  sprinkles of silence.

In this case, the change was all about what happens when circuits get turned on or off. And so I jotted down as my first proper approximations:

- Mains breakthrough from PSU

- Clicks, Crackle and Crunches

- Noise (Rising then falling?)

- Clipping of audio

- Loss of high frequencies in audio

And then I programmed a custom 'synthesizer' in MaxForLive, that used a 4-state slow On and Off generator to drive 5 sections producing each of the 5 features that I had noted. I'm sure there are more things happening, but this was a first attempt, and I'd never seen anything like this before... Now when I say 'I programmed' then that can make it sound like something trivial and rapid, but that isn't quite how the process works... Anyway, some hours later...

OnOff Emulation mr 0v01


There are five processing sections, plus a sixth 'control etc.' section on the right hand side. The layout is much the same as the Ironic Distortion and the Ferrous Modulation M4L devices:

Ironic Distortion - blog post.                   Ironic Distortion - M4L.com

Ferrous Modulation - blog post.              Ferrous Modulation - M4L.com

Each section has a 'Mix' slider, which sets the level of the output of that section, with a big 'Mute' button.


But because this device is all about controlling the 'Turning On' and 'Turning Off' states, then there are extra controls in each section which are devoted to setting how time affects each section. The big grey bar is the current On/Off stare: 100 (all of the bar is grey) is On, whilst 0 (all of the bar is black) is Off. The movement of the bar (up or down) shows how things change during the 'Turning On' or 'Turning Off' states. To the right of the bar are four rotary controls, plus an 8-button switch selector.  The screenshot above is for the I (Impulse) section, and so each starts with that letter. So I-On is the time for the bar to move from Off to On (the 'Turning On' time), whilst I-Off is the time for the bar to move from On to Off (the 'Turning Off' time). 

The 8 position switch in the middle controls how the bar moves. L is for Linear, and so the bar just moves steadily from top to bottom (a straight line graph). S is for Sine, so the bar slows down as it gets to On. Z is Sine-squared, so the slow-down is sharper. P is for Power, so the bar slows down as it gets to Off. Q is for Power-squared, so the slow-down is more abrupt. B is for Bipolar, so the bar slows down as it gets to On and Off. D is for Bipolar-squared, so the slow-down is more abrupt. Finally, the light purple S that is linked to the two rotary controls on the right is for 'Smooth' (or Log) and this provides two additional controls that let you change the time of a logarithmic slow-down as the bar gets near to  the On or the Off. 


The best thing to do is to listen to the effect that the controls have! It is a bit like the Flutter waveforms in Ferrous Modulation: sine sounds boring, whilst the narrow spikes sound jerky... You may find that the Smooth setting gives good control, but remember that the S, Z, P and B positions don't have the slow-down at one extreme, and so have a very different effect. If you find yourself over-using the Smooth setting, then deliberately choose one of the more abrupt options. 

Separate controls are provided for each sections because the final sound works best when each of the sections has different timing! If you have the same timing for all of the sections than it will sound boring... One of the settings that I like is to have the Clip section happen last, so that you last thing you hear is the distorted audio...

The Sections

From the left hand side, the sections are in two parts. The first two sections process the incoming audio signal: 

Freq. 

This section just applies a low-pass filter to the audio input, and lowers the cut-off frequency as the bar moves from On to Off.  (Or raises it as the bar moves from Off to On). This emulates that way that some audio circuitry loses high frequencies as the power supply is reduced.

Clip.

This section has optional Compression and Filtering, but the main effect is to apply clipping to the audio input, where the clip limits reduce with the bar, so there is no Clipping when the device state is On, but more and more clipping as the state approaches Off. Note that the volume drops to zero when the state is Off... so you don't hear the effect of extreme clipping when the limits are zero! 

The next three sections are generators, and so do not process the incoming audio:

Noise

White noise filtered to give it various colours. The 'Gain' control and the mixer slider are effectively the same control...

Impulse

Crackles, pops, crunches, and other 'Impulse'-type sounds are generated in this section. Because the source is random noise, then these will not repeat - every time a new and different sound will be produced. 

Mains

This is slightly strange - it introduces the sound of mains hum, which is weird if the power supply has been removed. But, curiously, as with many sound effects, nonsensical often seems to work. It seems that having mains hum fade in and out implies something happening with the power - a bit like the way that sparks always seem to jump out of control panels on spaceships and submarines in the movies whenever there's an explosion or a collision. 

None of these sections is particularly complicated. Each does just one generation or processing function. Feel free to look into the code to see how each works - there's no magic used. 

The Big Button

One the far right hand side is the Control section. This has the big 'On/Off' button, text that shows the current state (1 of 4 possible states), and a generous set of memories for your own creations - just shift-click to store, click to recall. 

Reminder...

It is probably worth noting that although this might appear to be just a generator of On/Off sounds, it is also a processor - the Freq and Clip sections process audio, so if you don't input anything then they won't produce any output. The ideal setup is to have a sound that you want as the basis of the final result, and then use OnOff Emulation as a way of 'bracketing' it with an On and Off emulation.

This is slightly different to what the Release Trigger or Release Tail samples are doing in a piano sample - they deliberately do not include the piano note itself. (You press down on a key, and then release it, so you get the sound made by the key itself and the associated 'action' mechanics, but you don't do this with a string vibrating. ) OnOff Emulation processes any audio that is sent to it, and then layers the mains, impulse and noise sections on top of it. 

And this set me thinking... What about a release trigger/tail generator? I've never seen a dedicated one, because all of the release triggers/tails that I've ever used have been just samples that are part of the sample set of a sampled piano... The only exception that I can think of is for Harpsichord-type sounds on a DX7 (or other FM synths,  etc.), where the sound of the jack hitting the string when the note is released, is synthesized separately using an envelope where the attack and decay are short, the sustain level is zero, and the release rises to the final/initial level to give an envelope that only affects the release segment of the note. Oh, and acoustic guitar sounds, where string buzz is also synthesized this way... There's probably more now that I'm thinking about it this topic...

So a release trigger/tail generator would have different sections, and actually might have some aspects in common with a 'Riser' synthesizer, although they don't seem to be as 'in vogue' as they were a few years ago. I remember suggesting that a custom riser could be made by processing a 'reverb'ed section of a track in an Ableton Loop Studio Session back in 2015, and got a tumbleweed reaction from the room, and the 'Name' Producer then made one using filtered noise and everyone else nodded their heads. I have always swum against the tide, by the way...

I have added this task to my 'ever-expanding' (as Loopop says on YouTube) list of 'things to do'.  Don't hold your breath, though: it's a long list and I'm very busy. 

And Finally...

I haven't really seen a device like this before. Well, actually, that's not exactly right, because I have - this is just a synthesizer, but not your common variety. This is a purpose-built 'custom' synthesizer made to produce just one type of sound.  What I haven't seen before is a synthesizer that is dedicated to making the sound of a circuit being turned on or off. But now I have. And so do you, now! I think it shows the power of Max that you can use it to make arbitrary sounds and sounds that haven't been made before (or maybe sounds that I think might not have been made before...).

My grateful thanks to @MeLlamanHokage for the original question about turning circuits on and off, and to Christian Henson for using a pedal board as a performance instrument at exactly the right moment to get me to turn speculation into reality. Thank you, sirs!

---

Getting ONOff Emulation

You can get OnOff Emulation here:

    https://maxforlive.com/library/device/7074/onoff-emulation

And yes, I realise that it should be called AUDonOFFemulation if I was to use my own naming scheme, but that just reads crazy!

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

(In Live 10, you can also just double-click on the .amxd file, but this puts the device in the same folder as all of the factory devices...)

Oh, yes, and sometimes last-minute fixes do get added, which is why sometimes a blog post is behind the version number of MaxForLive.com...

And no, I haven't had a chance to test it in Live 11 yet... To much to do, so little time...

Modular Equivalents

In terms of basic modular equivalents, then implementing OnOff Emulation is a mixer plus a VCF plus a Clipper plus a noise source, an envelope follower and a State-Variable Filter, plus a trigger and 10 AR envelopes. Nothing is complex, but there's quite a lot of separate bits to deal with, which can be tricky on a modular... 

Overall, I reckon that OnOff Emulation would require an ME of about 20. Alternatively, you could just take any modular patch and see what happens when you power it down and up. (Caution: Turn your amplifier volume down, and use a limiter on the input. Increase the volume slowly and carefully - with caution. Not recommended with headphones! Do not turn modulars on and off repeatedly and quickly!) 

---

If you find my writing helpful, informative or entertaining, then please consider visiting this link:

Buy me a coffeeBuy me a coffee (Encourage me to write more posts like this one!)


Synthesizerwriter's Store
 (New 'Modular thinking' designs now available!)

 



 













Tuesday, 19 January 2021

Music Hackspace 'Max meetup Europe #1' event report...

Just occasionally (Spitfire Audio please note), I get invited to music business events, so I was very pleased when the Music Hackspace (Based in Somerset House, London, although in these Covid-19 times, maybe 'Online' is a better location!) informed me about an interesting event in the middle of January... (I'm a MH 'mailing list' subscriber, and thoroughly recommend the Music Hackspace if you are into music technology...)


So 3pm GMT on Saturday, the 16th of January 2021, found me videoconferencing on Zoom.us, taking part in the first 'Max meetup Europe Edition'. Max is the commercial 'visual programming' language for multimedia published by Cycling '74 (Miller Puckette, one of the original authors of Max at IRCAM in France, has also released an open source branch called PureData

After the usual welcomes and intros, there were two short presentations on projects using Max: 

One (above) from Phelan Kane on using Weather metadata in a MaxForLive device to control music generation in Ableton Live (I loved the use of the 'dict.view' dict viewer object to give the hierarchical list), and another (below) from JB on exploring dual sampling and pitch manipulation using two instances of the 'groove~' object. Now I have to declare here that I'm a great fan of the groove~ object, and I have been working on a sample processing device using it for far too long, but that's another story. Here's a tease partial screen-shot showing one of the two groove~ objects...

My main 'go to' object at the moment is the live.grid object, but not with the chucker~ object that it is supposed to be used for. Instead I mis-use it to provide a neat user interface to some probability functions. And that is another story as well...

Breakout

After this, attendees distributed themselves into breakout rooms (including chill rooms for those who didn't want to go too nerdy). I joined the MaxForLive breakout room because I've been doing more M4L than Max for quite a while. Now maybe I should do more Max, but TAS, as I've been saying too much...

The conversation started around MIDI Controllers. There's something about people who program Max For Live - they often seem to have a keen interest in MIDI Controllers, interfacing them, emulating them, reimagining them in M4L inside Live, etc. As usual with any discussion of MIDI Controllers, the topic of 'Custom' came up. I'm not immune to this, I have a half-built custom MIDI Controller made using the Makey Makey device, and I backed the Kickstarter Ototo project with the aim of turning it into a custom MIDI Controller. But DIY hardware is tricky (although I do like the occasional mod here and there...) and so the latest incarnation, the Yaeltex.com 'we built your custom MIDI Controller for you, was shared and there was lots of 'oohing' as everyone imagined something custom... This set us along a thread of 'MIDI Controllers' you may not have heard about, and it turns out that Yaeltex do some predefined controllers as well (like the 'MiniBlock2' shown here).


So that all of the discussion wasn't lost, I took some notes, and produced a database of most of the things mentioned, plus some others. You can view it either via the Music Hackspace Discord channel (max-meetups) or here: https://airtable.com/shrAClKa1B9X4w3ZC 

MIDI Controller database

Mapping

Things then got a little bit philosophical as the discussion went into programming, particularly going 'deeper' than Max or MaxForLive. We talked about Gen, which took us to JUCE, and then to SOUL, then via Bela, and ended up with C++ or even DSP assembler. I think Axoloti was mentioned too, but no-one dropped in Faust. It struck me that this whole topic needed some sort of map, so I produced one:


I have deliberately avoided trying to position VSTs (or AUs, or...) or Faust on this mind-map, but it's a personal view of what part of the 'Audio Dev' landscape kind of looks like. I'm sure it isn't perfect, but it gives some positioning of technologies on that spectrum between 'Easy and fast to code, but middling performance' to 'Difficult and slow to code, but amazing performance'. It's a long time since I did Motorola 56000 DSP coding, and recently I've not gone any lower than Gen. I suspect that talking about this topic is going to be a regular feature of the Music Hackspace Max meetups - did I mention that they are monthly for Europe, and for the USA too, so that's fortnightly if you register for both. 

Oh, and they are free! 

All you need is your time and Zoom (not the music electronics company from Japan, but Zoom.us, the videoconferencing services provider...)

I have to say that I thoroughly enjoyed talking to other people about Max, and the conversation strayed well away from it as well, so it was more like a gathering of 'people who make music', and I'm always up for that. 

Here's a link to the Music Hackspace 'Upcoming Events' page, so that you can register for future events... 

I would like to thank the Music Hackspace for a fascinating and useful couple of hours spent in Max-land. I may well do it again!

Links

Music Hackspace - The hosts of the Max meetup...
Cycling '74 - Max and more...
PureData - A very interesting alternative end-point to IRCAM research by Miller Puckette et al...
Phelan Kane - More about, and more from...
Yaeltex.com - Pre-built and custom built MIDI Controllers
Makey Makey - DIY MIDI Controller enabler - just add physical hardware...
MIDI Controllers Database - Some of the available MIDI Controllers (let me know about others!)
Gen - is one layer underneath Max...
JUCE - do just about anything audio on a computer...
SOUL - even deeper down the rabbit hole...
Bela - C++, PureData, SuperCollider...
Faust - an alternative to C++?
Music Hackspace 'Upcoming Events' page - Future Max meetup Europe Edition & USA Edition events, and more...

  ---

If you find my writing helpful, informative or entertaining, then please consider visiting this link:

Buy me a coffeeBuy me a coffee (Encourage me to write more posts like this one!)


Synthesizerwriter's Store
 (New 'Modular thinking' designs now available!)





   


Monday, 31 August 2020

Decoding a 'ParamName Value' control string in MaxForLive...

Over time, Max and its 'Ableton Live' cousin, MaxForLive, have iteratively added functionality to do music, MIDI and audio-related tasks. 

Me, I'm not so good with new functions. I tend to use the same Max objects over and over again, because I know them, I'm familiar with how they work, and so I use them. 

The problem is, sometimes this means that I struggle to solve problems when there's a perfect solution just waiting, not hidden but overlooked, already in Max. This happened recently when I wanted to decode a 'ParamName Value' control string, and string processing is not one of Max's greatest strengths. I have used quite a few of the 'zl.' list processing functions, but there are a lot that I've never used as well. Searching through the 'zl.' help pages, I found 'zl.sub', where the example shown isn't very exciting:


Okay, so for the first number, '1', then it will output the number '1' indicating the first position in the list. And 2 for the second item, and so on. But then I realised that the numbers were distracting me, this is a list processor, and so it could be any 'symbol': numbers or text. It suddenly dawned on me (Duh!) that the 'sub' in the name meant 'Sub-set', and it all became clear. All of those convoluted 'If' objects that I had struggled with previously to process text strings were instantly rendered obsolete. 

Yep, a face-palm moment.

So here's an example that should make it much clearer what you can do with zl.sub in a more musical  'MaxForLive' type of context:


At the start is a control string: a parameter name, followed by the value of that parameter. The sort of string that is human-friendly... The 'fromsymbol' object turns it into a list containing a string symbol ('Cutoff') and an integer ('100'). This is then split into two separate fragments by the 'unpack' object. The symbol goes into zl.sub, which reports back that 'Cutoff' is the 5th item in the list, and the integer is the value of that parameter. 

Human-readable input becomes programming-friendly name and value pair. It's not a click-bait headline, but it makes quite a few of my abandoned projects much more possible now. 

So that's a face-palm turned into a light-bulb moment. Not bad for a Max command I'd always overlooked. My Day: Made. Happy face.

(Yep, one of the shortest blog posts so far, I think...)

---

If you find my writing helpful, informative or entertaining, then please consider visiting this link:


Synthesizerwriter's StoreSynthesizerwriter's Store
 (New 'Modular thinking' designs now available!)



  


Monday, 15 April 2019

Spectral auto-panning in MaxForLive for Ableton Live

My two recent MaxForLive audio devices have both been based around having 6 processing sections - hence the 'hex' in their names. But I realised that there was a much simpler device that uses the hex pan section, which could be used in many ways, and this blog post is devoted to it: a hex spatializer!

AUDhexSPATIAL 


AUDhexSPATIAL moves parts of sounds around in the stereo field. That's all. It is quite straightforward, but don't let that fool you into thinking that you can't do much with it.

The input audio is passed through three parallel filters, and then the outputs are auto-panned across the stereo image. The three filters can be used in several ways, but the most obvious way is to use them to split the audio into three separate bands: The high-pass filter outputs the high frequencies, the low-pass filter outputs the low frequencies, and the band-pass filter outputs the middle frequencies.

Each filter output can be panned to hard left or hard right, or can be Auto-panned - controlled by a three position switch: L/Auto/R. But the frequencies of each filter are independent, so there's nothing to stop you putting the high-pass filter below the low-pass, or the band-pass anywhere from low to high.

The filters are there just to provide different blocks of frequencies to the output section where the panning happens. And the three [X] toggle switches allow you to turn the outputs on and off, so if you want to have just the high-pass filter output, then just enable that toggle switch and turn off the others. The two stereo channels are separate, so if you want different filters and pans for left and right, then that is completely possible.

Naming

After a lot of agonising, I have finally decided to use a new and consistent naming scheme for my M4L plug-ins. From now onwards, and if I update anything, then I will strive to use three prefixes:

- AUD for Audio processing devices (aka effects)
- MIDI for MIDI devices (this took ages to figure out!)
- GEN for devices that generate audio

Of course, in an imperfect world, I may not always succeed in trying to be consistent, but I will try. Please let me know if I falter!

Applications

OK, so your imagination is probably your main limitation here. If you want to have the left channel quickly auto-panning the top end of a piano sound, whilst the right channel slowly pans the bass around and both channels have two different resonant filters panning at different speeds, then that's fine.

But there's more. Try putting AUDhexSPATIAL in front of a Ping-Pong Echo, or put it in between two Ping-Pong Echoes... It is very interesting to experience just how complex a simple sequence can sound when it goes through this sort of processing.

Limitations

You can't adjust the panning width directly - adding two extra rotary controls would make the centre section way too big, I reckon. (But let me know if you really want this, and I might schedule a '+' version...) You get full left-to-right panning, or else hard left or hard right. Of course, you could make a rack and use the Utility object to restrict the pan width of multiple AUDhexSPATIALs...

There are only 3 filters and three panners per channel. Making a version with more channels is not in my current plans, and my main concern would be trying to find a way to fit everything into the user interface...

Oh, and the filters are not animated - they are fixed graphics! Sorry...

MaxForLive

Recent blog posts have included details of what is happening inside my M4L devices, and this is no exception. This time, I'm going to look at the three-position switch that has been added to the output section.

Max and MaxForLive have a lot of ways of routing numbers, messages and signals around. There are lots of objects, with names like Gate, Switch, Route, Selector, Matrix, and more. Sometimes the objects that route signals around have different names, and work slightly differently to the objects that route numbers or messages, and they can work slightly differently. It's quite a lot to get your head around, and one of these days, I'm going to try to do a guide (a bit like the one I did on squeezing controls into limited spaces!). But in the meantime, here's the first of a little mini-series where I look at a few interesting ways to route stuff.

The three-position switch does two things simultaneously: it allows you to select between hard left and hard right pan positions, or it selects the auto-pan. These are very different things, although if you look at AUDhexECHO or AUDhexFrequencyShifter then you will see that by slowing the LFO to 'stopped' then the result is fixed pan positions. But that isn't a very practical approach for a three position switch. There is also the complication that the output of the LFO that does the auto-panning is a signal (so it has the yellow-striped connections in Max), whilst the more usual way to control a panner is with numbers, so there's going to be a conversion somewhere.

First off, let's look at the context. Here's the relevant part of the Max code for the audio output of  AUDhexSPATIAL:


And here's the 'pan_mr' object expanded out (this is a cheat to make things clear - in reality, you don't see the controls that are connected to the input ports, but I have removed the ports and added the rotary control and the 3-position switch control to make it obvious how things are connected):


The main audio processing is on the left hand side. Input port 1 (the square box with '1' in it) is the audio signal that is going to be 'panned'. It goes to two signal multipliers (notice the '~' after the '*') that are driven in anti-phase using the '!- 1.' inverter shorthand that I've mentioned before. (The formula inside the object just subtracts whatever you feed into the object from 1, so it really means '1-the_number', and so it inverts the value, so if you put 0 in then you get 1 out, and if you put 1 in, then you get 0 out, and linearly for all other values...). The pan value goes from 0 to 1 to pan from left to right, and so centre is a value of 0.5.

On the far right hand side, you can see how the left and right values re stored in message boxes that are triggered every time that the switch is changed. The 'LED" object with the round circle is a useful way to convert changes into 'bangs' that also shows you what is happening when you are debugging. The '0' and '1' messages that the message boxes output when they receive a bang are converted into signals using the 'sig~' objects.    

In the middle, starting from the rotary control, there is a 'cycle~' object that does the sine-wave LFO function, followed by a bit of maths to get the output into the 0<->1 range that is required by the multipliers that do the panning. The 'scaled and offset' sine-wave is then connected to the middle input of a 'selector~' object, which is a special switch for routing signals. The other two inputs are from the signals from the message boxes. So the selector switch can output:
- a signal representing 'left'
- a signal that is an LFO sine-wave
- a signal representing 'right'


And that's how you can make a three-position switch that has fixed values on two of the settings, and an LFO signal on the other.

Getting AUDhexSPATIAL

You can download AUDhexSPATIAL 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

(In Live 10, you can also just double-click on the .amxd file, but this puts the device in the same folder as all of the factory devices...)

Oh, yes, and sometimes last-minute fixes do get added, which is why sometimes the blog post is behind the version number of MaxForLive.com...

Modular Equivalents

In terms of basic modular equivalents, then AUDhexSPATIAL requires six filters, six LFOs, six VCAs, and a mixer, plus some switching for the fixed pan positions, giving a total of about 20 ME.


Sunday, 17 February 2019

Interviewed by Darwin Grosse of Cycling '74

Back in January, I mentioned that sometimes the music industry caught up with me, and I'm pleased to say that it has happened again! As a result of asking about gen~ in Live 10 for a blog article, I exchanged emails with Darwin Grosse, who is the Director of Education and Customer Services at Cycling '74, and he asked me if I would be interested in being interviewed for the 'Art + Music + Technology' podcast page.

And I said 'Yes, of course!'

So if you ever wanted to hear what I sound like, and learn a bit more about my background...


(I'm interview number 264, so Darwin has been very busy! It is well worth scrolling down to see some of the other people that he has interviewed...)

I would like to thank Darwin, Cory and all at Cycling '74 for all of their help over quite a few years. Their support has been consistently wonderful! I just wish that I had more time to develop more  MaxForLive devices - unfortunately I have a lot of other projects that also keep me busy...

Darwin Grosse's web-page contains a lot of useful and interesting links.








Tuesday, 18 December 2018

Modulated Sine Waves Two Ways - a Recipe in Two Parts (Part 1)

I was one of the helpers at the recent Rebel Technology 'Gen' Workshop in association with the Music Hackspace at Somerset House in London, and I got inspired by the way that many of the attendees went beyond the basics and took a basic oscillator and modulated it with another, and modulated that, and...

So I thought that I should try to make a multi-oscillator generic version of this 'modulated oscillator' genre, and at the time I was using Max 7.3.5 and the Live-bundled Max 8.0.0 - the significance of this will become apparent later... As my previous 'BankOSC' device (and quite a few others, on various platforms!) reveal, I have a weakness for sound generators that make atmospheric drones, hums, buzzes and other background 'subliminal' noises - the sort of thing that makes the bridge of the star-ship Enterprise immediately recognisable (or the transporter noise, or the sounds or planets, or... Hmmm, time to activate the 'Star Trek' filter.)

Which begs the question, what is the underlying 'genotype' of modulated oscillators? Considering what I saw at the workshop, plus more years than I care to think about of experience, I eventually decided that it was something to do with themes like: detune, tremolo/'ring modulation' (AM) and vibrato/'frequency modulation' (FM). Now as with slash fiction (don't look it up if you don't know about it), it is the juxtaposition that matters, and here it is the broad range that tremolo (usually interpreted as meaning low frequency (10 Hz or less) amplitude modulation) and ring modulation (usually interpreted as audio frequency (20 Hz to 20 kHz) amplitude modulation) imply that is the key, and this applies to FM as well. So wide range was essential, which mean using 'exponential' scalings to keep a huge range manageable with a single rotary control.


This is a very broad specification, so I cut it down to something simpler for my first attempt, mainly because there are limits to what you can do on platforms that use gen, like the Rebel Technology devices (OWL Pedal, OWL Modular, Alchemist, Wizard...) Now, I've always preferred FM to AM because it seems to provide a broader range of timbres, and so I went for FM, leaving AM for another day. I also restricted the waveforms to sine wave, because one of the major constraints is the number of controls. (4 rotary controls, one expression pedal input and one switch on the OWL pedal, for example) I also like auto-pan, and so I subverted the AM into simple panning just to give movement to the output. Here's the gen code and the block diagram for what I made as my underlying oscillator module:

So 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 '+' add object to do the modulation. This gives 'linear' 'vibrato-style' FM and so I chose a suitable frequency range of 0.01 to 2.5 Hz (look in the Param C 'scale' object) - if you replace the add with a '*' 'multiply' object (and tweak the scaling multiply and set the LFO to run at audio frequencies) then you get the 'multiply' FM (frequency modulation) variant. 'Linear/vibrato' gives a milder sound, whilst 'Multiply/FM' is much brighter in timbre.


 Here's where the oscillator module fits into the main gen code. At the top there are interfaces to the rotary controls etc., followed by slide objects to smooth any bad connections in the potentiometers, and then scale objects to turn the 0 to 1 range into useful ranges for the oscillator module. The 'Spreader' gen object is my attempt to turn those single values into a range of values - there's no point sending the same control values to all of the oscillator modules, because they will then all make the same sound. So what the spreader does is turn one incoming value into several different output values, and the range of those output values is set by the 'Spread' variable.

When I wrote the spreader object, then I was using Max 7.3.5 and the bundled Max 8.0.0 that comes with Live 10. I didn't have Max 8.0.2, and so I hadn't seen the 'spread' object that is included! However, that spread object 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.

Having to work exclusively in gen also has other consequences. One type of object that is often used in Max projects is the toggle - either the 'box with a cross', or a text box that can be used to set values to on or off. In Max this is fine, but in gen there's no such object, and what you usually get is just a push-button that goes from 0 to 1 when you press it, and from 1 to 0 when you release it. So the button has a 'momentary' action, and you can use it as a toggle that stays in one of two states, and when you press the button is goes to the other state. In order to implement this, then you need to store information about the current state in an object, and then to change that state when the button is pressed. Because this isn't needed in Max (there are already objects that provide 'toggle' outputs), then there aren't any ready-made objects in gen that solve this. So what is needed is something that turns pushes on a switch into toggling between two values.

Toggling

This sort of functionality is called sequential logic, and one of the standard ways to store a specific state is to have some feedback around a logic gate. Here's an example:


Now you don't need to know that these are NOR gates, or have any specific knowledge of how sequential logic works, because how this works is really straight-forward if you just follow what happens when we change the value of the 'Set' input from 0 (zero: false) to 1 (true). Those two gate symbols do only one thing: if either of the inputs is true, the output goes false. You can think of each NOR gate as being a bit like a person who is watching a room via closed circuit television. If they have been told to say when the room is empty, then as soon as one or more people enter the room, the room is no longer empty. So when the Set goes to 1 (true), then the output of the first gate will go to 0 (false). But this output is connected to another NOR gate, and so because Reset is also 0 (false), then this gate will output 1 (true: the room is empty!), and so the value of 'Output' will be true (1). But that true (1) value is fed back into the input of the first gate, and so that input will be 1 (true). So now there is someone in the room, which means that it isn't empty. And no matter what value 'Set' has, there's still someone in the room, and so it stays false (0), which means that the 'Output' stays at 1 (true). In order to change things, then we need to change the 'Reset' input from 0 to 1 (false to true), and then the second gate will no longer have two false at its inputs, and so will go false (the room is no longer empty!). Once the 'Output' goes false, then this goes back via the feedback to the input of the first gate, and so that now has two false, and so the output stays at true (1) (the room IS empty).

In other words, if Set goes from 0 to 1, then the value of Output goes to 1 and stays there, and after that, Set can return back to 0 because that won't affect the Output. The only way to affect the Output is to have the Reset go from 0 to 1, because that will then force the circuit to change the Output to 0 and stay there. 

So, remarkably, this simple pair of gates acts like a memory that can be set and reset. Setting and resetting a value sounds like what a toggle switch does - it sets something, then resets it, and so the state changes every time that we do a set or reset.

So to implement a toggle switch, all we need is a bit of feedback, and some way of using just one 'Set' input to do the setting and resetting, instead of two separate inputs. In gen, here's an example piece of code that does exactly that:


The input is from the push button, and goes from 0 to 1 when it is pressed, and then back to 0 again when it is released. This is turned into a quick pulse by an edge detector circuit, which is used to trigger a latch that holds the value. But we need to have the toggle action, and so we can't just put the input value in, we need to alternate between the input and its inverse. So the output of the store is delayed by the 'Previous' time delay box (1 sample delay), which then selects the inverse of the input, then the input, and so the value that is latched changes back and forth between 1 and 0 for each press of the push button. So this gen code provides exactly the 'toggle' action that is needed. 



Looking again at the main gen code, the toggle code is inside the 'gen @title toggle' object, and when the push-button is pressed, the output of the toggle object output goes to 1 and stays there, then when the push-button is pressed again, the toggle object output goes back to 0 and stays there, and so on.


The output of the toggle is multiplied by 0.4, and this is then smoothed into an envelope by the 'slide' object, which then controls the fade in and out of the volume at the outputs. 


At the very top level for the project, you can see the test controls that emulate the controls in the Rebel Technology devices: in this case an OWL pedal with four rotary controls, and Expression Pedal and a Push-button. All of the gen code from earlier is inside the gen~ object. You can also see the extra Max objects that I used whilst debugging the gen code during development - gen doesn't allow the same sort of monitoring of value directly, and so you need to use extra out<n> ports to send values up to this project level where they can be displayed. 

Upload and Download


The final result was compiled into C++ by the gen compiler inside Max, and the result uploaded to the Patches area on the Rebel technology web-site, from where it can be downloaded and put into any of the compatible devices. You may notice that there are two different versions: one for the 'Linear/Vibrato' and one for the 'Multiply/FM' versions of FM. To keep things simple, I have named these based on how they sound, not strictly according to how they work (they are both really FM!). Why two different versions? Well, there wasn't an easy way of switching between the two variations of FM because I had already used the push-button to fade the volume up and down. Of course, there's nothing to stop you altering the code to suit your own purposes...

In Part 2 (coming soon), I will take the gen code developed here, and make it into the core of a MaxForLive device...

Thanks

Thanks to everyone at Rebel Technology and the Somerset House Music Hackspace for a wonderful day!