gnmidiscript script language is an extension of gnscript with functions, constants, object types to analyse, modify, create MIDI files
This file describes the syntax elements and functions that are added for handling MIDI file access only. The basic script language elements are described in gnscript project.
MidiSong is a structure that keeps optional file name of a song and loaded song info
the structure contains only the fields (no remove, no insert):
filename a string
events a vector of MidiEvent objects
Hint: modifying tempo or tact inside for or foreach events loop is critical.
it causes that the times of all events are calculated again and resorts the order of events by time.
Use setautoupdatetimes() function to turn off/on this behaviour while working in the loop.
MidiEventList is a vector of MidiEvent objects.
It allows to insert, remove and modify elements.
MidiEvent
The MidiEvent structure object allows to get or modify information from different kind of event types. The MidiEvent object here allows to access every existing field from any of these types (no casting required but if getting a field that does not exist will result in a runtime error)
MidiEvent can have following structure keys that are strings
type (delivers null object for null Midi Event object)
program
programname
note
notename
text
key
polykey
sysex
meta
MidiEvent can have following structure keys that are numbers
hint: when setting startunit, endunit, starms, endms exception may occur if the new value causes end < start . Use setnotetimes or setnoteunits for setting both values at same time.
LIVE VARIABLES
live variables are global variables that are dynamic
midicompression
this live variable (long) gets or sets MIDI compression. Live variable means that when the program changes the value the variable also changes and same in other direction.
it must have the values of constants MIDI_COMPRESSION_NONE,MIDI_COMPRESSION_MEDIUM,MIDI_COMPRESSION_FULL
FUNCTIONS
newsong(version,resolution)
midiload(filename,combineoption)
midisave(&song,filename)
deleteevent(&song,index)
after deleting you should call song.compact() or check before accessing events (isnullevent() or event.type == "" or event.eventindex() == -1)
collectevents(&song,andfieldname,andoperator,andfieldpattern,...)
e.g. find all notes with channel == 10 requires triple parameters like collectevents("channel","==","10","type","=",EVENTTYPE_NOTE)
findfirstevent(&song,andfieldname,andoperator,andfieldpattern,...)
e.g. find first note in channel 10 requires triple parameters like collectevents("channel","==","10","type","=",EVENTTYPE_NOTE)
compact(&song)
eventindex(&event)
event2string(&event)
inserttempo(&song,index,startunit,microsecperbeat)
inserttact(&song,index,startunit,nomin,demon)
inserttext(&song,index,track,startunit,texttype,text)
insertprogram(&song,index,track,channel,startunit,programnumber)
insertcontrol(&song,index,track,channel,startunit,controlnumber,controlvalue)
insertnotestart(&song,index,track,channel,startunit,note,vel)
-- deprecated: better use insertnote(&song,index, notestructure)
insertnoteend(&song,index,track,channel,endunit,note,veloff,...)
-- deprecated: better use insertnote(&song,index, notestructure)
insertnote(&song,index,track,channel,startunit,endunit,note,vel)
-- deprecated: better use insertnote(&song,index, notestructure)
insertnote(&song,index,track,channel,startunit,endunit,note,vel,veloff)
-- deprecated: better use insertnote(&song,index, notestructure)
insertnote(&song,index, notestructure)
notestructure can be { track: tracknr, channel: channelnr, startunit: optionalstartunit, endunit: optionalendunit, note: notename, velocity : optionalvelocityon, velocityoff: optionalvelocityoff)
parsenotename(notename)
convert a note name to a note number 0-127 if note name is valid and known (else -1)
getnotename(notenumber)
convet a note number to note name
insertpitchbend(&song,index,track,channel,startunit,pitchbend)
insertaftertouch(&song,index,track,channel,startunit,aftertouch)
insertpolyaftertouch(&song,index,track,channel,startunit,polykey,polyvalue)
insertkey(&song,index,track,channel,startunit,key)
insertsysex(&song,index,track,startunit,sysex)
insertmeta(&song,index,track,startunit,metatype,meta)
insertrealtime(&song,index,track,startunit,realtimeevent,realtimeparam)
insertendtrack(&song,index,track,startunit)
insertmeasure(&song,barnr,newtactnom, newtactdemom)
insert a new empty measure with given tact e.g. 3/4
insertmeasure(&song,barnr,newtactnom, newtactdemom,barcount)
insert a some empty measures with given tact e.g. 3/4
moveevent(&event,newindex)
copyevent(&event,newindex)
copyevent(&event,&newsong,newindex)
duplicatechannel(&song,channel,newchannel,delayunits)
duplicate all events of a channel to a new channel with some units position difference
duplicatechannel(inputfilename,outputfilename,channel,newchannel,delayunits)
setnotetimes(&event,startms,endms)
setnoteunits(&event,startunit,endunit)
timeat(&song,unit)
unitat(&song,ms)
tempoat(&song,unit)
bpmat(&song,unit)
bpm2microsecperbeat(bpm)
microsecperbeat2bpm(microsecperbeat)
setautoupdatetimes(&song,autoupdatetimes)
getautoupdatetimes(&song)
updateeventtimes(&song)
updatetimetable(&song)
tactat(&song,unit)
tactlength(&song,nom,denom)
measurelength(&song,measurenr)
measureatunit(&song,unit)
posatunit(&song,unit)
unitatmeasure(&song,measurenr)
unitatmeasure(&song,measurenr,beatnr)
unitatmeasure(&song,measurenr,beatnr,tick)
midiposition(&song,positiontext)
supports time and unit and bar position e.g. 0:30 is 30 seconds after beginning of song,
error if invalid syntax,
result is midi unit for given song
barunits(&song)
lastunit(&song)
gettrackcount(&song)
getfirsttrackforchannel(&song, channel)
find a track number that already uses channel
getresolution(&song)
getversion(&song)
loadbestchords(&song)
loadchords(&song)
loadchords(&song,format)
removechords(&song)
removechords(&song,format)
ischordevent(event,onlysafetextchords)
identify chord event, for text onlysafetextchords decides if probably lyrics are probably not chords e.g. Am
isnullevent(event)
a song might contain null events where events have already been deleted
removefade(&song)
containsfadein(&song)
containsfadein(&song,&fadeinfo)
containsfadeout(&song)
containsfadeout(&song,&fadeinfo)
miditool(commandline)
e.g. midicat, midi1to0, miditrim, midi2txt, txt2midi, ...
initialisecontrol(&song,channel,controlnr)
inserts a control of given controlnr with default control value if there is no such control before first note in channel
initialiseprogram(&song,channel)
inserts a program change with default program value (0, grand piano) if there is no program change before first note in channel
initialisechannelsettings(&song, channel)
inserts channel setting commands with default values if such commands are missing before first note in channel
guesskey(midifilename)
returns number of # signs or b signs (signs >= 0 means # signs < 0 means b)
songkeyname(signs,minor)
e.g. signs == 0 returns song key "C"
keysigns(key)
returns number of # signs or b signs (information stored in song) (signs >= 0 means # signs < 0 means b)
keysigns(key,&minor)
returns signs and sets boolean variable minor (signs >= 0 means # signs < 0 means b)
couldbechordname(text)
e.g. Am, C, G7, Bb, D#,...
issafetextchordname(text)
e.g. "Am " is no safe chord
istextchord(text)
e.g. [Cm7]
ischordevent(event)
quantise(&song,posbase,lenbase)
e.g. quantise to base 1/16, all channels
quantise(&song,posbase,lenbase,channels)
e.g. quantise to base 1/16, channel list as string e.g. 1-9, 11-16
quantisebase(&song,notelen)
e.g. notelen 1/16
unescapetext(escapedtext)
when using commandline with macro %escapetext(text) then unescapetext(escapedtext) can be used for easier getting back original text
deletepauses(&song,fromunit,units)
deletepauses(&song,fromunit,units,deleteemptynotes)
deletepauses(&song,vectorunitranges)
unitrange is structure fromunit, units
deletepauses(&song,vectorunitranges,deleteemptynotes)
comparemidi(&midisong1, &midisong2)
comparemididetail(&midisong1, &midisong2)
comparemididetail(&midisong1, &midisong2, filename1)
comparemididetail(&midisong1, &midisong2, filename1, filename2)
equalevents(&event1, &event2)
equalevents(&event1, &event2,ignoretrackno)
equalevents(&event1, &event2,ignoretrackno,ignoretiming)
getmetatypename(metatypenumber)
returns the name of the metatype number e.g. 3 => "Trackname"
getmetatypenumber(metatypename)
returns the number of the meta type name e.g. "trackname" => 3
ischannelpolyphone(&song, channel, minnotesoverlapping)
finds a note that plays at same time with other notes
ischannelpolyphone(&song, channel)
finds a note that plays at same time with an other note (minnotesoverlapping=2)
__GNMIDISCRIPTVERSION__()
return version string e.g. 1.0
__USEGNMIDISCRIPTVERSION__(version)
error if version e.g. 1.0 is older than CURRENTGNMIDISCRIPTVERSION
setStatusbarText(shortmsg)
only usable when application has statusbar control
dumpevents(&song)
get all song data as text string
dumpevents(&song,firstindex,lastindex)
get some events of song between index firstindex and lastindex (inclusive) as text string
replaceprogrambank(&song, channels, oldprog, oldbankmsb, oldbanklsb, newprog, newbankmsb, newbanklsb)
find old program/bank in given channels of a song and replace it with a new program/bank
getprogrambankranges(&song,channel,track)
find areas with sound addresses in song at channel and track
getprogrambankranges(&song,channel)
find areas with sound addresses in song at channel
setprogrambank(&song, channel, track, startunit, endunit, prog, bankmsb, banklsb)
set a program/bank address in channel and track from position startunit till endunit
findmatchingsoundaddress(&song, channel, addresspattern)
find soundaddress in a channel of a song and return a vector of event indices (indexlist) for the program and bank events used,
addresspattern is a structure { program: 3, msbbank : 0, lsbbank: -1} where bank numbers -1 are matching any bank address
replacesoundaddress(&song, channel, addressreplace, &indexlist)
replace the found sound addresses in indexlist by a new sound address