How would I change notes with a Scriptlet

  • With On NoteOn use NoteTracker_GotNoteOn
  • With On NoteOff use NoteTracker_GotNoteOff
  • With On Note use NoteTracker_GotNote

So in your example don’t use On NoteOn Event, but On Note Event.

A NoteTracker is not a printable object. Use NoteTracker_GetHeldNotes and print the elements of the array you get.

To clarify

On NoteEvent(m : NoteMessage) // I.e, respond to BOTH Note On and NoteOff
   NoteTracker_GotNote (nt, m) // This will now keep track properly

   Print(nt) // Printing this object currently just returns the count - it's really only intended for debugging
End

I am trying to capture a 3 or 4 note chord using NoteTracker with Scriptlet, but it isn’t working! Obviously, I would eventually like to do something to the notes captured on the NoteOnEvent but I can’t get the code to distinguish between a played 3 note chord and a played 4 note chord. Any help plz?

var
xArray : Integer Array
nt : NoteTracker
nNotes : integer
n1 : integer
n2 : integer
n3 : integer
n4 : integer
n5 : integer
thisNote : integer

On Activate
ClearArray(xArray)
NoteTracker_Clear(nt)
End

On NoteOnEvent(m : NoteMessage)

NoteTracker_GotNote(nt,m)

    
nNotes = NoteTracker_NoteOnCount(nt)
Print("nNotes = " + nNotes)
thisNote = GetNoteNumber(m)
xArray <-- thisNote

if nNotes == 4 then
    n1 = xArray[0] - 12
    n2 = xArray[0] 
    n3 = xArray[1]
    n4 = xArray[2] + 12
    n5 = xArray[3]
    Print("Number of notes = " + Size(xArray) + "    " + n1  + " " + n2 + " " + n3 + " " + n4 + " " + n5)
    SendNow(m)
    nNotes = 0
End

if nNotes == 3 then
       Print("3 nNotes = " + nNotes)
       n1 = xArray[0]
       n2 = xArray[1]
       n3 = xArray[2]
       Print("Number of notes = " + Size(xArray) + "    " + n1  + " " + n2 + " " + n3)
    SendNow(m)
    nNotes = 0
End

End

On NoteOffEvent(m : NoteMessage)

SendNow(m)
NoteTracker_Clear(nt)
      
ClearArray(xArray)
nNotes = 0

End

image

I think you started to learn GPScript trying to do things that are still too complicated for you. Could you first try to write a function which creates a string containing the notes of a NoteTracker? It is both a good exercise and something you will need for debugging, as printing this string will display the content of a NoteTracker.

I am printing the note numbers played :slight_smile:

Print(" 44444 Number of notes = " + Size(xArray) + " " + n1 + " " + n2 + " " + n3 + " " + n4 + " " + n5)

I could easily convert note values to string values by indexing into a parallel string array with a note value.

Isn’t there a function that will put all notes played into an array?

It seems that my program as written only captures one note at a time and I need to capture all the notes played. Otherwise, it detects a 3 note chord before I get to a 4 note chord.

I did find some interesting functions that I intend to use once I get across my basic obstacle:

MakeNoteMessage(number: Integer, velocity: Integer) Returns NoteMessage
Transpose(m: NoteMessage, steps: Integer) Returns NoteMessage
WithNoteNumber(m: NoteMessage, number: Integer) Returns NoteMessage
WithNoteNumberAndVelocity(m: NoteMessage, n: Integer, v: Integer) Returns NoteMessage
WithTranspose(m: NoteMessage, steps: Integer) Returns NoteMessage
WithVelocity(m: NoteMessage, v: Integer) Returns NoteMessage

How exactly would you distinguish these….remember that there is no concept of a chord in the MIDI world….remember that you’re running in real time so you can’t really wait to see if any more notes are coming.

That’s the concept of NoteTracker:

Var
  nt            : NoteTracker;
  notifyChord   : Boolean = false;  
  timelapse     : double = TimeSinceStartup();
  // adjust this delay if necessary
  analysisDelay : double = 10.0;
  
Initialization
  SetTimersRunning(true);
End

Function DS_NoteTracker_GetStringOfNotes(nt : NoteTracker) Returns string
Var
  i            : Integer;
  nt_heldNotes : Integer Array = nt.NoteTracker_GetHeldNotes();
  stringOfNotes : string = "";
  
  For i=0; i<nt_heldNotes.Size(); i=i+1 Do
    stringOfNotes = stringOfNotes+NoteNumberToNoteName(nt_heldNotes[i])+"("+nt.NoteTracker_GetSpecificNoteOnCount(nt_heldNotes[i])+") - ";
  End
  result = stringOfNotes;
End

