Skip to content

Commit

Permalink
Add --ticks and --duration options.
Browse files Browse the repository at this point in the history
  • Loading branch information
shoogle committed Jan 26, 2018
1 parent 2ed00ab commit e98807e
Showing 1 changed file with 46 additions and 23 deletions.
69 changes: 46 additions & 23 deletions midicsv-process.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import numpy
import sys
import subprocess
import argparse

noteLetters = ["C","C","D","D","E","F","F","G","G","A","A","B"]
sharps = [ "","#", "","#", "", "","#", "","#", "","#", ""]
Expand All @@ -12,7 +13,7 @@ class NoteEvent:
tick = 0
pitch = 64
velocity = 127

def __init__(self, track, tick, pitch, velocity):
self.track = track
self.tick = tick
Expand All @@ -25,35 +26,35 @@ class Note:
pitch = 64
velocity = 127
duration = 480

def __init__(self, noteEvent_on, noteEvent_off):
self.track = noteEvent_on.track
self.tick = noteEvent_on.tick
self.pitch = noteEvent_on.pitch
self.velocity = noteEvent_on.velocity
self.duration = noteEvent_off.tick - noteEvent_on.tick

def onTimeMicros(self, tempoMap):
return tempoMap.microsAtTick(self.tick)

def durationMicros(self, tempoMap):
return tempoMap.microsAtTick(self.tick + self.duration) - self.onTimeMicros(tempoMap)

def octave(self):
return (self.pitch / 12) - 1

def letter(self):
return noteLetters[self.pitch % 12]

def sharp(self):
return sharps[self.pitch % 12]

def fullNote(self):
return "%s%s" % (self.letter(), self.sharp())

def fullNoteOctave(self):
return "%s%s%s" % (self.letter(), self.octave(), self.sharp())

def toString(self, tempoMap):
return "%s,%s,%s,%s,%s,%s,%s,%s" % (\
self.tick,
Expand All @@ -73,28 +74,38 @@ class TempoEvent:
class TempoMap:
tpqn = 480 # ticks per quarter note
tmap = []

def addTempo(self, tick, tempo):
tempoEvent = TempoEvent()
tempoEvent.tick = tick
tempoEvent.tempo = tempo
tempoEvent.micros = self.microsAtTick(tick)
self.tmap.append(tempoEvent)

def tempoEventAtTick(self, tick):
savedTempoEvent = TempoEvent()
for tempoEvent in self.tmap:
if tempoEvent.tick > tick:
break
savedTempoEvent = tempoEvent
return savedTempoEvent

def microsAtTick(self, tick):
tempoEvent = self.tempoEventAtTick(tick)
return tempoEvent.micros + ((tick - tempoEvent.tick)*tempoEvent.tempo)/self.tpqn

parser = argparse.ArgumentParser()

parser.add_argument("files", nargs='+', help="path to input files")

modes = parser.add_mutually_exclusive_group()
modes.add_argument("-t", "--ticks", action="store_true", help="print total ticks for the file")
modes.add_argument("-d", "--duration", action="store_true", help="print total duration of the file in seconds")

args = parser.parse_args()

rows = []
for file in sys.argv[1:]:
for file in args.files:
extension = file.split(".")[-1].lower()
if extension == "csv":
print >> sys.stderr, "File: " + file
Expand All @@ -110,6 +121,16 @@ def microsAtTick(self, tick):
except:
print "Couldn't open '" + file + "'. Does it exist? Is midicsv installed?"
continue
elif extension == "mscx" or extension == "mscz":
print >> sys.stderr, "File: " + file + " (via mscore and midicsv)"
try:
tmpFile = "tmp-" + file + ".mid"
subprocess.call(["bash", "-c", "mscore " + file + " -o " + tmpFile + " &>/dev/null"])
rows = subprocess.check_output(["midicsv", tmpFile ]).splitlines()
subprocess.call(["rm", tmpFile])
except:
print "Couldn't open '" + file + "'. Does it exist? Is mscore and midicsv installed?"
continue
else:
print >> sys.stderr, "Ignoring: " + file + " (not a MIDI or CSV file)"
continue
Expand Down Expand Up @@ -147,12 +168,14 @@ def microsAtTick(self, tick):
# sort notes by onTick
notes = [x for (y,x) in sorted(zip(onTicks,notes))]
onTicks.sort()
rank = 0
prevTick = onTicks[0]
print "start_ticks,start_secs,dur_ticks,dur_secs,pitch,fullNoteOctave,velocity,part"
for i, note in enumerate(notes):
tick = onTicks[i]
if tick != prevTick:
rank += 1
print note.toString(tempoMap) # + "," + str(rank)
prevTick = tick
if args.ticks or args.duration:
finalNote = notes[-1]
finalTick = finalNote.tick + finalNote.duration
if args.ticks:
print finalTick
elif args.duration:
print tempoMap.microsAtTick(finalTick)/1000000.0
else: # print everything
print "start_ticks,start_secs,dur_ticks,dur_secs,pitch,fullNoteOctave,velocity,part"
for i, note in enumerate(notes):
print note.toString(tempoMap)

0 comments on commit e98807e

Please sign in to comment.