nmMelodyMagic
A tribute to Ken Stone’s Infinite Melody and Modulo Magic 4U CGS Serge modules, which are unique and fun control signal generators and processors.
You can find expandable development diary entries at the bottom of this post.
More Screenshots
Requirements
- Norns
- PolyPerc
- MIDI output (optional, but highly recommended)
- MIDI input (optional)
- Crow CV in & out (optional)
- Grid or 8x8 midigrid device (optional)
Documentation
nmMelodyMagic is a MIDI note and CC sequencer, synced to Norn’s clock. Connect it to your favorite synth and generate infinite melodies! A very basic PolyPerc audio engine sound is available as well for easier testing and learning. Connect Crow to interface the script with your analog/modular synths. Connect a Grid to poke your fingers into the virtual circuits and interfere with bits directly.
My guides for the original 4U CGS Serge modules on GitHub are a very good starting point and hopefully also an interesting read:
Below you will find guides specific to the nmMelodyMagic script.
Controls:
K1: Hold for in-script manual
K2: Clock pulse
K3: Advance pulse
K1+K2: MIDI Panic (all notes off)
K1+K3: Save state (auto-loaded on startup)
E1: Switch page
E2: Select parameter
E3: Change parameter
Check out the EDIT menu “MIDI output settings”, where you can assign each of the script’s output values an individual MIDI channel and select between note or CC generation!
Quickstart Guide
Open Quickstart Guide
Go to the EDIT menu, scroll down and choose your MIDI output device.
Scroll down further, go into MIDI Output Settings and set “DAC1 Proc. Out” to Note and choose a MIDI channel for your connected synth (Default: 1).
Now go out of the menu, back to the Infinite Melody screen, which you saw on startup. The default values will let you experiment manually with nmMelodyMagic, before diving into clock-synced chaos.
On the Infinite Melody page, press K2 and K3 to watch the shift registers fill up and see what happens to the output values at the bottom. The (processed) D1 number is the note that will be sent to your synth. Later then, change Clock and Adv. to positive (faster) or negative (slower) values to automate melody generation, synced to Norns’ clock.
On the Diatonic Converter page, turn E2 and watch the shift register fill and generate octaves and notes. Later, change the Input to something other than Manual to automate note generation. You may go back to the MIDI output settings and assign note or CC output and a MIDI channel to “Dia Out” to sequence an external synth.
On the Modulo Magic page, turn E2 and watch the input bar on the left rise to Initiation threshold markers and see what happens to the output bar. Again, choose an Input other than Manual to process another signal from the script. You may go back to the MIDI output settings and assign a channel to “Modulo Out” to sequence an external synth.
Illustrated In-Depth Guide
Open Illustrated In-Depth Guide
Please have the script running with the default settings loaded, by selecting “Load Default Settings” in the EDIT menu and pressing K3.
Binary Basics
It’s useful to know at least a tiny little bit about counting in binary for this script, so here’s a short introduction.
- Start at (1.), where you see the 6 bits 111111, representing the number 63 in binary.
- Above each 1 is a number 1, 2, 4, 8, 16 and 32.
- Those numbers each correspond to one of the 6 bits, from right to left.
- If a bit is 1, then the value above it is added to the total sum.
- So in this example 1+2+4+8+16+32 equals 63, the maximum number we can count up to with 6 bits.
- Thus 6 bits encompass numbers from 0 to 63, a total of 64 numbers.
- Look at the other examples and understand how the results are calculated simply by summing each 1’s corresponding number.
- Try to solve ?, ?? and ??? on your own.
Infinite Melody
Let’s dive right in!
1. Noise
- At the beginning we have a Noise input, which is either fed by an internal random generator or a manual value, which can be mapped to an incoming MIDI CC# for example.
2. Sense
- The Sense parameter sets a comparator threshold.
- Is the noise/manual value above Sense, a 1 is generated and a little square is shown next to Sense.
- Is the noise/manual value equal or lower, a 0 is generated.
3. Clock
- On each Clock pulse, the number generated by Sense (0 or 1) is fed into the input digital shift register “DSRIn”.
- If that happens, all other values in the register shift one cell to the left, with the last value being discarded.
- You can see this happening by pressing K2, which triggers a Clock pulse manually.
4. DSR In
- DSRIn is used to store the semi-randomly generated 0s and 1s from the Sense comparator.
- It’s a binary random generator.
- So clocking DSRIn does not generate any output (usually).
5. Advance
- On each Advance pulse, bits from DSRIn’s cells are pushed down into another grid of shift registers.
- Random mode will push all six bits from DSRIn down at once.
- 1/f mode will push the 1st (right-most) bit down on every pulse, the 2nd on every second pulse, the 3rd on every fourth pulse, etc.
- You can see this happening by pressing K3, which triggers an Advance pulse manually
- This is an animation from my original CGS Serge module guide:
6. More bits!
- There are 4 rows of bits, each leading to an output.
7. DAC Outputs
- The digital-to-analog-converter DAC1 converts the first row of bits into a number between 0 and 63.
- DAC2 converts the second row.
- DAC 3 converts the third row.
- All of the DAC numbers are scaled to the MIDI value range of 0 to 127.
8. Mix Output
- Each of the fourth row’s bits are sent through their own “attenuator” m1-6.
- If an attenuator receives a 1, a little square is shown next to it.
- All attenuators receiving a 1 have their values added together at the Mix output.
- Like this you can set up precise number combinations in a range of 0 to 127.
- For example by setting m1 to 12, it will transpose the Mix output up one octave, whenever m1 receives a 1 bit.
Again, try it out with the default values, to manually send Clock and Advance pulses. You can also set the Noise Generator to external and manually choose the Sense input!
Diatonic Converter
The Diatonic Converter receives a 6 bit binary input and converts it to a diatonic scale note number.
1. Input Bits
- The 6 input bits are split in the middle into two 3 bit binary numbers.
- 3 bits let you count from 0 to 7 in binary, so 8 numbers in total.
2. Note and Octave
- Bits 1-3 are representing one of 8 note numbers.
- Bits 4-6 are representing one of 8 octave numbers.
3. Scale
- The note numbers each correspond to a certain note in a diatonic major or minor scale
- Major: C D E F G A B C
- Minor: C D Eb E F G Ab Bb C
4. Offset and Scaling
- Note number and Octave number are combined to form a proper MIDI note number.
- The Root value is added to the MIDI note number, acting like a simple offset.
- The result is multiplied by the Scaling value, which will shift the notes away from their previously rigid diatonic scales.
5. Bits 5 and 6
- Input bits 5 and 6 are responsible for the largest note changes.
- If Bit 5 equals 1, then this adds 2 octaves to the note output.
- If Bit 6 equals 1, then this adds 4 octaves to the note output.
- To constrain the notes and to avoid big pitch jumps, you may disable bits 5 and 6.
- Did you understand all of this?
- If so, think back to the Infinite Melodies’ 1/f mode and about why it might be especially important to disable bits 5 and 6 when using that mode.
- If not, let me know in the thread below
Modulo Magic
The Modulo Magic is a separate CGS Serge CV processor module, which sits next to the Infinite Melody on the “Best of CGS MARSH” panel. Read on below to understand why this might be the case
1. Parameters
- The left rising white line is the input signal.
- The right rising jagged white line is the output signal.
- Once the input signal reaches the Initiation threshold, it triggers a Step.
- A Step will add or subtract the Step Size value from the input signal.
- The illustration shows a negative Step Size value.
- Step Size can be modulated with the Add and Subtract parameters.
- This whole process can happen up to 8 times in a row, as defined by the Steps value.
- Offset shifts the Initiation thresholds upwards, delaying the first Step trigger.
2. Modulus Operation
- If the Initiation threshold value equals Step Size * -1, then the module will constrain the input signal to the initiation value range.
- Example: Set Initiation to 12 and Step Size to -12. The output will now stay inside a one octave range!
- This way you can precisely constrain the wide ranging Infinite Melody outputs to a more musical note range.
Output Processors
Also on the “Best of CGS MARSH” panel, we find two CV Processors, which I wanted to include in this script due to their versatility.
- Each script output has one Processor assigned to it.
- The output value is multiplied by the bipolar attenuator, with a range of -1 to +1, allowing for signal attenuation and inversion.
- The result is then added to the Offset value, letting you shift the output upwards.
- Each Processor has its own script output, indicated by “-p” after the original output’s name.
- Like this you could use the Mix output to play a certain range of notes, while having the Mix-p output play the same notes offset by 12 semitones, i.e. one octave.
Note On/Off Triggers
- For MIDI notes we don’t just need a pitch signal, but also a gate signal.
- A gate generator was not part of the original CGS Serge modules though, so I came up with one in their spirit.
- For each output you may choose a note on and off bit.
- Whenever the on bit is 1, a note on/gate high event is sent for that output.
- Whenever the off bit is 1, a note off/gate low event is sent.
- Only after an output’s note is set to off, another one may be turned on for that output.
Modulation
- Because it’s fun and in the modular synth spirit, I included a modulation matrix.
- Choose an input signal source, set the modulation amount by attenuating and/or inverting it and send it to a target parameter.
- This lets you creat feedback loops, for example by modulating Clock or Advance rate with DAC outputs.
- Modulating Advance rate is very important for interesting rhythm generation.
Modern Art
- It’s modern art, related to what’s going on in the script, to give you a break from bits, bats, atts and stuff.
To Do:
- Maybe rename parameters to be more descriptive or offer an option to choose between the current, original module parameter names and new ones
- Implement a note quantizer feature to nudge MIDI note outputs into traditionally musical scales
- Maybe tweak MIDI Panic feature to send only necessary note off commands
- More testing
Known Issues:
- Changing a MIDI output setting from note to CC will probably make the current note get stuck. If that happens, or if other notes should get stuck, hold K1 and press K2 to send an “all notes off” signal.
Version History & Download
Version History
v0.5.0 - Initial release for further testing and feedback
v0.5.1 - MIDI panic implementation, tweaks and new default values
v0.5.2 - Notes will be cut off by DSR In bits now (see Gate Length EDIT menu)
v.0.5.3 - Added setting to set which DSR bits start and stop MIDI Notes, added internal modulation/feedback page
v0.6.0 - Added PolyPerc audio output, a UI for gate length setup and a Modern Art page
v0.6.3 - Added saving+loading, in-script manual (hold K1) and tweaked some stuff
v0.6.8 - Added a first try at Monome Crow CV in & out support
v0.6.9 - Another Crow test release, with added gate output and (hopefully) analog clock sync
v0.6.9.1 - Crow functionality code restructuring to make it run independently from MIDI
v0.7.0 - Added MIDI Clock output, made Modern Art more persistent and tweaked some bits and pieces
v0.7.3 - Added grid and midigrid support for testing, added a fourth mod matrix slot
v0.7.3.1 - Grid init error bugfix (hopefully)
v0.7.3.2 - another grid related bug fix
Latest release:
v0.7.4 - improved modulation and fixed Modulo Magic
Installation
Via the community library in Maiden, or manually via the REPL command:
;install https://github.com/TuesdayNightMachines/nmMelodyMagic/
Development Diary
I’ve posted this thread before the script is released to share my process and thoughts with you and to encourage discussion. Expand the diary entries below to read on
2021-05-02 Hello and welcome to infinite melodies!
When I still had my “Best of CGS” Serge modular synthesizer in 2018, I went on a quest to fully understand its more complex (seeming) modules, specifically Ken Stone’s Infinite Melody and Modulo Magic. Due to little documentation, this meant having to understand the actual analog circuitry diagrams, which was a wonderful learning experience for me, as a synth DIY novice back then.
I shared my findings in text form, supported by hand-scribbled images, in threads on Modwiggler and also as .md files on my GitHub:
Before I continue, here’s a generative CGS Serge Modular synth jam I posted a while back, which is centered around melody CVs generated with a combination of both modules:
CGS Serge Modular Synthesizer - Infinite Melody Music (w/ patch notes) #TTNM - YouTube
A few days ago, fellow synth nerd @gnome666 suggested that I should create a Norns port of the Infinite Melody module - a challenge which I happily accepted. And since the Infinite Melody goes so well together with the Modulo Magic, I (foolishly?) set my goal even higher, to create both modules and more in one script! The nmMelodyMagic!
The core functionality of the Infinite Melody was coded in Lua surprisingly quickly and I’ve got a working prototype script now, which is doing exactly what the module does, but optimized for MIDI instead of analog CV, meaning that parameter and output ranges are set to 0 to 127. It does not actually output MIDI yet, but I hope that this will be trivial to implement.
Again, my screenshot from above:
You can see the parameters from the module’s front panel, its DAC1-3 and Mix output values on the bottom and even a little grid visualization of the internal digital shift registers (DSRs), similar to my expertly painted drawings from the above mentioned guides:
My goals for this script: (in order of priority)
- simulate the Infinite Melody, Diatonic Converter and Modulo Magic functionalities as faithfully as possible
- add visualizations for what’s happening inside the virtual chips and wires
- optimize their inputs and outputs for a 7 bit MIDI value range (0 to 127)
- option for each individual output to send MIDI notes or CC
- additional “voltage processors” for each output to attenuate and offset the signals
- additional note quantizers for relevant outputs to tame the chaos even more
I look forward to share more of this project as it develops. In the meantime, let me know your thoughts and wishes and if you haven’t already, do check out those guides for an insight into Ken Stone’s brain
2021-05-04 Tackling the magic
Development continues very smoothly. Too smoothly? We’ll see! I still haven’t implemented an actual MIDI output, but I coded up the Diatonic Converter, a value processing screen and the Modulo Magic functionality and the output values (optimized for the MIDI range 0…127) seem correct.
Diatonic Converter
Preview image:
The Diatonic Converter was an add on circuit for the Infinite Melody. It receives a 6 bit input from the Infinite Melody, splits it in two groups and derives an octave and note number from each 3 bit group:
This is very cool, as it provided a diatonic 1V/Oct CV output, which is more traditionally musical than the other CV outputs of the Infinite Melody. A modification of the Diatonic Converter also allowed to disable the 2nd and 3rd bits of the octave selection, to reduce the octave range from 8 to only 2. I’ve included this modification as well in my script and I also plan to let the user choose the input, which was usually hard-wired to an Infinite Melody DSR output. It might be fun to wire it to the input DSR too for example (the pink one from my guide drawings), or even to an external MIDI CC signal converted to binary!
Modulo Magic
Preview image:
This thing was coded surprisingly quickly. Either it is just that simple, or I am getting better at nornsing
Here’s another drawing from my guide just for fun:
Since the Modulo Magic is a standalone module, I implemented input selection from the get go. So the user may choose any Infinite Melody/Diatonic Converter output or a “Manual” parameter, which of course can be mapped to an external MIDI CC source! This means you can use the module stand-alone and not just in combination with the Infinite Melody.
More thoughts
It occurred to me that I’m actually not sure if there are any people here who know what I’m talking about CGS Serge modular synths are a niche within a niche already and the modules I’m porting are certainly of the more obscure kind. So my plan is to add some kind of “live manual” to the script, making it easier for newcomers to learn to use it.
At the moment I’m not using any buttons, so I thought while holding K1, the display would show a screen telling you about the currently selected module or even the currently selected parameter. This shouldn’t be difficult to code.
Before that though, I want to add some visualizations to the Diatonic Converter and Modulo Magic screens too. The Infinite Melody screen already has the animated DSR grid, which is very helpful in my opinion and the other modules need something like this as well.
2021-05-05 Optimzations and Parameter Naming
Progress
-
Included an internal noise generator as a signal source for the Infinite Melody. Alternatively, the user may select a “Manual” MIDI CC input to be used for noise generation through the IM’s comparator.
-
Improved the update rate of the three ported modules Infinite Melody, Diatonic Converter and Modulo Magic, so it runs smoothly and properly in sync to the Norns master clock.
-
Started with the animated visualizations for the inner workings of the DC and MM. Some binary counting knowledge will probably still be required by the user, but even if there is absolutely none, I believe that it will still be fun.
-
Added input selection to the Diatonic Converter, so now it runs stand-alone and the user may even choose a “Manual” or MIDI CC source to be processed and turned into diatonic notes.
-
Added routing options for all outputs to MIDI Note or CC# with individual channel selection. No actual MIDI output yet though
Parameter Naming
I always felt that some of the parameters on the original modular synth modules had slightly misleading names - at least in the context I read them.
For example on the Infinite Melody, there is an input called “Clock”. This however is the clock source for the comparator/noise generator input, which populates the first DSR with bits and has nothing to do with rhythm or note output. So feeding a clock signal into that socket will not generate anything at the module outputs. Instead, the “Advance” input requires a typical clock signal to make the module generate melodies and the “Clock” input should actually be rather fast, even audio rate, to generate very random values.
So I’m a bit torn wether to stick to the original parameter names from the modules or to choose new, maybe more fitting, ones. Since I assume that few people will actually have experience with the original modules, this might not be a bad thing.
2021-05-06 v0.5.0 First release
I got the MIDI note and CC output working all of a sudden, so I thought it would be a good time to present a first version of the script to this forum to gather some feedback. MIDI Note output is still very rudimentary though. Just one note playing at a time per output, lasting the whole clock subdivision length. So a gate length feature is needed and I also need to check for conditions in which notes get stuck, one of which I found already
I also finished the visualizations for the three modules and hope they help.
2021-05-08 v0.5.3 Feature creep and a surprise
With the functionality of the original 4U CGS Serge modules being completely coded, it’s now time to think about where this script should actually be heading in terms of scope and usability.
I feel like I’m my own worst enemy when it comes to feature creep Norns scripting being so fun and easy as it is, I keep having feature ideas for which I already know most of the code structure in my head, so implementing them is not that hard at all so far. But this of course makes the script even more complex for the end user than it already would be, with only those weird original CGS Serge modules being ported to simply output MIDI.
But - much to my surprise - MIDI is quite a different beast than CV. You cannot only have a “note pitch” output with MIDI apparently, like when a modular synth outputs 1V/Oct pitch CV. No, with MIDI you also need to generate a gate start and stop signal every time you want your connected synth to make a sound or go silent. But the original CGS Serge modules I ported were not meant for this. They are only used to output pitch CV melodies and process incoming CV. Gating and rhythm signals needed to be generated with something else in the rack.
So I definitely needed to expand my script here beyond infinite melodies, to infinite gates/rhythms too. Staying true to the spirit of the modules, I thought that I could use the many bits in the digital shift registers (DSRs), to create note start and stop signals. The user can simply select a bit for note on and another one for note off commands. When the bits go high then, the command is sent, making sure that only one note can sound at once. So a note needs to be stopped in order for a new one to be generated. Since there are 12 signal outputs in total, one can still achieve polyphony, by routing those outputs to the same MIDI channel.
I feel like this will be a fun way of handling the gate situation, although it does add another layer of complexity to the script, especially for users who are not yet familiar with the original module functionality and their many DSRs. To tackle this problem, I need to start developing the promised in-script manual ASAP and also think about some additional user interface pages and data visualizations. Hopefully before even more features creep in.
2021-05-10 v0.6.8 Krah!
OMG! What a ride this project is! I can’t imagine I wrote 2717 lines of code already!!! Well, okay, 2717 of very spaciously formatted and heavily redundant code. But still
I fell like I’m at a point now where I should do some research and learn about programming best practices and how to structure code properly. Also, I need to check how this whole “object oriented” thing actually works and maybe how to spread parts of my script across several .lua files, for a better overview and easier maintenance. I don’t know if that’s actually a thing or helpful at all, but it seems like it.
I also want to know how to write this cryptic Lua “shorthand” … don’t know how to describe it, but sometimes, in other scripts, people seem to get a lot done with just one line of code, which is then not that well readable to me though, compared to the usual “human readable” Lua snippets. But it seems like you can omit writing certain things in Lua and string together stuff.
Anyway, I just implemented Monome Crow CV in & out support and hope that it actually works. I don’t have a Crow myself, but maybe I should save up for that. CV is obviously really useful. Thanks again to @gnome666 for nudging me into this direction and for offering to test the functionality.
When Crow support is done and I’ve tweaked the script some more, I think I’ll need to take a little break from coding. I’ve spend several hours almost every day for over two weeks now coding Norns scripts and while I’m still totally fired up and full of ideas, I need to check wether I’m neglecting something/someone else in my life … uhm … well, yeah, I know I do and she has been totally, amazingly cool the whole time and I’m so grateful I’m still on business trips during the week, where it’s easy to code alone in hotel rooms after work, but I’m afraid I spent too much time doing this on the past weekends at home too. Whoops! Coding for fun can be so crazily addictive. It’s like brain games, where you have to build the games and puzzles yourself too before playing with them.
By the way, I’m still coding exclusively on my iPad with Textastic and while it’s not as great as Visual Studio Code or some other desktop software like that, it works surprisingly well still and I feel quite at home with it.