@@ -508,7 +508,7 @@ def _operation(self, other, operation):
508
508
if not isinstance (other , numbers .Number ):
509
509
return NotImplemented
510
510
time .triple = other
511
- time .note = operatrion (self .note , other .note )
511
+ time .note = operation (self .note , other .note )
512
512
else :
513
513
return NotImplemented
514
514
return time
@@ -538,7 +538,7 @@ def __sub__(self, other):
538
538
return self ._operation (other , operator .sub )
539
539
540
540
def __repr__ (self ):
541
- return str ( self )
541
+ return 'Time({note})' . format ( note = note )
542
542
543
543
def __str__ (self ):
544
544
self ._node = self .specification .time (self )
@@ -548,31 +548,18 @@ def __str__(self):
548
548
return string
549
549
550
550
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
576
563
577
564
@property
578
565
def triple (self ):
@@ -590,113 +577,143 @@ def ppn(self):
590
577
return self .specification .division .pps / self .tempo .bps * 4
591
578
592
579
def __repr__ (self ):
593
- return 'TimeNode(note= {note})' .format (note = self .note )
580
+ return 'TimeNode({note})' .format (note = self .note )
594
581
595
582
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
601
589
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
614
601
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
+
615
616
@property
616
617
def division (self ):
617
618
return self ._division
618
619
619
620
@division .setter
620
621
def division (self , value ):
621
622
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 )
623
671
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' )
626
679
627
680
def note (self , value ):
628
681
return self ._lookup (value , 'note' )
629
-
682
+
630
683
def cumulative (self , value ):
631
684
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
+
633
699
def events (self , * , track = None ):
634
- self .sort ()
635
- tempo = None
636
- signature = None
637
700
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 ))
651
709
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 )
683
710
684
711
def _lookup (self , value , key ):
685
- for node in reversed (self ):
712
+ for node in reversed (self . _cache ):
686
713
if node .__dict__ [key ] <= value :
687
714
return node
688
715
return None
689
716
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
-
700
717
class Event :
701
718
"""Base class for MIDI events."""
702
719
@@ -1340,28 +1357,11 @@ def cumulative(event):
1340
1357
sequence .sort (key = cumulative )
1341
1358
1342
1359
to_delete = list ()
1343
- tempo = Tempo ()
1344
- signature = TimeSignature ()
1345
- node = TimeNode (tempo = tempo , signature = signature )
1346
- sequence .specification .append (node )
1347
1360
for index in range (len (sequence )):
1348
1361
event = sequence [index ]
1349
1362
if isinstance (event , (SetTempo , SetTimeSignature )):
1350
1363
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 )
1365
1365
for index in reversed (to_delete ):
1366
1366
del sequence [index ]
1367
1367
return sequence
0 commit comments