Real time note transmittor / splitter

Hi Martin and Thomas,
perhaps some crazy ideas here below, and not within the intended comfort zone of the E1.
Nonetheless, I’m just curious: is the E1 fast enough when it comes to real time processing/retransmitting incoming notes and aftertouch ?
If it is fast enough, we may use it for MIDI note event filtering/routing. Not the standard stuff like taking out messages or changing channels, but more advanced things:

  • Take the lowest note played below middle C and transmit only that note to a different MIDI channel, so the bass can (also) be played by a separate bass synth
  • Same for highest note played above a certain threshold => lead synth
  • Apply multitimbral keyboard tricks in combination with monotimbral sound engines:
    • layering: duplicate incoming messages over multiple channels, to allow quick layering of multiple synths (16 on/off buttons on a screen define to which midi channel you transmit to)
    • velocity layering: same as layering, but per outgoing channel the velocity values can be recalculated, for instance: Vel becomes 127-Vel). Now you can dynamically balance between 2 synth sounds.
    • keyboard split : assign key zones to different midi channels, combined with a transpose function
  • Filter out the channel aftertouch and assign its value as polyphonic aftertouch to the highest note only
  • Synth polychaining: Distribute the incoming notes messages via some round robin method over multiple midi channels, so you could polyphonically control multiple (monophonic) synths of various make.

I’ll be testing some of these ideas just to learn working with midi callback functions.

Now I’ll try to leave this behind me and concentrate on today’s work :slight_smile:

1 Like

i had as wel this idea of implementing polyphony over different channels using rounrobin.
you could use it to play polyphonic synths that are multimembral.
then change every patch a bit for depth
If i am correct we should now be able to perform actions based on any incomming midi message type. not sure
polyAT on the last note only is as wel a cool idea. i believe the SY 85 or 99 does that.

the idea is not mine. Steve Hunt has implemented it in his LFE and also Arturia has foreseen something similar in the latest polybrute firmware. It is indeed a very musical way of using aftertouch. And a lot of synths respond to polyAT (without generating it themselves).

Based on my experimentation it is fast enough. I’m working on E1-based “advanced” controller for Launchpad Pro – chords, arp, sequencer, that kind of stuff – and the initial tests are rather promising.

3 Likes

So far the midi layering is quite simple to do. Code is below.
A bit of explanation. I have 16 buttons with parameter numbers 1001 til 1016. If on value 1, the purpose is to transmit the note to channel 1 to 16, hence why I subtract 1000 from the parameternumber.
I need to check transmission for each note On and note Off, therefor two callback functions.
I allow incoming messages from any channel, but I never retransmit into the incoming channel as this is already covered by the E1’s own routing.
Last but not least, I gave each button the function ‘silenceNotes’ so it will send the ‘All Notes Off’ on midiCC123 when layering is no longer wanted. This to prevent stuck notes.

Learnings so far

  • the E1 is pretty fast, so I hear no delay so far, even when I send the same note to 10 different MIDI channels at once :slight_smile:
  • Not all synths responds to midiCC 123 (or 120) so I do get stuck notes if I switch off a button whilst playing

Can anyone help with the following:

  • This is still simple code, but it does process lots of if-statements. Is that good coding if we want the E1 to be at it fastest? If not, how should I rewrite it?
  • To overcome the issue with the stuck notes, I will need to retain what notes are being held so I can individually transmit a NoteOff to each of them to the appropiate channel. What is the best (and fastest) way to get this working: should I make an array with 120 notes where I keep the state of each note at all times? Or should I rather assume a max polyphony of let’s say 10 held notes max, so my array would be much smaller and only contains the current notes, but is maybe much more difficult to handle? I’m inclinded to actually go for an array of 122 notes (120 + spaceholder for current lowest and current highest note)

– Setup

deviceId = 1
device = devices.get(deviceId)
devport = device:getPort()
devchannel = device:getChannel()
pages.setActiveControlSet(1)

– callback functions

