Sometimes you may want to have the lowest note you play to go a separate plugin/device, for example a bass plugin (of course ). You could use the filter-option in the MIDI-in block, but that one filters the other notes out and do not remember the ones that are held.
The same thing goes for playing only the highest note.
Just for fun and out of curiosity I wrote two scriptlets for playing the lowest c.q. playing the highest note, while remembering the held notes, so these can be played when the current lowest (or highest) note is released. These scriptlets are named ‘PlayHighestNote’ and ‘PlayLowestNote’
An example using PlayLowestNote:
- You play C3-E3-G3, the C3 will pass, but E3 and G3 are remembered
- You release C3. A Note Off will be sent for C3 and a Note On will be sent for E3 (the next lowest)
Another example using PlayLowestNote:
- You play E3-G3, the E3 will pass, but G3 is remembered
- You play C3 in addition. A Note Off will be sent for E3 and a Note On will be sent for C3 (the new) lowest), but E3 is being remembered
- You release C3. A Note Off will be sent for C3 and a Note On will be sent for E3 (the next lowest)
- You release E3. A Note Off will be sent for E3 and a Note On will be sent for G3 (the next lowest)
General guidelines:
- The scriptlets are channel aware, so a Note On entering the scriptlet at channel 2 will leave the scriptlet (when appropriate) at channel 2.
- The scriptlets are not multichannel: For example when you a Note On E3 at channel 2 (and it it only remembered) and after that a Note On E3 at channel 8, if the E3 becomes the lowest (or highest) note it will be sent at channel 8. The E3 at channel 2 will be lost. As this also goes for the Note Off messages, things might become a real mess. Use separate MIDI-in blocks or filters to circumvent this
- AfterTouch and PolyTouch are respected: AfterTouch just passes, PolyTouch passes when it is the current playing note, otherwise the velocity of the remembered note is adjusted to have the velocity of the PolyTouch message. I’m not sure whether this is the desired behavior. I do not have equipment to really test this
I created a demo gig file. Screenshots:
(The buttons operates like a radio switch, but the implementation is rather rudimentary. If you try hard enough you might succeed to activate two buttons at a time. But after all, that’s not what this gig file is about.)
For people (only) wanting to see the script, this is ‘PlayLowestNote’:
var nt : NoteTracker
var NoteVelocities : integer[128]
var NoteChannels : integer[128]
var CurrentNote : int = 128
var CurrentChannel : int = 0
/*
* This scriptlet filters out all notes except the lowest. All the notes, however, are
* tracked and when the current lowest note is released the next lowest note from
* the tracker starts. If all notes are released, of course no note is send
*
* The midi channels are recorded, but this scriptlet is not multichannel capable:
* If first a D3 on channel 1 is tracked and after that a D3 on channel 3 is coming in,
* the D3 on channel 1 is lost.
* To solve this, use a separate scriptlet for each channel
*/
Initialization
SetInfoMessage("MIDI Filter for only playing the lowest note")
SetDisplayMessage("MIDI Filter for only playing the lowest note")
End
On NoteOnEvent(m : NoteMessage)
var heldNotes : integer array
var newLowestNote : int
var noteOff : NoteMessage
NoteVelocities[GetNoteNumber(m)] = GetVelocity(m)
NoteChannels[GetNoteNumber(m)] = GetChannel(m)
NoteTracker_GotNote(nt, m)
heldNotes = NoteTracker_GetHeldNotes(nt)
newLowestNote = SmallestInt(heldNotes)
if newLowestNote != CurrentNote
then
if CurrentNote < 128
then
noteOff = MakeNoteMessageEx(CurrentNote, 127, CurrentChannel)
SendNow(ReinterpretAsNoteOffMessage(noteOff))
end
SendNow(MakeNoteMessageEx(newLowestNote, NoteVelocities[newLowestNote], NoteChannels[newLowestNote]))
CurrentNote = newLowestNote
CurrentChannel = NoteChannels[newLowestNote]
SetDisplayMessage("Current: " + NoteNumberToNoteName(newLowestNote))
end
End
On NoteOffEvent(m : NoteMessage)
var heldNotes : integer array
var newLowestNote : int
var noteOff : NoteMessage
NoteTracker_GotNote(nt, m)
heldNotes = NoteTracker_GetHeldNotes(nt)
if Size(heldNotes) > 0
then
newLowestNote = SmallestInt(heldNotes)
if newLowestNote != CurrentNote
then
noteOff = MakeNoteMessageEx(CurrentNote, 127, CurrentChannel)
SendNow(ReinterpretAsNoteOffMessage(noteOff))
SendNow(MakeNoteMessageEx(newLowestNote, NoteVelocities[newLowestNote], NoteChannels[newLowestNote]))
CurrentNote = newLowestNote
CurrentChannel = NoteChannels[newLowestNote]
SetDisplayMessage("Current: " + NoteNumberToNoteName(newLowestNote))
end
else
SendNow(m)
CurrentNote = 128
SetDisplayMessage("MIDI Filter for only playing the lowest note")
end
end
On ControlChangeEvent(m : ControlChangeMessage)
SendNow(m)
End
On PolyTouchEvent(m : PolyTouchMessage)
NoteVelocities[GetPolyTouchNoteNumber(m)] = GetByte(m, 2)
if GetPolyTouchNoteNumber(m) == CurrentNote
then
SendNow(m)
end
End
On AfterTouchEvent(m : AfterTouchMessage)
SendNow(m)
End
The scriptlet ‘PlayHighestNote’ is almost the same.
The gig file itself:
MonoPhonicMidi.gig (83.2 KB)
Have fun with it.