Send MIDI click notes to drum plugin (or Record MIDI Beats During Count-In)

Hi,

During a count-in, I would like to send MIDI click notes to my drum plugin, something like this:

On Timeline(bar : integer, beat : integer ) // EveryBeat

1:1 
  //	Send MIDI click note to EZDrummer
1:2 
  //	Send MIDI click note to EZDrummer     
1:3
  //	Send MIDI click note to EZDrummer 
1:4 
  //	Send MIDI click note to EZDrummer 		

End

Can it be done like that? I have not been able to create code that works to do that.

Included in the ultimate goal here is to have the MIDI click notes appear in the MIDI output captured by the GP recorder. This will assist in alignment of the recorded MIDI if it is later ingested into a DAW. This is why simply sounding the metronome during the count-in falls short of the goal.

What is the problem?

If it is doable, I don’t know how to do it. All my attempts to code it have failed so far.

In a rackspace script just send a midi note to a midi in plugin connected to your drum module.
Or in the global rackspace script when your drum module is located in the global rackspace.
You can use the function PlayNote

What did you try?

I haven’t tried it in a while, but I think the BeatMode parameter in the System Actions plugin, combined with the Midi Beat parameters, could achieve this without scripting.

There is good, related general information at these links:

but I may be trying to do something that cannot currently be done, and that is what I’m hoping to determine by consulting here where I might get an answer from someone who knows GP’s internals with a depth that I cannot. (Or by someone who has already achieved what I’m aiming at.)

I now think my topic title is not the best one for what I’m aiming at.

GP has a built-in recorder that offers a swtich to ā€˜Record MIDI Input’.

Snag_230506

When that is on, a MIDI file is written out by GP.

I would like to have the beats of the count-in saved as MIDI as the first events in that MIDI file.

That’s either possible, somehow, or not possible - depending on the internals of GP, yes?

So, that’s my question, and sorry for any prior sub-optimal statement of it. Thanks.

There is no concept of a count-in. If you need to do that, create a midi file with a count-in and throw it into the MIDI File player

I’m sure this is intended as a definitive answer, and I appreciate it.

To tie back to the OP, and put it on the record, is this impossible?

On Timeline(bar : integer, beat : integer ) // EveryBeat

1:1 
  //	Send MIDI click note to GP's recorded MIDI file
1:2 
  //	Send MIDI click note to GP's recorded MIDI file     
1:3
  //	Send MIDI click note to GP's recorded MIDI file
1:4 
  //	Send MIDI click note to GP's recorded MIDI file		

End

It seemed to me like it would be possible, but that was perhaps a faulty assumption on my part.

I don’t think the above requires the concept of a count-in, as the recorder is on in realtime once it is on. The Playhead and Timeline would then come into play at any point after the recorder is turned on.

IOW, it is a matter of routing. If the clicks were coming in externally, they would record. But I was hoping to generate them internally in GPScript.

You can do that - it’s documented in the script language documention – so I ask what I asked before, What did you try?

I can’t give you a forensic account of hours of failed attempts. I’m not sure you’d want to read it even if I could.

If no one has actually done it, then I have no hopes or expectations.

But it someone has done it, I hope for sharing of specific technique and/or already existing code. Thanks.

Sure it can be done. Just use the InjectMidiEvent system function

Thanks. I did have a go at using InjectMidiEvent, but I did not succeed with it (at least not yet).

InjectMidiEvent : Inject a message to any Midi Input Port with the specified physical device name

Declaration: function InjectMidiEvent (physicalDeviceName : String, m : midiMessage) Autotype
Category: MIDI
    Parameters
    physicalDeviceName : String
    m : midiMessage
Autotype

When I say I didn’t succeed, I mean I never got a MIDI not message thru to be saved in GP’s recorded MIDI file.

If I understand this function correctly, it is placing the injected MIDI into the Wiring Diagram as-if it were coming out of the plugin MIDI output port of the specific physical device. IOW, subsequent to that physical device, no block in the diagram would know that the injected MIDI didn’t actually come from that physical device.

However, I speculate that the ā€œtap pointā€ for GP’s recording of incoming MIDI from a physical device is prior to the ā€œinjection pointā€ of that function, and thus injected MIDI does not get recorded. Yes? No?

If this approach can work, I think there is something more I need to know, understand, or setup to make it work.

Try this as gig script or rackspace script

var TW : MidiInDeviceAlias

