From d59e5fdb05afe7a9bc73ab8bbf1f44cf4777238c Mon Sep 17 00:00:00 2001
From: Grissess <grissess@nexusg.org>
Date: Sat, 23 Apr 2016 20:52:20 -0400
Subject: Fixed shiv

---
 shiv.py | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 99 insertions(+), 6 deletions(-)

(limited to 'shiv.py')

diff --git a/shiv.py b/shiv.py
index 80411e3..07f0bdd 100644
--- a/shiv.py
+++ b/shiv.py
@@ -8,27 +8,54 @@ parser = optparse.OptionParser()
 parser.add_option('-n', '--number', dest='number', action='store_true', help='Show number of tracks')
 parser.add_option('-g', '--groups', dest='groups', action='store_true', help='Show group names')
 parser.add_option('-N', '--notes', dest='notes', action='store_true', help='Show number of notes')
+parser.add_option('-M', '--notes-stream', dest='notes_stream', action='store_true', help='Show notes per stream')
 parser.add_option('-m', '--meta', dest='meta', action='store_true', help='Show meta track information')
 parser.add_option('--histogram', dest='histogram', action='store_true', help='Show a histogram distribution of pitches')
 parser.add_option('--histogram-tracks', dest='histogram_tracks', action='store_true', help='Show a histogram distribution of pitches per track')
+parser.add_option('--vel-hist', dest='vel_hist', action='store_true', help='Show a histogram distribution of velocities')
+parser.add_option('--vel-hist-tracks', dest='vel_hist_tracks', action='store_true', help='Show a histogram distributions of velocities per track')
 parser.add_option('-d', '--duration', dest='duration', action='store_true', help='Show the duration of the piece')
 parser.add_option('-D', '--duty-cycle', dest='duty_cycle', action='store_true', help='Show the duration of the notes within tracks, and as a percentage of the piece duration')
+parser.add_option('-H', '--height', dest='height', type='int', help='Height of histograms')
 
 parser.add_option('-a', '--almost-all', dest='almost_all', action='store_true', help='Show useful information')
 parser.add_option('-A', '--all', dest='all', action='store_true', help='Show everything')
 
+parser.set_defaults(height=20)
+
 options, args = parser.parse_args()
 
 if options.almost_all or options.all:
     options.number = True
     options.groups = True
     options.notes = True
+    options.notes_stream = True
     options.histogram = True
+    options.vel_hist = True
     options.duration = True
+    options.duty_cycle = True
+    options.meta = True
     if options.all:
-        options.meta = True
         options.histogram_tracks= True
-        options.duty_cycle = True
+        options.vel_hist_tracks = True
+
+def show_hist(values, height=None):
+    if not values:
+        print '{empty histogram}'
+    if height is None:
+        height = options.height
+    xs, ys = values.keys(), values.values()
+    minx, maxx = min(xs), max(xs)
+    miny, maxy = min(ys), max(ys)
+    xv = range(minx, maxx + 1)
+    incs = max((maxy - miny) / height, 1)
+    print '\t --' + '-' * len(xv)
+    for ub in range(maxy + incs, miny, -incs):
+        print '{}\t | {}'.format(ub, ''.join(['#' if values.get(x) > (ub - incs) else ' ' for x in xv]))
+    print '\t |-' + '-' * len(xv)
+    xvs = map(str, xv)
+    for i in range(max(map(len, xvs))):
+        print '\t   ' + ''.join([s[i] if len(s) > i else ' ' for s in xvs])
 
 for fname in args:
     try:
@@ -45,11 +72,11 @@ for fname in args:
     if options.meta:
         print 'Metatrack:',
         meta = iv.find('./meta')
-        if meta:
+        if len(meta):
             print 'exists'
             print '\tBPM track:',
             bpms = meta.find('./bpms')
-            if bpms:
+            if len(bpms):
                 print 'exists'
                 for elem in bpms.iterfind('./bpm'):
                     print '\t\tAt ticks {}, time {}: {} bpm'.format(elem.get('ticks'), elem.get('time'), elem.get('bpm'))
@@ -70,11 +97,77 @@ for fname in args:
     if options.groups:
         groups = {}
         for s in notestreams:
-            group = s.get('group', '<anonymous')
+            group = s.get('group', '<anonymous>')
             groups[group] = groups.get(group, 0) + 1
         print 'Groups:'
         for name, cnt in groups.iteritems():
             print '\t{} ({} streams)'.format(name, cnt)
 
-    if not (options.notes or options.histogram or options.histogram_tracks or options.duration or options.duty_cycle):
+    if not (options.notes or options.notes_stream or options.histogram or options.histogram_tracks or options.duration or options.duty_cycle):
         continue
+
+    if options.notes:
+        note_cnt = 0
+    if options.notes_stream:
+        notes_stream = [0] * len(notestreams)
+    if options.histogram:
+        pitches = {}
+    if options.histogram_tracks:
+        pitch_tracks = [{} for i in notestreams]
+    if options.vel_hist:
+        velocities = {}
+    if options.vel_hist_tracks:
+        velocities_tracks = [{} for i in notestreams]
+    if options.duration or options.duty_cycle:
+        max_dur = 0
+    if options.duty_cycle:
+        cum_dur = [0.0] * len(notestreams)
+
+    for sidx, stream in enumerate(notestreams):
+        notes = stream.findall('note')
+        for note in notes:
+            pitch = int(note.get('pitch'))
+            vel = int(note.get('vel'))
+            time = float(note.get('time'))
+            dur = float(note.get('dur'))
+            if options.notes:
+                note_cnt += 1
+            if options.notes_stream:
+                notes_stream[sidx] += 1
+            if options.histogram:
+                pitches[pitch] = pitches.get(pitch, 0) + 1
+            if options.histogram_tracks:
+                pitch_tracks[sidx][pitch] = pitch_tracks[sidx].get(pitch, 0) + 1
+            if options.vel_hist:
+                velocities[vel] = velocities.get(vel, 0) + 1
+            if options.vel_hist_tracks:
+                velocities_tracks[sidx][vel] = velocities_tracks[sidx].get(vel, 0) + 1
+            if (options.duration or options.duty_cycle) and time + dur > max_dur:
+                max_dur = time + dur
+            if options.duty_cycle:
+                cum_dur[sidx] += dur
+
+    if options.histogram_tracks:
+        for sidx, hist in enumerate(pitch_tracks):
+            print 'Stream {} (group {}) pitch histogram:'.format(sidx, notestreams[sidx].get('group', '<anonymous>'))
+            show_hist(hist)
+    if options.vel_hist_tracks:
+        for sidx, hist in enumerate(velocities_tracks):
+            print 'Stream {} (group {}) velocity histogram:'.format(sidx, notestreams[sidx].get('group', '<anonymous>'))
+            show_hist(hist)
+    if options.notes_stream:
+        for sidx, value in enumerate(notes_stream):
+            print 'Stream {} (group {}) note count: {}'.format(sidx, notestreams[sidx].get('group', '<anonymous>'), value)
+    if options.duty_cycle:
+        for sidx, value in enumerate(cum_dur):
+            print 'Stream {} (group {}) duty cycle: {}'.format(sidx, notestreams[sidx].get('group', '<anonymous>'), value / max_dur)
+    if options.notes:
+        print 'Total notes: {}'.format(note_cnt)
+    if options.histogram:
+        print 'Pitch histogram:'
+        show_hist(pitches)
+    if options.vel_hist:
+        print 'Velocity histogram:'
+        show_hist(velocities)
+    if options.duration:
+        print 'Playing duration: {}'.format(max_dur)
-- 
cgit v1.2.3-70-g09d2