// (c) Günter Nagler 2025 GNMIDI script
//
// this script contains functions for copying a part of a midi file to an other position
// do not use it for copying setup measure at beginning of song (this part should only be once in a midi file)
// do not copy to a position before setup measure (near begin of song) if it contains MIDI reset initialisations
// call function copyunits instead if you want to copy an units range part
function copyunits(fromunit, tillunit, insertatunit)
{
if (tillunit <= fromunit)
throwexception("error: tillunit must be greater than fromunit");
var copiedunits = tillunit - fromunit;
var moverangelistunits = insertatunit - fromunit;
var movelaterunits = +copiedunits;
var rangelist = song.collectevents("startunit", ">=", fromunit, "startunit", "<", tillunit);
var laterlist = song.collectevents("startunit", ">=", tillunit);
foreach (var ev in laterlist)
{
if (ev.type == EVENTTYPE_HEADER)
continue;
if (ev.hasend)
ev.setnoteunits(ev.startunit + movelaterunits, ev.endunit + movelaterunits);
else
ev.startunit += movelaterunits;
}
var duplicatelist;
foreach (var ev in rangelist)
{
if (ev.type == EVENTTYPE_HEADER)
continue;
if (ev.type == EVENTTYPE_TEXT) println("orig: ",ev.event2string());
var dupev = ev.copyevent(song, song.events.size());
if (dupev.hasend)
dupev.setnoteunits(ev.startunit+moverangelistunits, ev.endunit + moverangelistunits);
else
dupev.startunit += moverangelistunits;
if (dupev.type == EVENTTYPE_TEXT) println("new: ",dupev.event2string());
dupev.copyevent(song,song.events.size());
}
}
function copymeasures(fromnr, count, insertbeforenr) // do not use fromnr value 1
{
if (count <= 0)
throwexception("error: invalid measure count used");
if (fromnr <= 0)
throwexception("error: invalid fromnr (used must be 1 or higher)");
if (insertbeforenr <= 0)
throwexception("error: invalid insertbeforenr (used must be 1 or higher)");
var fromunit = song.unitatmeasure(fromnr);
var tillunit = song.unitatmeasure(fromnr + count);
var insertatunit = song.unitatmeasure(insertbeforenr);
copyunits(fromunit, tillunit, insertatunit);
}
var copyfrommeasurenr = 9; // change this to a value greater than 1
var copymeasurecount = 3; // change this to a value greater than 0
var copytobeforemeasurenr = 12; // change this to a value greater than 1
copymeasures(copyfrommeasurenr, copymeasurecount, copytobeforemeasurenr);
// (c) Günter Nagler 2025 GNMIDI script
// the script calculates song duration and writes file name and duration into GNMIDI logfile if duration is longer than value of longerthanseconds variable
// it does not produce a midi file output
var longerthanseconds = 3 * 60; // replace 3 against a minutes number or 3 * 60 against a seconds number
var durms = song.timeat(song.lastunit());
if (durms > longerthanseconds*1000)
logmessage(input, " is longer: ", time2shorttext(seconds2time(durms/1000))); // result is in GNMIDI log file
lasttoolstate = "IGNORE";// do not produce output files
// (c) Günter Nagler 2025 GNMIDI script
//
// change tempo within a given range dynamically between firstbpm and lastbpm
// inserts tempo changes every stepunit (default: measure) if necessary
var firstunit = 0;
var lastunit = song.lastunit();
var firstbpm = 120;
var lastbpm = 40;
var stepunit = song.getresolution() * 4;
// bpm values must be in a correct range
if (firstbpm < 40)
firstbpm = 40;
if (firstbpm > 300)
firstbpm = 300;
if (lastbpm < 40)
lastbpm = 40;
if (lastbpm > 300)
lastbpm = 300;
var oldtempoevents = song.collectevents("type", "=", EVENTTYPE_TEMPO);
foreach (var ev in oldtempoevents)
{
song.deleteevent(ev);
}
var bpmatunit;
var curbpm = -1;
for (var unit = 0; unit < lastunit; unit+= stepunit)
{
// interpolate tempo
//(bpmatunit - firstbpm) / (lastbpm - firstbpm) = unit / lastunit;
bpmatunit = round(((lastbpm - firstbpm) * unit) / lastunit) + firstbpm;
if (curbpm == bpmatunit)
continue; // do not insert twice
song.inserttempo(1,unit,bpm2microsecperbeat(bpmatunit));
curbpm = bpmatunit;
}