diff options
| -rw-r--r-- | broadcast.py | 2 | ||||
| -rw-r--r-- | mkiv.py | 59 | ||||
| -rw-r--r-- | shiv.py | 5 | 
3 files changed, 54 insertions, 12 deletions
| diff --git a/broadcast.py b/broadcast.py index 2a7ce3c..714533d 100644 --- a/broadcast.py +++ b/broadcast.py @@ -464,7 +464,7 @@ for fname in args:                      nsq, cl = self._Thread__args                      for note in nsq:                              ttime = float(note.get('time')) -                            pitch = int(note.get('pitch')) + options.transpose +                            pitch = float(note.get('pitch')) + options.transpose                              vel = int(note.get('vel'))                              dur = factor*float(note.get('dur'))                              while time.time() - BASETIME < factor*ttime: @@ -32,7 +32,8 @@ parser.add_option('-f', '--fuckit', dest='fuckit', action='store_true', help='Us  parser.add_option('-n', '--target-num', dest='repeaterNumber', type='int', help='Target count of devices')  parser.add_option('-v', '--verbose', dest='verbose', action='store_true', help='Be verbose; show important parts about the MIDI scheduling process')  parser.add_option('-d', '--debug', dest='debug', action='store_true', help='Debugging output; show excessive output about the MIDI scheduling process') -parser.set_defaults(tracks=[], repeaterNumber=1, perc='GM') +parser.add_option('-D', '--deviation', dest='deviation', type='int', help='Amount (in semitones/MIDI pitch units) by which a fully deflected pitchbend modifies the base pitch (0 disables pitchbend processing)') +parser.set_defaults(tracks=[], repeaterNumber=1, perc='GM', deviation=2)  options, args = parser.parse_args()  if options.help_conds: @@ -180,8 +181,12 @@ for fname in args:              self.abstime = abstime              self.bank = bank              self.prog = prog +        def copy(self, **kwargs): +            args = {'ev': self.ev, 'tidx': self.tidx, 'abstime': self.abstime, 'bank': self.bank, 'prog': self.prog} +            args.update(kwargs) +            return MergeEvent(**args)          def __repr__(self): -            return '<ME %r in %d @%f>'%(self.ev, self.tidx, self.abstime) +            return '<ME %r in %d on (%d:%d) @%f>'%(self.ev, self.tidx, self.bank, self.prog, self.abstime)      events = []      cur_bank = [[0 for i in range(16)] for j in range(len(pat))] @@ -234,27 +239,37 @@ for fname in args:      print 'Generating streams...'      class DurationEvent(MergeEvent): -        __slots__ = ['duration'] -        def __init__(self, me, dur): +        __slots__ = ['duration', 'pitch'] +        def __init__(self, me, pitch, dur):              MergeEvent.__init__(self, me.ev, me.tidx, me.abstime, me.bank, me.prog) +            self.pitch = pitch              self.duration = dur      class NoteStream(object): -        __slots__ = ['history', 'active'] +        __slots__ = ['history', 'active', 'realpitch']          def __init__(self):              self.history = []              self.active = None +            self.realpitch = None          def IsActive(self):              return self.active is not None -        def Activate(self, mev): +        def Activate(self, mev, realpitch = None): +            if realpitch is None: +                realpitch = mev.ev.pitch              self.active = mev +            self.realpitch = realpitch          def Deactivate(self, mev): -            self.history.append(DurationEvent(self.active, mev.abstime - self.active.abstime)) +            self.history.append(DurationEvent(self.active, self.realpitch, mev.abstime - self.active.abstime))              self.active = None +            self.realpitch = None          def WouldDeactivate(self, mev):              if not self.IsActive():                  return False -            return mev.ev.pitch == self.active.ev.pitch and mev.tidx == self.active.tidx +            if isinstance(mev.ev, midi.NoteOffEvent): +                return mev.ev.pitch == self.active.ev.pitch and mev.tidx == self.active.tidx and mev.ev.channel == self.active.ev.channel +            if isinstance(mev.ev, midi.PitchWheelEvent): +                return mev.tidx == self.active.tidx and mev.ev.channel == self.active.ev.channel +            raise TypeError('Tried to deactivate with bad type %r'%(type(mev.ev),))      class NSGroup(object):          __slots__ = ['streams', 'filter', 'name'] @@ -326,6 +341,32 @@ for fname in args:                      break              else:                  print 'WARNING: Did not match %r with any stream deactivation.'%(mev,) +                if options.verbose: +                    print '  Current state:' +                    for group in notegroups: +                        print '    Group %r:'%(group.name,) +                        for stream in group.streams: +                            print '      Stream: %r'%(stream.active,) +        elif options.deviation > 0 and isinstance(mev.ev, midi.PitchWheelEvent): +            for group in notegroups: +                found = False +                for stream in group.streams: +                    if stream.WouldDeactivate(mev): +                        base = stream.active.copy(abstime=mev.abstime) +                        stream.Deactivate(mev) +                        stream.Activate(base, base.ev.pitch + options.deviation * (mev.ev.pitch / 2000.0)) +                        found = True +                        break +                if found: +                    break +            else: +                print 'WARNING: Did not find any matching active streams for %r'%(mev,) +                if options.verbose: +                    print '  Current state:' +                    for group in notegroups: +                        print '    Group %r:'%(group.name,) +                        for stream in group.streams: +                            print '      Stream: %r'%(stream.active,)          else:              auxstream.append(mev) @@ -372,7 +413,7 @@ for fname in args:                  		ivns.set('group', group.name)              		for note in ns.history:                  		ivnote = ET.SubElement(ivns, 'note') -                		ivnote.set('pitch', str(note.ev.pitch)) +                		ivnote.set('pitch', str(note.pitch))                			ivnote.set('vel', str(note.ev.velocity))          	       		ivnote.set('time', str(note.abstime))   	               		ivnote.set('dur', str(note.duration)) @@ -3,6 +3,7 @@  import xml.etree.ElementTree as ET  import optparse  import sys +import math  parser = optparse.OptionParser()  parser.add_option('-n', '--number', dest='number', action='store_true', help='Show number of tracks') @@ -69,7 +70,7 @@ def show_hist(values, height=None):      xs, ys = values.keys(), values.values()      minx, maxx = min(xs), max(xs)      miny, maxy = min(ys), max(ys) -    xv = range(minx, maxx + 1) +    xv = range(int(math.floor(minx)), int(math.ceil(maxx + 1)))      incs = max((maxy - miny) / height, 1)      print COL.CYAN + '\t --' + '-' * len(xv) + COL.NONE      for ub in range(maxy + incs, miny, -incs): @@ -173,7 +174,7 @@ for fname in args:      for sidx, stream in enumerate(notestreams):          notes = stream.findall('note')          for note in notes: -            pitch = int(note.get('pitch')) +            pitch = float(note.get('pitch'))              vel = int(note.get('vel'))              time = float(note.get('time'))              dur = float(note.get('dur')) | 