function midi.onNoteOn (midiInput, channel, noteNumber, velocity)
for i = 1,16 do
if i == channel then end
if (parameterMap.get (deviceId, PT_CC7, 1000+i) == 1 ) then
midi.sendNoteOn (devport , i, noteNumber, velocity)
end
end
end

function midi.onNoteOff (midiInput, channel, noteNumber, velocity)
for i = 1,16 do
if i == channel then end
if (parameterMap.get (deviceId, PT_CC7, 1000+i) == 1 ) then
midi.sendNoteOff (devport , i, noteNumber, 0)
end
end
end

– this sends an ‘all notes off’ when the midi channel is no longer to be used.
function silenceNotes(valueObject, value)
local message = valueObject:getMessage()
if value == 0 then
midi.sendControlChange(devport, tonumber(message:getParameterNumber())-1000, 123, 0)
end
end

1 Like

I have some ideas for all of this, but I really don’t have any time until Sunday to sketch out answers.

LUA doesn’t have a switch statement so my thought would be to use an array and then execute the function directly.

Note offs are a problem for anything doing MIDI. Most end up keeping a queue/stack/list of notes sent (note number, channel) and as you send offs, clear that entry and when there’s a channel switch go through the list and clear out (or adjust) the ones affected by the channel change

1 Like

cool stuff.

Regarding the performance, E1 is rather fast I would say, When it came to adding scripting to E1, I decided to use Lua as the implementation seemed very efficient and fast. I will follow this thread, I guess ideas will be flying around here. If you felt anything is needed to be added or adjusted on the side of the firmware, just post it here.

@farcaller - I am very curious!

1 Like

The first version of the note processor is ready .

It contains the multitimbral functions I was looking for, with layering, splits, key zones, velocity inversions, volume management, incoming notes monitor and a panning randomizer. I must admit it is musically inspiring.

Before making the other functions, I’ll have to learn to work with arrays first. Have fun!

1 Like

I hope to do more work on this in January, for now it’s a quick hack to see a proof of concept :slight_smile:

1 Like

A lot of progress to report :slight_smile: I’m quite happy with the result so far.
Those arrays start to do what I want them to do !
The preset is now called “Notes Transmittor V2”

