aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrissess <grissess@nexusg.org>2016-04-22 19:15:16 -0400
committerGrissess <grissess@nexusg.org>2016-04-22 19:15:16 -0400
commita3cfdd481d40a7a28dcb5f421797d52b10deeab1 (patch)
tree0b7ade272f2966886135b57e8695c62dc0758ff0
parentb6ab9fcbec899e345d81554d60111e95cf9ce466 (diff)
Added saw wave
-rw-r--r--client.py4
-rw-r--r--mkiv.py46
-rw-r--r--shiv.py4
3 files changed, 44 insertions, 10 deletions
diff --git a/client.py b/client.py
index 91ef663..01344c1 100644
--- a/client.py
+++ b/client.py
@@ -166,6 +166,10 @@ def tri_wave(theta):
else:
return lin_interp(-1, 0, (theta-3*math.pi/2)/(math.pi/2))
+@generator('Saw wave (line from (0, 1) to (2pi, -1))')
+def saw_wave(theta):
+ return lin_interp(1, -1, theta/(math.pi * 2))
+
@generator('Simple square wave (piecewise 1 at x<pi, 0 else)')
def square_wave(theta):
if theta < math.pi:
diff --git a/mkiv.py b/mkiv.py
index 0d2bfa0..3a71847 100644
--- a/mkiv.py
+++ b/mkiv.py
@@ -92,6 +92,8 @@ for fname in args:
iv.set('version', '1')
iv.set('src', os.path.basename(fname))
print fname, ': MIDI format,', len(pat), 'tracks'
+ if options.verbose:
+ print fname, ': MIDI Parameters:', pat.resolution, 'PPQN,', pat.format, 'format'
if options.chansplit:
print 'Splitting channels...'
@@ -126,6 +128,38 @@ for fname in args:
##### Merge events from all tracks into one master list, annotated with track and absolute times #####
print 'Merging events...'
+ class SortEvent(object):
+ __slots__ = ['ev', 'tidx', 'abstick']
+ def __init__(self, ev, tidx, abstick):
+ self.ev = ev
+ self.tidx = tidx
+ self.abstick = abstick
+
+ sorted_events = []
+ for tidx, track in enumerate(pat):
+ absticks = 0
+ for ev in track:
+ absticks += ev.tick
+ sorted_events.append(SortEvent(ev, tidx, absticks))
+
+ sorted_events.sort(key=lambda x: x.abstick)
+ bpm_at = {0: 120}
+
+ for sev in sorted_events:
+ if isinstance(sev.ev, midi.SetTempoEvent):
+ if options.debug:
+ print fname, ': SetTempo at', sev.abstick, 'to', sev.ev.bpm, ':', sev.ev
+ bpm_at[sev.abstick] = sev.ev.bpm
+
+ if options.verbose:
+ print fname, ': Events:', len(sorted_events)
+ print fname, ': Resolved global BPM:', bpm_at
+ if options.debug:
+ btimes = bpm_at.keys()
+ for i in range(len(btimes) - 1):
+ fev = filter(lambda sev: sev.abstick >= btimes[i] and sev.abstick < btimes[i+1], sorted_events)
+ print fname, ': BPM partition', i, 'contains', len(fev), 'events'
+
class MergeEvent(object):
__slots__ = ['ev', 'tidx', 'abstime', 'bank', 'prog']
def __init__(self, ev, tidx, abstime, bank, prog):
@@ -138,7 +172,6 @@ for fname in args:
return '<ME %r in %d @%f>'%(self.ev, self.tidx, self.abstime)
events = []
- bpm_at = {0: 120}
cur_bank = [[0 for i in range(16)] for j in range(len(pat))]
cur_prog = [[0 for i in range(16)] for j in range(len(pat))]
chg_bank = [[0 for i in range(16)] for j in range(len(pat))]
@@ -150,12 +183,11 @@ for fname in args:
abstime = 0
absticks = 0
for ev in track:
+ bpm = filter(lambda pair: pair[0] <= absticks, sorted(bpm_at.items(), key=lambda pair: pair[0]))[-1][1]
if options.debug:
- print ev
- if isinstance(ev, midi.SetTempoEvent):
- absticks += ev.tick
- bpm_at[absticks] = ev.bpm
- elif isinstance(ev, midi.ProgramChangeEvent):
+ print ev, ': bpm=', bpm
+ absticks += ev.tick
+ if isinstance(ev, midi.ProgramChangeEvent):
cur_prog[tidx][ev.channel] = ev.value
chg_prog[tidx][ev.channel] += 1
elif isinstance(ev, midi.ControlChangeEvent):
@@ -170,9 +202,7 @@ for fname in args:
elif isinstance(ev, midi.Event):
if isinstance(ev, midi.NoteOnEvent) and ev.velocity == 0:
ev.__class__ = midi.NoteOffEvent #XXX Oww
- bpm = filter(lambda pair: pair[0] <= absticks, sorted(bpm_at.items(), key=lambda pair: pair[0]))[-1][1]
abstime += (60.0 * ev.tick) / (bpm * pat.resolution)
- absticks += ev.tick
events.append(MergeEvent(ev, tidx, abstime, cur_bank[tidx][ev.channel], cur_prog[tidx][ev.channel]))
ev_cnts[tidx][ev.channel] += 1
diff --git a/shiv.py b/shiv.py
index 423bdf7..80411e3 100644
--- a/shiv.py
+++ b/shiv.py
@@ -9,8 +9,8 @@ parser.add_option('-n', '--number', dest='number', action='store_true', help='Sh
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', '--meta', dest='meta', action='store_true', help='Show meta track information')
-parser.add_option('-h', '--histogram', dest='histogram', action='store_true', help='Show a histogram distribution of pitches')
-parser.add_option('-H', '--histogram-tracks', dest='histogram_tracks', action='store_true', help='Show a histogram distribution of pitches per track')
+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('-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')