Skip to content

Commit 9b83576

Browse files
committed
Made TimeSpecification more modular.
1 parent af7e219 commit 9b83576

File tree

1 file changed

+126
-126
lines changed

1 file changed

+126
-126
lines changed

midi.py

Lines changed: 126 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ def _operation(self, other, operation):
508508
if not isinstance(other, numbers.Number):
509509
return NotImplemented
510510
time.triple = other
511-
time.note = operatrion(self.note, other.note)
511+
time.note = operation(self.note, other.note)
512512
else:
513513
return NotImplemented
514514
return time
@@ -538,7 +538,7 @@ def __sub__(self, other):
538538
return self._operation(other, operator.sub)
539539

540540
def __repr__(self):
541-
return str(self)
541+
return 'Time({note})'.format(note=note)
542542

543543
def __str__(self):
544544
self._node = self.specification.time(self)
@@ -548,31 +548,18 @@ def __str__(self):
548548
return string
549549

550550
class TimeNode:
551-
def __init__(self, time=None, *, note=0.0, bar=1, beat=1, tick=1,
552-
triple=None, cumulative=0, signature=None, tempo=None):
553-
self.specification = None
554-
if isinstance(time, Time):
555-
self.note = time.note
556-
if isinstance(signature, TimeSignature):
557-
self.signature = signature
558-
else:
559-
self.signature = time.node.signature
560-
if isinstance(tempo, Tempo):
561-
self.tempo = tempo
562-
else:
563-
self.tempo = time.node.tempo
564-
self.triple = time.triple
565-
self.cumulative = time.cumulative
566-
else:
567-
self.note = note
568-
self.signature = signature
569-
self.tempo = tempo
570-
self.bar = bar
571-
self.beat = beat
572-
self.tick = tick
573-
if triple != None:
574-
self.triple = triple
575-
self.cumulative = cumulative
551+
def __init__(self, note=0.0, *, bar=1, beat=1, tick=1, triple=None,
552+
cumulative=0, signature=None, tempo=None, specification=None):
553+
self.specification = specification
554+
self.note = note
555+
self.signature = signature
556+
self.tempo = tempo
557+
self.bar = bar
558+
self.beat = beat
559+
self.tick = tick
560+
if triple != None:
561+
self.triple = triple
562+
self.cumulative = cumulative
576563

577564
@property
578565
def triple(self):
@@ -590,113 +577,143 @@ def ppn(self):
590577
return self.specification.division.pps / self.tempo.bps * 4
591578

592579
def __repr__(self):
593-
return 'TimeNode(note={note})'.format(note=self.note)
580+
return 'TimeNode({note})'.format(note=self.note)
594581

595582

596-
class TimeSpecification(list):
597-
def __init__(self, nodes=list(), *, division=None):
598-
for node in nodes:
599-
self.append(node)
600-
self.division = division
583+
class TempoNode:
584+
def __init__(self, note=0.0, tempo=None):
585+
self.note = note
586+
if isinstance(note, Time):
587+
self.note = note.note
588+
self.tempo = tempo
601589

602-
def triple(self, iterable):
603-
bar, beat, tick = iterable
604-
for node in reversed(self):
605-
if node.bar < bar:
606-
return node
607-
elif node.bar == bar:
608-
if node.beat < beat:
609-
return node
610-
elif node.beat == beat:
611-
if node.tick <= tick:
612-
return node
613-
return None
590+
def __repr__(self):
591+
return 'TempoNode({note}, {tempo!r})'.format(note=self.note,
592+
tempo=self.tempo)
593+
594+
595+
class TimeSignatureNode:
596+
def __init__(self, note=0.0, signature=None):
597+
self.note = note
598+
if isinstance(note, Time):
599+
self.note = note.note
600+
self.signature = signature
614601

602+
def __repr__(self):
603+
return 'TimeSignatureNode({note}, {signature!r})'.format(
604+
note=self.note, signature=self.signature)
605+
606+
607+
class TimeSpecification:
608+
def __init__(self, *, division=None):
609+
self._division = division
610+
self.tempos = list()
611+
self.signatures = list()
612+
self._cache = list()
613+
self._default_tempo = Tempo()
614+
self._default_signature = TimeSignature()
615+
615616
@property
616617
def division(self):
617618
return self._division
618619

619620
@division.setter
620621
def division(self, value):
621622
self._division = value
622-
self._update_cumulative()
623+
self.update()
624+
625+
def add(self, item):
626+
if isinstance(item, TempoNode):
627+
self.tempos.append(item)
628+
elif isinstance(item, SetTempo):
629+
self.tempos.append(TempoNode(item.time.note, item.tempo))
630+
elif isinstance(item, TimeSignatureNode):
631+
self.signatures.append(item)
632+
elif isinstance(item, SetTimeSignature):
633+
self.signatures.append(TimeSignatureNode(item.time.note,
634+
item.signature))
635+
self.update()
636+
637+
def remove(self, item):
638+
for node in self.tempos + self.signatures:
639+
if item is node:
640+
del item
641+
self.update()
642+
return
643+
644+
def update(self):
645+
def note(node):
646+
return node.note
647+
self.tempos.sort(key=note)
648+
self.signatures.sort(key=note)
649+
changes = self.tempos + self.signatures
650+
changes.sort(key=note)
651+
652+
tempo = self._default_tempo
653+
signature = self._default_signature
654+
time = Time(specification=self)
655+
self._cache = list()
656+
self._cache.append(TimeNode(tempo=tempo, signature=signature,
657+
specification=self))
658+
for change in changes:
659+
if isinstance(change, TempoNode):
660+
tempo = change.tempo
661+
else:
662+
signature = change.signature
663+
time.note = change.note
664+
node = TimeNode(note=time.note, triple=time.triple,
665+
cumulative=time.cumulative, tempo=tempo,
666+
signature=signature, specification=self)
667+
if node.note == self._cache[-1].note:
668+
self._cache[-1] = node
669+
else:
670+
self._cache.append(node)
623671