On NoteEvent(m : NoteMessage)
  SendNow(m);
  nt.NoteTracker_GotNote(m);

  Print("Number of different notes played : "+nt.NoteTracker_NoteOnCount() );
  Print(nt.DS_NoteTracker_GetStringOfNotes());
  Print("");    
  
  If nt.NoteTracker_NoteOnCount() >= 3
  Then 
    timelapse = TimeSinceStartup()+analysisDelay;
    notifyChord = true;
  Else
    notifyChord = false;
  End    
End

On TimerTick(ms : double)
 If notifyChord && nt.NoteTracker_NoteOnCount() >= 3 && ms > timelapse
 Then
   Print("");
   Print("*** "+nt.NoteTracker_NoteOnCount()+"-notes chord playing ***");
   Print("");
   notifyChord = false;
 End
End

NoteTracker_test.gig (14.0 KB)

image

I couldn’t test this with a MIDI keyboard controller, but it could possibly work :grimacing:

1 Like

“RealTime” Exactly! This is my problem!. … but looking further ahead it appears that @David-san may have solved this difficult problem. It really looks pretty good. I will check it out this evening.

Your code looks like it is right on the money - especially by introducing the time element! You may have very well solved one of the seemingly impossible problems! The reason that I was struggling with this effort was because as Dhj had denoted, “MIDI is realtime” … so you have access to only one MIDI event at a time and therefore you don’t see multiple MIDI notes in one single event.

Now, that you may have solved this problem, the sky is the limit for me to code → EG: Here is a list of related projects that I intend to implement using Scriptlets:

 1)  Change boring closed voiced chords to open piano voiced chords.  The is mainly directed to MIDI Accordion players that are currently restricted to the left hand chords they play. Since you have introduced a time element that I will use, I will be able to allow them to play 9th, 11th, 13th and poly chords. I already know the algorithms to detect the root note of a chord, so I can do all kinds of magical tricks. MIDI Accordionists can play to chord notes simultaneously, however if they play for instance a CM and BbM simultaneously, the sound would be very cacaphonous.  However, I will be able to catch this scenario in the Sciptlet and adjust the BbM up one octave thus creating a C11th. Voila!

 2) Setting up various guitar arpeggios specified by widgets. Piece of cake.

 3) Incorporate jazz harmoinc modes triggered again by widgets.  Again, I know how to do this based on teachings by Dave Brubeck and Kent Hewitt.

 4) Take played notes in a chord and spread them over various MIDI channels EG: Create a more true sounding brass section.  Then of course randomize this based on velocity.

 5) Trigger notes based on zone and then also on velocity to do various things as specified by widgets

 6) Create an ultra-realistic banjo effect and as well as the perfect harp effect. My friend Ray Cavicchio had done this in 1980 with his invention the Cavichord. No one has ever come close to this.  I know the algorithms and I will implement them with GPSCript.

Once I get going there will be no stopping me. LOL! Thank you GPscript and the GP community :slight_smile:

1 Like

Be careful that the sky doesn’t fall on your head! :cloud_with_lightning_and_rain: :wink:

I tried to give you a compliment. I should have known better :roll_eyes:

2 Likes

Thanks for the compliment, I don’t deserve it. :wink::+1:

People react differently to compliments, this one is hilarious, for example: Joaquin Phoenix does not care at all - YouTube

:slight_smile:

The most important thing is that you solved your problem :beers:

Phil, please don’t be upset.
I really don’t think, @David-san wanted to offend you in any way - he wrote his line with a :wink: and he is a very friendly and helpful guy.
I guess, most probably this phrase “to be afraid of the sky falling on our heads” is a quote from a comics series called “Asterix the Gaul” which is very poular in France (where David comes from) and also in Germany (where i come from). The stories are about a tribe of Gauls which are smart, strong and mostly fearless - except from one thing: the sky could fall on their heads.
…at least this is what first came to my mind when i read it.

3 Likes

I totally was reminded to Asterix and like that super funny comment :wink:

Humor can become difficult when there is no common basis for a jestery… and this is even more difficult for internet conversations when you can’t read the face expression of your conversation partner or hear them chuckle. :wink: :beers:

I know - we have the same problem in Germany.
The Bavarian sense of humour is different from Hamburg as an example.

But both do not talk that much as one coming from Köln.

1 Like

At least two Astérix lovers here :stuck_out_tongue_winking_eye::+1:

And I am sure @Phil understand my humour. If not I will try to explain peacefully:

image

2 Likes

:slightly_smiling_face:

It was really genius of you introducing the element of time to solve this linear-realtime problem. It really opens up a lot of doors for GPScripters wanting to pursue advanced MIDI-related scripts. Your technique should be added as an intrinsic GPscript function. :slight_smile:

3 Likes

Not sure exactly what you want built in? I just tried that scriptlet and as far as I can tell, it’s detecting how many notes are being held down (using the Note Tracker) - I’m not sure what the time checking is supposed to do - for example, if I press a C, wait two seconds, then add an E, wait two seconds and then add a G - it detects that’s a chord — but that isn’t really a chord — those three notes would have all needed to have been played within the threshold time to be recognized as a chord.