I expect the array notesInKey to be equal to the array modeOffsets, however, I get an error message:
“Semantic error: Line 26, Col 5: Types are not compatible”
Absolutely. GP Script was very much inspired by the Pascal/Algol world. I even thought about using the term procedure when the “function” didn’t return anything. I still could allow it
On the same subject, how do you prefer the use of global versus local variables?
I see myself resorting to both: why return a value from a function if you can also change the global variable (which you would be returning it to) inside the function, directly?
Var modeOffsets, notesInKey : integer array
function csort(a : Integer Array) returns integer array
var at : Integer Array
at = a
Sort(at, true)
result = at
end
Initialization
modeOffsets = [0, 2, 4, 5, 7, 9, 11]
notesInKey = csort(modeOffsets)
End
Functions should generally not modify global variables unless there’s no choice. Unfortunately, GPScript does not yet have scoping rules as local as I would like.
Now I think of it, how do you define that the input to the function is to be modified?
Would you write something like this?
Function removeIndex(someArray : Integer Array, index : Integer) returns Integer Array
// Removes data at any index from array
var i : Integer
For i = index; i < Size(someArray) - 1; i = i + 1 Do
someArray[i] = someArray[i+1] // Move remainder data 1 index lower
End
result = RemoveLast(someArray)
End
This is one of those cases where I’m cautious to simply try.
I think that is not possible as the parameter is only a value and not the object itself.
GP script is not C where you can give a pointer to the original object as a parameter.
I left the body of the function commented out and only left the function definition (and its End) in place and the function call later in the code removeIndex(a, b).
The error message was
Semantic error: Line 164, Col 9: No assignment found for function that returns a value
After trying to return the original array it became
Semantic error: Line 165, Col 9: No assignment found for function that returns a value
So now I got it as
Function removeIndex(someArray : Integer Array, index : Integer)
// Removes data at any index from array
var i : Integer
For i = index; i < Size(someArray) - 1; i = i + 1 Do
someArray[i] = someArray[i+1] // Move remainder data 1 index lower
End
// result = RemoveLast(someArray)
RemoveLast(someArray)
End
Mind you, still commented out the meat and potatoes. But now I can debug the rest of my code without worrying about this part.
Do you recommend to define it as a function that returns an array and assign it to the same variable with which it was called?
Currently, arrays (and other non-primitive types) are passed as “call by ref” so parameter arguments of these types can be directly modified in a function.
If you don’t want the array itself modified in a function, assign it to a local variable inside the function and do the work there.
At some point it may make sense to have some more built-in functions (like sort) for operations such removing elements. What is the use case for this kind of function, i.e, what are you trying to accomplish that you need to be able to remove parts of an array
Also, I would note that removeIndex is a very misleading function name since, from looking at what you wrote, this should be called removeElementAtIndex
You are correct about the name, it is misleading. I like your suggestion better.
The script keeps track of the notes I’ve enabled, i.e. triads in a programmable inversion, based on a single root note. So when I modify the inversion between the root note’s NoteOn and NoteOff, I disable the wrong chord notes (except for the root) and the original third and fifth remain on.
Also, if I enable a C major triad and subsequently an E minor triad (before releasing the C) I get a Cmaj7, where the E and G are enabled again. If I then release the C, all notes of its triad are released (C-E-G) and only the B remains on. I’d prefer, that in that case only the C is released and the Em (E-G-B) remains on.
For bookkeeping, the note numbers of each NoteOn event and the (then valid) inversion are stored in two arrays (noteOnEvents and inversionEvents). When a key is released, its note is necessarily in the noteOnEvents array (as far as I know it is not possible to receive a NoteOff message without having received the corresponding NoteOn message, first).
I find its index with IndexOf() and use it to recover the corresponding inversion, such that the correct chord notes are released. This happens conditionally, see the C and Em example above. Next, the event must be deleted from the noteOnEvents and inversionEvents arrays, otherwise the arrays would overflow after 128 NoteOn events, and what’s worse the same NoteOn may occur multiple times with different inversions.
I realize that what I’m doing is probably already supported in some way by the NoteTracker, but I couldn’t find information about it.