OK… here we go! ![]()
Since this rackspace still was in an experimental phase i had to do some “cleanup” first, so it took a bit longer…
This rackspace will do the following things:
- load a specified midi file (has to be done in the script!)
- do a remapping of particular midi tracks to a specified midi channel (has to be done in the script!)
- step sequentially through the midi events of that file according to the quantization setting using two diffrent trigger controls
You can
- set the quantization value with a knob widget
- see the current position of the midi sequence
- set the used note/key pair as stepping triggers or
- use a pad widget as a stepping trigger (could be midi-mapped to a pedal or whatever)
- use a pad widget to reset the sequence to start (could be midi mapped to a certain note or midi controller)
- use a widget as “panic-button” (sends all notes off & resets midi)
This is the code of the script:
Var
MidiStepIn : MidiInBlock
cs : MidiSequence
trackCount, quantization, UStepKey : integer
padStep, padReset, lblPosition, knbQuant, btnPanic, knbUStepKey : widget
//user function to calculate the quantization from the knob widget's value
function SetQuantization(kVal : double) returns integer
var
exponent, quantValue : double
exponent = ScaleRange(kVal, 0.0, 4.0)
quantValue = Power (2.0 , exponent)
result = Round(quantValue)
SetWidgetLabel(knbQuant, result)
End
//user function to handle the MIDI-Stepping
function MidiStep()
var
notes : MidiMessage Array
aNote : MidiMessage
index : integer
trackIndex : integer
bar, beat, tick : integer
bar = MidiSequence_GetCurrentBar(cs)
beat = MidiSequence_GetCurrentBeat(cs)
tick = MidiSequence_GetCurrentTick(cs)
if MidiSequence_EndOfSong(cs) then
MidiSequence_ResetToStart(cs)
end
SetWidgetLabel (lblPosition, "Pos: " + bar + " / " + beat + " / " + tick)
MidiSequence_CollectEventsNow(cs); //fetch all events from current position
notes = MidiSequence_GetCurrentEvents(cs, 3) // Get current events from track #3
for index = 0; index < Size(notes); index = index + 1 do
aNote = notes[index]
SendNow(MidiStepIn, aNote)
end
End
initialization
//load the midi file (!!! use a a"/" instead of "\" for path separator !!!)
MidiSequence_LoadStandardMidiFile(cs, "D:/MIDI-files/The-Model.mid")
trackCount = MidiSequence_GetTrackCount(cs) //get number of tracks of midi file
Print(trackCount)
quantization = SetQuantization (GetWidgetValue (knbQuant)) //get quantization value from widget
MidiSequence_Quantize(cs, quantization ) // Quantization may be 1/2/4/8/16
//map events coming from track 2 & 3 both to MIDI channel 1
//change remapping to your needs -> add/remove according code lines
MidiSequence_MapOutputChannel(cs, 2, 1)
MidiSequence_MapOutputChannel(cs, 3, 1)
UStepKey = ParamToMidi(GetWidgetValue (knbUStepKey))
end
// Use this as a finger clock -- pressing the trigger control (widget or two notes) behaves
//like a manual clock to sequence through the MIDI events of the loaded file
//use pad widget as a trigger to step through the MIDI file
On WidgetValueChanged (pVal : double) from padStep
if pVal > 0.6 then
MidiStep()
end
End
//use the two trigger notes to step through the MIDI file (use knob widget to set the according notes)
On NoteEvent(m : NoteMessage) from MidiStepIn
//if the note event is a trigger note, step forward
if GetNoteNumber(m) == UStepKey or GetNoteNumber(m) == UStepKey-2 then
if IsNoteOn(m) then
MidiStep()
end
else //all other note will be played
SendNow(MidiStepIn, m) //just send out note event
end
End
//reset the midi sequence to start
On WidgetValueChanged (pVal : double) from padReset
var
bar, beat, tick : integer
AllNotesOff(MidiStepIn)
MidiSequence_ResetToStart(cs)
bar = MidiSequence_GetCurrentBar(cs)
beat = MidiSequence_GetCurrentBeat(cs)
tick = MidiSequence_GetCurrentTick(cs)
SetWidgetLabel (lblPosition, "Pos: " + bar + " / " + beat + " / " + tick)
End
//Panic button = all notes off & back to start
On WidgetValueChanged (pVal : double) from btnPanic
if pVal > 0.6 then
MidiSequence_ResetToStart(cs)
Panic() // Stop any sounds that were being held
AllNotesOff(MidiStepIn)
end
End
//use knob to set quantization for sequence stepping
On WidgetValueChanged (kVal : double) from knbQuant
quantization = SetQuantization (kVal)
MidiSequence_Quantize(cs, quantization )
End
//use knob widget to set the Upper note/key used to step forward
On WidgetValueChanged (kVal : double) from knbUStepKey
UStepKey = ParamToMidi(kVal)
SetWidgetLabel (knbUStepKey, "" + NoteNumberToNoteName(ParamToMidi(kVal)-2) + "/" + NoteNumberToNoteName(ParamToMidi(kVal)))
End
And here is the gigfile for download:
midistepper.gig (115.8 KB)
I hope this helps somehow…
…and maybe, some day in the future, we might have some better options to do such things?!
However, have fun with it! May it be useful! ![]()
Cheers, Erik
