AutoSustainer and Chord Recognition with GP Script


#1

Here’s a YouTube video I just uploaded showing how GPScript can be used to implement an AutoSustainer to sustain notes automatically until you release all keys AND then start playing a new chord. It’s an approach that I’ve depended on for years with several bands and had previously implemented it using the ‘borax’ objects in MaxMSP. Now it can be done natively.

There’s also an example of a chord recognizer and you can see chord names being displayed as I play the chords on a keyboard.

The script in this video also shows the syntax for writing functions. This stuff is all implemented and will be available in the next beta.

Happy new year to you all.


#2

Since the version 2.4 we have the object “AutoSustainer”. Please can someone post an example code with this new object?


#3

Pretty easy :slight_smile:

var MasterKeyboard : MidiInBlock
    AutoSustain    : AutoSustainer

Initialization
    AutoSustain.AutoSustainer_SetTarget(MasterKeyboard)
End

On NoteEvent(m : NoteMessage) from MasterKeyboard
    AutoSustain.AutoSustainer_Play(m)
End

On PitchBendEvent(m : PitchBendMessage) from MasterKeyboard
    AutoSustain.AutoSustainer_Stop()
End

Requires a MidiInBlock with the script name ‘MasterKeyboard’. Routing is just as if there were no scripting involved at all. Touching the PitchBend wheel stops all pending chord. Remove this callback if you don’t need it.

The only problem I see is when using a different MIDI channel than 1. What happens is that NoteOn events will be on channel (say) 5, but the NoteOff events are sent on channel 1. I guess that the AutoSustainer makes use of the NoteTracker internally which does not save the MIDI channel of incoming NoteOn events.


#4

I’m looking at the best way to address that MIDI channel stuff for AutoSustainer.


#5

Perfect! Thank you for your quick anwser. I tried to find a way that it works also with all the settings (velocity, key- and velocitysplit) from the MidiInBlock.

Here is my result:

var MasterKeyboard : MidiInBlock
	AutoSustain    : AutoSustainer
	AUTOSUSTAIN_ON_OFF : Widget
Initialization
	AutoSustain.AutoSustainer_SetTarget(MasterKeyboard)
End

On NoteEvent (m : NoteMessage) from MasterKeyboard
	var blockfilter : boolean
	var velo : integer
	velo = m.GetVelocity()
	blockfilter = false
	if (m.IsNoteOn()) then
		// Block all notes lower than MIN note from the MidiBlock settings
		if (GetNoteNumber(m) < MasterKeyboard.GetMinNoteFromMidiInBlock()) then blockfilter = true end
		// Block all notes higher than MAN note from the MidiBlock settings
		if (GetNoteNumber(m) > MasterKeyboard.GetMaxNoteFromMidiInBlock()) then blockfilter = true end
		// Block all notes lower than Min Velocity from the MidiBlock settings
		if (velo < ParamToMidi(MasterKeyboard.GetParameter(150)) && velo > 0) then blockfilter = true end
		// Block all notes higher than Man Velocity from the MidiBlock settings
		if (velo > ParamToMidi(MasterKeyboard.GetParameter(151))) then blockfilter = true end
	end
	if (blockfilter == false) then
		if (m.IsNoteOn()) then
			if (MasterKeyboard.GetParameter(154)==1) then
				// Calculate the new veloctiy when the MidiBlock setting is Constrain
				if (velo < ParamToMidi(MasterKeyboard.GetParameter(152))) then velo = ParamToMidi(MasterKeyboard.GetParameter(152)) end
				if (velo > ParamToMidi(MasterKeyboard.GetParameter(153))) then velo = ParamToMidi(MasterKeyboard.GetParameter(153)) end
			else
				// Calculate the new veloctiy when the MidiBlock setting is Scale
				velo = (Round(Scale (velo, 0, 127, ParamToMidi(MasterKeyboard.GetParameter(152)), ParamToMidi(MasterKeyboard.GetParameter(153)))))
			end
		end
		if (GetWidgetValue(AUTOSUSTAIN_ON_OFF) > 0) then
			// Sending out the notes with the new veloctiy and transpose setting from MidiBlock over AutoSustain
			AutoSustain.AutoSustainer_Play(Transpose(WithVelocity(m,velo),MasterKeyboard.GetTransposeFromMidiInBlock()))
		else
			// Sending out the notes with the new veloctiy and transpose setting from MidiBlock without AutoSustain
			MasterKeyboard.SendNow(Transpose(WithVelocity(m,velo),MasterKeyboard.GetTransposeFromMidiInBlock()))
		end
	end
End

#6

AutoSustainer works beautifully! It’s now part of my standard rackspace, merged with my metronome volume script. I can turn the sustain on and off using a button on my Livid DS-1 controller.