There are already many topics about seamless switching. The approach depends on the use case:
- For seamless switching of rackspaces while maintaining the held notes there is the built-in MIDI Patch Persist.
- For preserving held notes while switching to a different plugin/channel using variations, it’s best to filter the note-ons only in different MIDI In Blocks or even more advanced options.
Still I couldn’t find the one suitable for my specific need concerning transposing:
I sometimes simply need to transpose the MIDI going to one plugin in the middle of the song (for the last chorus, for example). While both the integrated transposer and the MIDI In Blocks send notes off when adjusting the transposition, I need a simple transposer plugin that preserves the held notes.
I created a scriptlet for this case making use of the note tracker functions. It works on all channels and has a simple on/off switch (intended to be linked to a widget) and a transposition slider.
I must admit, after writing the code, I discovered a similar functionality hidden inside this pretty complex gig file (except for multiple channels). I wanted to share it anyways if one wants only this simple functionality.
This is the scriptlet preset:
Transpose with Note Persist.gpp_internal.zip (2.3 KB)
As an alternative, here’s the code:
var
TransposeSwitch : Discrete Parameter "off", "on" = "off"
Transpose : Subrange Parameter -64..64 = 7
Tracker1, Tracker2 : MultiChannelNoteTracker
NoteNumber, Channel : integer = 0
Initialization
SetDisplayMessage("Preserves notes when switching on/off. Sends all notes off when adjusting transpose.")
For Channel = 1; Channel <= 16; Channel = Channel+1 do
MultiChannelNoteTracker_Clear(Tracker1, Channel)
MultiChannelNoteTracker_Clear(Tracker2, Channel)
End
End
On NoteEvent(m : NoteMessage)
NoteNumber = GetNoteNumber(m)
Channel = GetChannel(m)
If GetVelocity(m) > 0 then // note-on
If TransposeSwitch == "off" then
If MultiChannelNoteTracker_IsNoteOffPending(Tracker1,NoteNumber,Channel) == false then // If this note isn't already registered
MultiChannelNoteTracker_GotNoteOn(Tracker1,NoteNumber,Channel) // Register it
End
SendNow(m) // Send it
Else
If MultiChannelNoteTracker_IsNoteOffPending(Tracker2,NoteNumber+Transpose,Channel) == false then // If this transposed note isn't already registered
MultiChannelNoteTracker_GotNoteOn(Tracker2,NoteNumber+Transpose,Channel) // Register it
End
SendNow(WithTranspose(m,Transpose)) // Send it transposed
End
Else // note-off
If TransposeSwitch == "off" then
If MultiChannelNoteTracker_IsNoteOffPending(Tracker2,NoteNumber+Transpose,Channel) then // If this transposed note is pending
SendNow(WithTranspose(m,Transpose)) // Send it transposed
MultiChannelNoteTracker_GotNoteOff(Tracker2,NoteNumber+Transpose,Channel) // Deregister it
End
SendNow(m) // Send it
MultiChannelNoteTracker_GotNoteOff(Tracker1,NoteNumber,Channel) // Deregister it
Else
If MultiChannelNoteTracker_IsNoteOffPending(Tracker1,NoteNumber,Channel) then // If this note off is pending
SendNow(m) // Send it
MultiChannelNoteTracker_GotNoteOff(Tracker1,NoteNumber,Channel) // Deregister it
End
SendNow(WithTranspose(m,Transpose)) // Send it transposed
MultiChannelNoteTracker_GotNoteOff(Tracker2,NoteNumber+Transpose,Channel) // Deregister it
End
End
End
On ParameterValueChanged matching Transpose
For Channel = 1; Channel <= 16; Channel = Channel+1 do
If MultiChannelNoteTracker_NoteOnCount(Tracker1,Channel) > 0 then
SendNow(MakeControlChangeMessageEx(123,127,Channel))
MultiChannelNoteTracker_Clear(Tracker1,Channel)
End
If MultiChannelNoteTracker_NoteOnCount(Tracker2,Channel) > 0 then
SendNow(MakeControlChangeMessageEx(123,127,Channel))
MultiChannelNoteTracker_Clear(Tracker2,Channel)
End
End
End