# Double or halve all durations (notes, rests and time signatures) # Created by: .m.i.r.o. # Changes log: # 2015-05-08 - initial version # 2015-06-26 - added code for ( were already handled) # 2015-08-13 - added code for # # USAGE: # # gawk -f _durationDH.awk -v mode=value < score.mcsx # # -v mode=value # # mode= (synonyms: m= mx=), default: 2 # double or 2 or d -> double all durations # half or 0.5 or 1/2 or h -> halve all durations # # Examples: # # gawk -f _durationDH.awk -v mx=2 < score.mscx > newscore.mscx # gawk -f _durationDH.awk -v m=double < score.mscx > newscore.mscx # gawk -f _durationDH.awk -v mode=d < score.mscx > newscore.mscx # gawk -f _durationDH.awk -v mx=0.5 < score.mscx > newscore.mscx # gawk -f _durationDH.awk -v mode=0.5 < score.mscx > newscore.mscx # gawk -f _durationDH.awk -v mode=1/2 < score.mscx > newscore.mscx # gawk -f _durationDH.awk -v m=half < score.mscx > newscore.mscx # gawk -f _durationDH.awk -v m=half < score.mscx > newscore.mscx BEGIN { mode = tolower(mode) if (m != "") { mode = tolower(m) } if (mx != "") { mode = tolower(mx) } mx = mode + 0 if (mode == "double") { mx = 2 } if (mode == "d") { mx = 2 } if (mode == "" ) { mx = 2 } if (mode == "half" ) { mx = 0.5 } if (mode == "h" ) { mx = 0.5 } if (mode == "1/2" ) { mx = 0.5 } if (mx != 2 && mx != 0.5) { print "ABORTED: invalid parameter specified - \"" mode "\"" > "/dev/stderr" exit } # Keep track of the current position. # This is only needed to provide exact location of a unsupported duration type staff = 0 measure = 0 # indicate that chord or rest has started chord = 0 rest = 0 repeatmeasure = 0 chordTupledID = 0 durationType = "" tuplet = 0 # populate lookup table with note (rest) duration types maxIdurationType = split("128th,64th,32nd,16th,eighth,quarter,half,whole,breve,long", aDurationType, ",") maxItickLengths = split("15,30,60,120,240,480,960,1920,3840,7680", aTickLengths, ",") if (maxIdurationType != maxItickLengths) { print "FATAL: data arrays are incompatible." > "/dev/stderr" exit } # add whole measure rests aDurationType[0] = "measure" aTickLengths [0] = -1 } # durationType = "measure", "breve", "whole" etc. # mx = 2 (=> *2 ) or 0.5 (=> /2) function GetDuration(durationType, mx) { if (mx == 2) direction = +1 else direction = -1 for (i = 0; i <= maxIdurationType; i++) { if (aDurationType[i] == durationType) break; } if (i == 0) { direction = 0 } else { if (i > maxIdurationType || i+direction > maxIdurationType || i+direction < 1) { direction = 0 print "WARNING: unsupported duration - \"" durationType "\", Measure " measure ", Staff " staff > "/dev/stderr" } } dT = aDurationType[i+direction] return dT } /^ +(.*)<\/programVersion>/ { programVersion = gensub(/(.*)(.*)(<\/programVersion>.*)/,"\\2","g") if (substr(programVersion,1,2) != "2.") { print "FATAL: only scores created with MuseScore version 2.x are supported: " FILENAME > "/dev/stderr" exit } } # ----------------------------------------------------------------------------------------- /^ +/ { staff = gensub(/(.*.*)/,"\\2","g") } /^ +<\/Staff>/ { staff = 0; measure = 0 } # ----------------------------------------------------------------------------------------- /^ +/ { measure = gensub(/(.*.*)/,"\\2","g") } /^ +<\/Measure>/ { measure = 0 } # ---------------------------------------------------------------------------------------- # for calculating chord durations - assuming tuplet chords appear directly after atuplet definition /^ +/ { tuplet = gensub(/(.*.*)/,"\\2","g") } /^ +[0-9]+<\/normalNotes>/ { if (tuplet > 0) { normalNotes = gensub(/(.*)(.*)(<\/normalNotes>.*)/,"\\2","g") # $0 = gensub(/(.*)(.*)(<\/normalNotes>.*)/,"\\1" normaNotes "\\3","g") } } /^ +[0-9]+<\/actualNotes>/ { if (tuplet > 0) { actualNotes = gensub(/(.*)(.*)(<\/actualNotes>.*)/,"\\2","g") # $0 = gensub(/(.*)(.*)(<\/actualNotes>.*)/,"\\1" actualNotes "\\3","g") } } /^ +.+<\/baseNote>/ { if (tuplet > 0) { baseNote = gensub(/(.*)(.*)(<\/baseNote>.*)/,"\\2","g") $0 = gensub(/(.*)(.*)(<\/baseNote>.*)/,"\\1" GetDuration(baseNote,mx) "\\3","g") } } /^ +<\/Tuplet>/ { tuplet = 0 } # --------------------------------------------------------------------------------------- /^ +/ { TimeSig = 1 } /^ +[0-9]+<\/sigN>/ { if (TimeSig > 0) { sigN = gensub(/(.*)(.*)(<\/sigN>.*)/,"\\2","g") if (mx == 2 && n % 2 != 0) $0 = gensub(/(.*)(.*)(<\/sigN>.*)/,"\\1" sigN*mx "\\3","g") } } /^ +[0-9]+<\/sigD>/ { if (TimeSig > 0) { sigD = gensub(/(.*)(.*)(<\/sigD>.*)/,"\\2","g") if (mx == 0.5 || n % 2 == 0) $0 = gensub(/(.*)(.*)(<\/sigD>.*)/,"\\1" sigD/mx "\\3","g") } } /^ +<\/TimeSig>/ { TimeSig = 0 } # / -------------------------------------------------------------------------------- /^ +/ { chord = 1 } /^ +/ { rest = 1 } /^ +/ {repeatmeasure = 1} /^ +.*<\/durationType>/ { if (chord > 0 || rest > 0) { durationType = gensub(/(.*)(.*)(<\/durationType>.*)/,"\\2","g") $0 = gensub(/(.*)(.*)(<\/durationType>.*)/,"\\1" GetDuration(durationType,mx) "\\3","g") } } /^ +/ { if (chord > 0 || rest > 0 || repeatmeasure > 0) { z = gensub(/(.*.*)/,"\\2","g") n = gensub(/(.*.*)/,"\\4","g") if (mx == 2 && n % 2 != 0) $0 = gensub(/(.*.*)/,"\\1" z*mx "\\3\\4\\5","g") if (mx == 0.5 || n % 2 == 0) $0 = gensub(/(.*.*)/,"\\1\\2\\3" n/mx "\\5","g") } } /^ +<\/Chord>/ { chord = 0 } /^ +<\/Rest>/ { rest = 0 } /^ +<\/RepeatMeasure>/ {repeatmeasure = 0} # ----------------------------------------------------------------------------------------- /^ +[0-9]+<\/ticks>/ { ticks = gensub(/(.*)(.*)(<\/ticks>.*)/,"\\2","g") $0 = gensub(/(.*)(.*)(<\/ticks>.*)/,"\\1" mx*ticks "\\3","g") } # ----------------------------------------------------------------------------------------- /^ +[0-9]+<\/tick>/ { tick = gensub(/(.*)(.*)(<\/tick>.*)/,"\\2","g") $0 = gensub(/(.*)(.*)(<\/tick>.*)/,"\\1" mx*tick "\\3","g") } # Output ------------------------------------------------------------------------------------------ { print } END {}