Few GNMIDI operations use gnscript expressions to modify MIDI events (for experts only).
The current event can be modified or removed by one or more commands and conditionally.
gnscript language
https://www.gnmidi.com/gnscript.htm is a demo script interpreter with many script examples for learning programming. It is easier to learn programming by examples than by syntax.
There you can find the complete syntax of the script language.
Hint: gnscript language self does not contain MIDI support. GNMIDI and GNMIDI user tools use gnscript and a MIDI extension that supports MIDI file operations (e.g. variables song, ev, functions like midiload, midisave ...).
variables
song is a structure song information
song.filename a string
song.events a vector of MidiEvent objects
ev is a structure of event informations
ev.type can be
EVENTTYPE_NOTE
EVENTTYPE_PROGRAM
EVENTTYPE_CONTROL
EVENTTYPE_HEADER
EVENTTYPE_TEMPO
EVENTTYPE_TACT
EVENTTYPE_TEXT
EVENTTYPE_PITCHBEND
EVENTTYPE_AFTERTOUCH
EVENTTYPE_POLYAFTERTOUCH
EVENTTYPE_KEY
EVENTTYPE_SYSEX
EVENTTYPE_META
EVENTTYPE_REALTIME
EVENTTYPE_ENDTRACK
depending on the event type events have different attributes
ev.track track number (1,...)
ev.channel channel number (0 for no channel, 1-16)
ev.startunit MIDI unit where event started (0 is song start)
ev.endunit event EVENTTYPE_NOTE contains MIDI unit where note event finished (endunit must be greater or equal startunit)
ev.length event EVENTTYPE_NOTE contains note length in MIDI units (can also be 0)
ev.startms start time in milliseconds where event started (0 is song start)
ev.endms event EVENTTYPE_NOTE contains end time in milliseconds where note event finished
ev.duration event EVENTTYPE_NOTE contains note duration in milliseconds
ev.velocity event EVENTTYPE_NOTE contains note on velocity (1-127)
ev.velocityoff event EVENTTYPE_NOTE contains note off velocity (0-127)
ev.hasstart can be 0 when note on/off are not combined
ev.hasend can be 0 when note on/off are not combined
ev.iscombined 1 when note on and off are combined to a pair in the ev structure
ev.unitsperbeat event EVENTTYPE_HEADER contains MIDI resolution as units per beat
ev.version event EVENTTYPE_HEADER contains MIDI version 0, 1, 2
ev.trackcount event EVENTTYPE_HEADER contains number of MIDI tracks
ev.bpm event EVENTTYPE_TEMPO contains beats per minute tempo number
ev.microsecondsperbeat event EVENTTYPE_TEMPO contains microseconds per beat tempo number
ev.nomin event EVENTTYPE_TACT contains nominator of tact (e.g. 3 of 3/4)
ev.denom event EVENTTYPE_TACT contains denominator of tact (e.g. 4 of 3/4)
ev.texttype event EVENTTYPE_TEXT contains text type number
meta_text
meta_copyright
meta_trackname
meta_instrument
meta_lyric
meta_marker
meta_cuepoint
meta_programname
meta_devicename
ev.program event EVENTTYPE_PROGRAM contains program number (1,...)
ev.programname event EVENTTYPE_PROGRAM contains GM program name (1,...)
ev.note event EVENTTYPE_NOTE contains note number (0-127)
ev.notename event EVENTTYPE_NOTE contains note name
ev.controlnr event EVENTTYPE_CONTROL contains control number (0-127)
ev.ctrl_highbank
ev.ctrl_wheel
ev.ctrl_breath
ev.ctrl_foot
ev.ctrl_portamentotime
ev.ctrl_data
ev.ctrl_volume
ev.ctrl_balance
ev.ctrl_expression
ev.ctrl_effect1
ev.ctrl_effect2
ev.ctrl_slider1
ev.ctrl_slider2
ev.ctrl_slider3
ev.ctrl_slider4
ev.ctrl_lowbank
ev.ctrl_lowdata
ev.ctrl_hold
ev.ctrl_portamento
ev.ctrl_sustenuto
ev.ctrl_soft
ev.ctrl_legato
ev.ctrl_hold2
ev.ctrl_sound_variation
ev.ctrl_resonance
ev.ctrl_sound_release_time
ev.ctrl_sound_attack_time
ev.ctrl_xg_brightness
ev.ctrl_xg_portamento
ev.ctrl_reverb
ev.ctrl_tremolo
ev.ctrl_chorus
ev.ctrl_xg_effect4
ev.ctrl_phaser_level
ev.ctrl_datainc
ev.ctrl_datadec
ev.ctrl_lownrpn
ev.ctrl_highnrpn
ev.ctrl_lowrpn
ev.ctrl_highrpn
ev.ctrl_allsoundoff
ev.ctrl_allcontroloff
ev.ctrl_localkeyboard
ev.ctrl_allnotesoff
ev.ctrl_omnioff
ev.ctrl_omnion
ev.ctrl_mono
ev.ctrl_poly
ev.controlvalue event EVENTTYPE_CONTROL contains control value (0-127)
ev.text event EVENTTYPE_TEXT contains text
ev.key
ev.pitchbend event EVENTTYPE_PITCHBEND contains pitchbend number 0 is no pitchbend
pitch_center = 0
pitch_maxdown = -0x2000
pitch_maxup = 0x1fff
ev.aftertouch event EVENTTYPE_AFTERTOUCH contains aftertouch value
ev.polykey event EVENTTYPE_POLYAFTERTOUCH contains polyaftertouch key
ev.polyvalue event EVENTTYPE_POLYAFTERTOUCH contains polyaftertouch value
ev.key event EVENTTYPE_KEY contains key
ev.metatype event EVENTTYPE_META contains meta type value
meta_seqnumber
meta_prefixchannel
meta_prefixport
meta_endtrack
meta_tempo
meta_smpte
meta_meter
meta_key
ev.meta event EVENTTYPE_META contains meta data as hexadecimal string (values 00 - 7F)
ev.metadatalength event EVENTTYPE_META contains length of meta data in bytes
ev.realtimeevent event EVENTTYPE_REALTIME contains real time event number
event_songpos
event_songselect
event_tunerequest
event_clock
event_start
event_continue
event_stop
event_activesense
ev.realtimeparam event EVENTTYPE_REALTIME contains real time event parameter value
ev.sysex event EVENTTYPE_SYSEX contains sysex data as hexadecimal string (values 00 - 7F or F7)
sysex_GMReset = "7E 7F 09 01 F7"
sysex_GMExit = "7E 7F 09 02 F7"
sysex_GM2Reset = "7E 7F 09 03 F7"
sysex_GSReset = "41 10 42 12 40 00 7F 00 41 F7"
sysex_GSExit = "41 10 42 12 40 00 7F 7F 42 F7"
sysex_XGReset = "43 10 4C 00 00 7E 00 F7"
ev.sysexdatalength event EVENTTYPE_SYSEX contains sysex data length in bytes
Hint: constants listed above should be used e.g. if (ev.type == EVENTTYPE_CONTROL && ev.controlnr == ctrl_volume) ev.controlvalue = 127;
Important: many of those event parameters can only be accessed when the current MIDI command has a compatible event type e.g. ev.velocity is only available for notes ev.type == EVENTTYPE_NOTE and else the script aborts with an error. Therefore restrict in the condition the command type e.g. ev.type == EVENTTYPE_NOTE && ev.velocity >= 80
assignment operators
= assignment of a value e.g. ev.controlvalue = 127
+= increment by value e.g. if (ev.controlvalue + 10 <= 127) ev.controlvalue += 10;
+= appending a string e.g. ev.text += "\n";
-= decrement by value
*= multiplication by value e.g. if (ev.type == EVENTTYPE_TEMPO) ev.bpm *= 2;
/= division by value
Functions (more can be found in gnscript package)
random(maxvalue) a random value between 0 and maxvalue-1 e.g. ev.controlvalue += random(5);
replace(text, pattern, against) replace all occurrences of pattern inside text by against e.g. text.replace('(c)', 'copyright');
text.index(subtext) first position of subtext inside text or -1 if not found
text.toupper() change all characters a-z to A-Z
text.tolower() change all characters A-Z to a-z
text.mid(pos, len) get part of text beginning at index pos and maximum length len
text.left(len) get part of text from beginning with maximum length len
match(text,regex, options) match text against regular expression
substitute(text, regex, against,options) replace parts of text matching a regular expression regex by against e.g. text.substitute('hel.*o', 'HELLO', 'gi');
round(value)
song.deleteevent(ev.eventindex()) deletes event ev