Now that I get the hang of working with tables, I’ve added a bunch of channel dependent functions and play modes:

  • Two new playing modes have been added, allowing you to layer monophonic synths on to of polyphonic ones, where they will play the highest or lowest notes, with a certain tolerance (without tolerances, you’d loose unintentionally notes when playing legato.
  • Pitch bend and Mod wheel data can now be filtered out per channel.

Next on the wish list: transmission of expression pedal, hold pedal, all cc’s, the aftertouch conversion to poly-AT on highest note only, and a synth polychain play mode.
And also ‘pure non-legato’ monophonic transmission, i.e. the previous note is first given its note off, before the next note is transmitted. This way the EG’s of the receiving synth will always be retriggered.

Idea’s , suggestions and bug reports are welcome.

2 Likes

Progress report.

This is a very rewarding project :slight_smile:
Where I am so far on the remaining wish list: almost complete!
This last version is not yet published. I need to test it a bit more.

Implemented from the wishlist:

  • transmission of expression pedal with an added inverted mode, and a parameter setting to lower the range for better musical results when balancing expression values between multiple instruments
  • hold pedal transmission can be switched off per channel (default on)
  • all other cc’s transmission can be switched off per channel (default off)
  • aftertouch transmission ànd conversion to poly-AT on highest note only (SNAT) is possible.
  • 2 new monophonic play modes added, that will work on polyphonic synths also:
    • “highest/retrig”: Highest note only but with instant envelope retrigger (no legato)
    • “last/retrig”: Last note only but with instant envelope retrigger (no legato)

Left to do:

  • synth polychain play mode
  • transpose function
1 Like

thanks @oldgearguy for your tips.
Arrays were indeed the way to go.
The idea with the stack of active notes was also implemented and proofed useful.

Now for the PolyChain play mode I’ll add 2 more stacks to create a dynamic voice assignment algorithm.

  • freeVoices: this one will be fed with entries when:
    • a synth is added to the PolyChain (according to its number of voices)
    • a voice is cleared from the activeVoices stack
    • the oldest voice in the stack will be moved to the activeVoices when a NoteOn is received
  • activeVoices: this one will be fed with every NoteOn:
    • from the freeVoices stack, as long as it is not empty
    • from the activeVoices stack, if no more freeVoices are available (voice stealing)

Whenever a synth will be taken out of the PolyChain play mode, all of its voices will be cleared, regardless of the stack they are assigned to at that moment.

1 Like

very cool stuff here. I downloaded an earlier version to see what it all does and it’s pretty cool.

Glad the forum has been helpful for you.

2 Likes

Hi, version 3 is now ready and available as a preset.

A full explanation is added in its description

Was a challenge to get the polychain working decently, but I think it’s okay now. It needed 3 stacks to make it work: the active voices, the free voices and the pressed notes.

Everything is in there I could think of to turn individual synths into one multitibral monsterengine. And vice versa: to turn a monster synth back into its monophonic counter part.

The transpose is well suited for analog synths with continous pitch faders: you can now change pitch quickly without touching the oscillators and without altering the pitch of the other instruments played by the same keyboard.
And the single note aftertouch? Well, see or better hear for yourself :slight_smile:

Everything isn’t tested together yet, so there might still be some issues left. The logs are still abundant and the code needs some cleaning up.
As this is my first lua project ever, you’ll need to forgive me.
But do mention any found bugs or unexpected behaviour here, as I want this preset to be “a okay”.

5 Likes

This is a great project!

I did try it out, and after 5 minutes of playing non stop jazz scales it suddenly stop for an instant an then drop the notes out of tempo (was it a delay caused by the E1?)

Any way, works great.

1 Like

this is great. would be great to also have a roundrobin/cycling voice allocation algorithm.

imagine every time you press a key another voice is triggered. that is just so musical.

Two things: it has the round robin.allthough not yet perfect. What you need to do: set the synth you want to polychain in play mode, set the max amount of voices they can use, and activate those channels. That’s it.

I’m making a brand new version by the way, as I found the UX can use some improvements.

2 Likes

I’ve just published a new version V4 . Electra One App

  • the keyboard is to be set on MIDI channel 16
  • only 15 synths allowed (MIDI 1 - 15)
  • better monitoring of what is happening on the first page
  • velocity inversion is now configurable
  • the voice distribution in polychain mode has three different settings
  • new hold modes: allows sostenuto between layered synths

Beware: this preset is dangerously close to maxing out memory. So any ideas to further optimize memory are more than welcome !!! :stuck_out_tongue_closed_eyes:

Below is the MANUAL . ENJOY

NewIgnis Notesplitter V4


What if you could turn any midi synth in a master keyboard?
And what if you could add 15 synths together as if they are one multitimbral monstersynth?
What if you want to assign key aftertouch to the melody, using a channel AT keyboard?
Then this is the preset you’re looking for.

This preset assumes the keyboard transmits on channel 16 (port 1) and assumes the 15 synths are connected to MIDI channels 1-15.
Beware: messages will be routed through unprocessed on each channel they were received.


MAIN PAGE

Active transmission channels: when on, incoming notes may be transmitted into that MIDI channel, allowing mutiple synths playing at once.

Green controls are settings

Minimum Velocity will narrow the velocity range even when inverting the velocity values

Minimum Expression will narrow the expression CC range even when inverting the expression values

Pan: is a function to control CC10 in 3 ways:

  • Off: CC10 will be static on a default value 64 (= center)
  • Cyclical: received notes will be cyclically panned in the stereo field
  • Random: panning will be randomized.
    The spread of the effect can be controlled, widening the stereo effect.

High note detect Tolerance: when choosing play mode ‘highest only’, a strict algorithm would not allow you to descend notes in legato style. The tolerance amount (in semitones) allows you to loosen up that restriction and descend up to the chose amount of semitones and it will still be considered as the highest tone to play. The same applies to the Lowest note algorithm, or melody detection for High Note AT.

Yellow controls don’t do anything, except monitoring Incoming messages

Red controls don’t do anything, except monitoring Outgoing messages


SYNTH SET UP

This page doesn’t do anything yet, as I’m running out of memory for the moment


ON/OFF & VOLUME PAGE

Allows you to choose what channels are active.
Allows you to set the MIDI volume per channel


VELOCITY & EXPRESSION PAGE

Velocity Inversion When on, the velocity information on the channel will be inverted. This allows velocity dependent layering.

Expression pedal Transmission: there are three modes for transmitting Expression pedal:

  • Through: Expression pedal is transmitted unaltered
  • Inverted: Expression pedal is transmitted inverted. This allows expression dependent layering.
  • Off (X): Expression pedal values are not transmitted

PITCH BEND & MOD WHEEL AND AFTERTOUCH PAGE

PitchBend / Mod Wheel: allows to filter out one or both of these modulators. Default is: all passes through to the active channels.

Channel Aftertouch Transmission: there are three modes for transmitting channel aftertouch:

  • Channel AT Through: channel aftertouch is transmitted unaltered
  • High Note AT:the channel aftertouch is converted into polyphonic aftertouch but only applied to the highest note playing
  • Off (X): channel aftertouch is not transmitted

KEY ZONE PAGE

Key Zone: limits the transmitted notes per channel to the ones within the key zone. This allows for multisynth splitting and layering.

  • LOW: selects the lowest note that can be transmitted.
  • HIGH: selects the highest note that can be transmitted.
  • There are separate settings applicable to synths in polychain play mode (the channel key zones will be ignored when in polychain)

NOTE SHIFT PAGE

Note Shift Allows you to shift notes up to 2 octaves up or down.


PLAY MODE & POLYCHAIN PAGE

Play Mode choose the playing style per channel. There are two polyphonic and 4 monophonic styles. You can apply a monophonic style also to a polyphonic instruments, which will influence its playing behaviour.

  • Layer: all notes within the chosen key zone are transmitted
  • Poly Chain: all synths in poly chain will work together as if they are separate voices of the same synth.
  • Highest Only: will only transmit the highest note (with a certain tolerance), which is suited for combining chord playing with a lead line played by a monophonic synth. It also changes a polyphoinc instrument in a monophonic version.
  • Lowest Only: will only transmit the lowest note (with a certain tolerance), which is suited for combining chord playing with a bass line played by a monophonic synth
  • Highest/Retrig: same as Highest Only, but a new note is always preceedeed but the previous’s note off, even if you are still holding it. This forces a mono synth to retrigger its envelopes, even when you play legato or holding chords.
  • Last/Retrig: same as Highest/Retrig but will only transmit the last note
    .

Polychain

You need to set here for each synth the maximum amount of voices each synth is allowed to play when joining the polychain. Do not set more voices than the synth actually has, as the E1 will attempt to assign those non-existing voices during playing.
.

VOICE ASSIGN
This setting changes the way the voices are distributed over the synths in polychain mode

  • Cyclic per synth: voices are grouped per synth
  • Spread : voices are spread for maximum variation
  • Random : voices are ordered randomly

HOLD PAGE

Hold pedal transmission

  • HOLD: the hold information on the channel will be transmitted, unaltered
  • NO MORE NOTES: when pressing the hold pedal, the playing notes will be held, but no new notes will be transmitted. Allows for sostenuto effects when layered with other synths.
  • NO HOLD: no hold pedal info will be transmitted. Allows for sostenuto effects when layered with other synths that are in NO MORE NOTES mode.

OTHER CC PAGE

Other CC transmission
Is by default turned off, as most other CC’s have different purposes per synth. However you can turn the transmission on per MIDI channel.

2 Likes

fyi
I found a bug, and corrected it 30 minutes ago

1 Like

Thanks, looking forward to try this out!

1 Like