// Called at specfied bar:beats
On Timeline(bar : integer, beat : integer)  // EveryBeat
   
   1:1 
      InjectMidiEventViaRigManager(TW, MakeNoteMessage(64, 127))
   1:2 
      InjectMidiEventViaRigManager(TW, MakeNoteMessage(64, 0))
      InjectMidiEventViaRigManager(TW, MakeNoteMessage(64, 127))
   1:3 
      InjectMidiEventViaRigManager(TW, MakeNoteMessage(64, 0))
      InjectMidiEventViaRigManager(TW, MakeNoteMessage(64, 127))      
   1:4 
      InjectMidiEventViaRigManager(TW, MakeNoteMessage(64, 0))
      InjectMidiEventViaRigManager(TW, MakeNoteMessage(64, 127))   
   2:1
      InjectMidiEventViaRigManager(TW, MakeNoteMessage(64, 0))
      
End

No. Injection happens first. You can do it in a rackspace script….I tried it myself and the MIDI data was injected and captured.

Thank you @pianopaul and @dhj !

I’ve got working code now, two versions using InjectMidiEvent() and InjectMidiEventViaRigManager() respectively.

Much appreciated!

One more Q - I tried to make a scriptlet version (to send count-in click MIDI to EZDrummer), like so:

Scriptname : String = ā€œMIDICountInā€
Pre : String = "Scriplet - " + Scriptname

var	

Click_NoteNum : Integer = 42
Click_Chan : Integer = 4 // channel 4 is often drums on my Motif

///*
On Timeline(bar : integer, beat : integer ) // EveryBeat

// ignored if not called with EveryBeat (?)
// if uncommented, this info will be printed for each of the defined beats
/*
Prolog
//Print("Bar: " + bar + " Beat: " + beat )
Print( Pre + " " + bar + ā€œ:ā€ + beat )
end
*/

1:1 
  //Print( "Send MIDI click note after this" )
  EnableMetronome(true) 
  SendNow( MakeNoteMessageEx( Click_NoteNum, 127, Click_Chan ) )
  
1:2 
    SendNow( MakeNoteMessageEx( Click_NoteNum, 0, Click_Chan ) )      
  SendNow( MakeNoteMessageEx( Click_NoteNum, 127, Click_Chan ) )
    
1:3
    SendNow( MakeNoteMessageEx( Click_NoteNum, 0, Click_Chan ) )     
  SendNow( MakeNoteMessageEx( Click_NoteNum, 127, Click_Chan ) )
  
1:4 
    SendNow( MakeNoteMessageEx( Click_NoteNum, 0, Click_Chan ) )      
  SendNow( MakeNoteMessageEx( Click_NoteNum, 127, Click_Chan ) )

2:1
SendNow( MakeNoteMessageEx( Click_NoteNum, 0, Click_Chan ) )
SendNow( MakeNoteMessageEx( Click_NoteNum, 127, Click_Chan ) )

2:2
SendNow( MakeNoteMessageEx( Click_NoteNum, 0, Click_Chan ) )
SendNow( MakeNoteMessageEx( Click_NoteNum, 127, Click_Chan ) )

2:3
SendNow( MakeNoteMessageEx( Click_NoteNum, 0, Click_Chan ) )
SendNow( MakeNoteMessageEx( Click_NoteNum, 127, Click_Chan ) )

2:4       // turn off metronome after the 2nd bar  (i.e. do a 2-bar count-in)
    SendNow( MakeNoteMessageEx( Click_NoteNum, 0, Click_Chan ) )       
  SendNow( MakeNoteMessageEx( Click_NoteNum, 127, Click_Chan ) )
  EnableMetronome(false) 

3:1
SendNow( MakeNoteMessageEx( Click_NoteNum, 0, Click_Chan ) )

End

It compiled cleanly, but no MIDI comes out of the scriptlet block (as observed in a connected MIDI Monitor).

Do I need to convert from NoteMessage to MIDIMessage? Something else?

I am not sure if the callback On Timeline is even executed in a scriptlet.
There more I think the less sense does it make to react on ā€œOn Timelineā€ in a scriptlet.
You could have more than 1 scriptlet and when they all would support ā€œOn Timelineā€ that would be chaos.

1 Like

Correct

I track the logic here.

I suggest

a) that the doc page ( Callbacks > Playhead Events > On Timeline ) explain when & where On TImeline can or can’t be used.

b) that On TImeline fail compilation with a reported error when not used as designed/intended.