624-
def time(self, time_object):
625-
return self._lookup(time_object.note, 'note')
672+
def offset(self, time):
673+
for node in self.tempos + self.signatures:
674+
node.note += time.note
675+
self.update()
676+
677+
def time(self, value):
678+
return self._lookup(value.note, 'note')
626679

627680
def note(self, value):
628681
return self._lookup(value, 'note')
629-
682+
630683
def cumulative(self, value):
631684
return self._lookup(value, 'cumulative')
632-
685+
686+
def triple(self, iterable):
687+
bar, beat, tick = iterable
688+
for node in reversed(self._cache):
689+
if node.bar < bar:
690+
return node
691+
elif node.bar == bar:
692+
if node.beat < beat:
693+
return node
694+
elif node.beat == beat:
695+
if node.tick <= tick:
696+
return Node
697+
return None
698+
633699
def events(self, *, track=None):
634-
self.sort()
635-
tempo = None
636-
signature = None
637700
event_list = list()
638-
for node in self:
639-
if node.tempo != tempo:
640-
tempo = node.tempo
641-
event = SetTempo(tempo, track=track)
642-
event.time.specification = self
643-
event.time.note = node.note
644-
event_list.append(event)
645-
if node.signature != signature:
646-
signature = node.signature
647-
event = SetTimeSignature(signature, track=track)
648-
event.time.specification = self
649-
event.time.note = node.note
650-
event_list.append(event)
701+
for node in self.tempos:
702+
time = Time(node.note, specification=self)
703+
event_list.append(SetTempo(time=time, tempo=node.tempo,
704+
track=track))
705+
for node in self.signatures:
706+
time = Time(node.note, specification=self)
707+
event_list.append(SetTimeSignature(time=time,
708+
signature=node.signature, track=track))
651709
return event_list
652-
653-
def offset(self, time):
654-
for node in self:
655-
node.note += time.note
656-
for index in reversed(range(len(self))):
657-
if self[index].note <= 0.0:
658-
self[index].note = 0.0
659-
break
660-
del self[:index]
661-
self._update_cumulative()
662-
663-
def append(self, object):
664-
if not isinstance(object, (Time, TimeNode)):
665-
raise TypeError('cannot append {type!r} to \'TimeSpecification\''
666-
.format(type=type(object).__name__))
667-
node = object
668-
if not isinstance(object, TimeNode):
669-
node = TimeNode(object)
670-
node.specification = self
671-
super().append(node)
672-
673-
def extend(self, nodes):
674-
for node in nodes:
675-
self.append(node)
676-
677-
def sort(self, *, key=None, reverse=False):
678-
if key == None:
679-
def note(node):
680-
return node.note
681-
key = note
682-
super().sort(key=key, reverse=reverse)
683710

684711
def _lookup(self, value, key):
685-
for node in reversed(self):
712+
for node in reversed(self._cache):
686713
if node.__dict__[key] <= value:
687714
return node
688715
return None
689716

690-
def _update_cumulative(self):
691-
if self._division != None:
692-
note = 0.0
693-
cumulative = 0
694-
for node in self:
695-
node.cumulative = cumulative + (node.note - note) * node.ppn
696-
cumulative = node.cumulative
697-
note = node.note
698-
699-
700717
class Event:
701718
"""Base class for MIDI events."""
702719

@@ -1340,28 +1357,11 @@ def cumulative(event):
13401357
sequence.sort(key=cumulative)
13411358

13421359
to_delete = list()
1343-
tempo = Tempo()
1344-
signature = TimeSignature()
1345-
node = TimeNode(tempo=tempo, signature=signature)
1346-
sequence.specification.append(node)
13471360
for index in range(len(sequence)):
13481361
event = sequence[index]
13491362
if isinstance(event, (SetTempo, SetTimeSignature)):
13501363
to_delete.append(index)
1351-
previous = sequence.specification[-1]
1352-
if isinstance(event, SetTempo):
1353-
tempo = event.tempo
1354-
elif isinstance(event, SetTimeSignature):
1355-
signature = event.signature
1356-
if previous.note == event.time.note:
1357-
previous.tempo = tempo
1358-
previous.signature = signature
1359-
else:
1360-
node = TimeNode(tempo=tempo, signature=signature,
1361-
note=event.time.note, triple=event.time.triple,
1362-
cumulative=event.time.cumulative)
1363-
sequence.specification.append(node)
1364-
1364+
sequence.specification.add(event)
13651365
for index in reversed(to_delete):
13661366
del sequence[index]
13671367
return sequence

0 commit comments

Comments
 (0)