<s> import collections <EOL> import copy <EOL> from pyknon import notation <EOL> class MusiclibError ( Exception ) : <EOL> pass <EOL> class Rest ( object ) : <EOL> def __init__ ( self , dur = <NUM_LIT> ) : <EOL> self . dur = dur <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" . format ( self . dur ) <EOL> def __eq__ ( self , other ) : <EOL> return self . dur == other . dur <EOL> @ property <EOL> def verbose ( self ) : <EOL> return "<STR_LIT>" . format ( self . dur ) <EOL> @ property <EOL> def midi_dur ( self ) : <EOL> return self . dur * <NUM_LIT:4> <EOL> def stretch_dur ( self , factor ) : <EOL> return Rest ( self . dur * factor ) <EOL> class Note ( object ) : <EOL> def __init__ ( self , value = <NUM_LIT:0> , octave = <NUM_LIT:5> , dur = <NUM_LIT> , volume = <NUM_LIT:100> ) : <EOL> if isinstance ( value , str ) : <EOL> self . value , self . octave , self . dur , self . volume = notation . parse_note ( value ) <EOL> else : <EOL> offset , val = divmod ( value , <NUM_LIT:12> ) <EOL> self . value = val <EOL> self . octave = octave + offset <EOL> self . dur = dur <EOL> self . volume = volume <EOL> def __eq__ ( self , other ) : <EOL> return self . value == other . value and self . dur == other . dur and self . octave == other . octave <EOL> def __sub__ ( self , other ) : <EOL> return self . midi_number - other . midi_number <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" . format ( self . name ) <EOL> @ property <EOL> def verbose ( self ) : <EOL> return "<STR_LIT>" . format ( self . value , self . octave , self . dur ) <EOL> @ property <EOL> def name ( self ) : <EOL> note_names = "<STR_LIT>" . split ( ) <EOL> return note_names [ self . value % <NUM_LIT:12> ] <EOL> @ property <EOL> def midi_number ( self ) : <EOL> return self . value + ( self . octave * <NUM_LIT:12> ) <EOL> @ property <EOL> def midi_dur ( self ) : <EOL> return self . dur * <NUM_LIT:4> <EOL> def __note_octave ( self , octave ) : <EOL> """<STR_LIT>""" <EOL> return self . value + ( ( self . octave - octave ) * <NUM_LIT:12> ) <EOL> def transposition ( self , index ) : <EOL> return Note ( self . value + index , self . octave , self . dur , self . volume ) <EOL> def tonal_transposition ( self , index , scale ) : <EOL> pos = index + scale . index ( self ) - <NUM_LIT:1> <EOL> octave , rest = divmod ( pos , <NUM_LIT:7> ) <EOL> note = copy . copy ( scale [ pos % len ( scale ) ] ) <EOL> note . octave += octave <EOL> return note <EOL> def harmonize ( self , scale , interval = <NUM_LIT:3> , size = <NUM_LIT:3> ) : <EOL> i = ( interval - <NUM_LIT:1> ) <EOL> indices = range ( <NUM_LIT:1> , size * i , i ) <EOL> return [ self . tonal_transposition ( x , scale ) for x in indices ] <EOL> def inversion ( self , index = <NUM_LIT:0> , initial_octave = None ) : <EOL> value = self . __note_octave ( initial_octave ) if initial_octave else self . value <EOL> octv = initial_octave if initial_octave else self . octave <EOL> note_value = ( <NUM_LIT:2> * index ) - value <EOL> return Note ( note_value , octv , self . dur , self . volume ) <EOL> def stretch_dur ( self , factor ) : <EOL> return Note ( self . value , self . octave , self . dur * factor , self . volume ) <EOL> class NoteSeq ( collections . MutableSequence ) : <EOL> @ staticmethod <EOL> def _is_note_or_rest ( args ) : <EOL> return all ( [ True if isinstance ( x , Note ) or isinstance ( x , Rest ) else False for x in args ] ) <EOL> @ staticmethod <EOL> def _make_note_or_rest ( note_list ) : <EOL> if note_list [ <NUM_LIT:0> ] is not None : <EOL> return Note ( * note_list ) <EOL> else : <EOL> return Rest ( note_list [ <NUM_LIT:2> ] ) <EOL> @ staticmethod <EOL> def _parse_score ( filename ) : <EOL> with open ( filename ) as score : <EOL> notes = [ ] <EOL> for line in score : <EOL> notes . extend ( [ note for note in line . split ( ) ] ) <EOL> return notes <EOL> def __init__ ( self , args = None ) : <EOL> if isinstance ( args , str ) : <EOL> if args . startswith ( "<STR_LIT>" ) : <EOL> filename = args . replace ( "<STR_LIT>" , "<STR_LIT>" ) <EOL> note_lists = notation . parse_notes ( self . _parse_score ( filename ) ) <EOL> else : <EOL> note_lists = notation . parse_notes ( args . split ( ) ) <EOL> self . items = [ self . _make_note_or_rest ( x ) for x in note_lists ] <EOL> elif isinstance ( args , collections . Iterable ) : <EOL> if self . _is_note_or_rest ( args ) : <EOL> self . items = args <EOL> else : <EOL> raise MusiclibError ( "<STR_LIT>" ) <EOL> elif args is None : <EOL> self . items = [ ] <EOL> else : <EOL> raise MusiclibError ( "<STR_LIT>" ) <EOL> def __iter__ ( self ) : <EOL> for x in self . items : <EOL> yield x <EOL> def __delitem__ ( self , i ) : <EOL> del self . items [ i ] <EOL> def __getitem__ ( self , i ) : <EOL> if isinstance ( i , int ) : <EOL> return self . items [ i ] <EOL> else : <EOL> return NoteSeq ( self . items [ i ] ) <EOL> def __len__ ( self ) : <EOL> return len ( self . items ) <EOL> def __setitem__ ( self , i , value ) : <EOL> self . items [ i ] = value <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" . format ( self . items ) <EOL> def __eq__ ( self , other ) : <EOL> if len ( self ) == len ( other ) : <EOL> return all ( x == y for x , y in zip ( self . items , other . items ) ) <EOL> def __add__ ( self , other ) : <EOL> if isinstance ( other , NoteSeq ) : <EOL> return NoteSeq ( self . items + other . items ) <EOL> elif isinstance ( other , Note ) or isinstance ( other , Rest ) : <EOL> return NoteSeq ( self . items + [ other ] ) <EOL> def __radd__ ( self , other ) : <EOL> if isinstance ( other , NoteSeq ) : <EOL> return NoteSeq ( other . items + self . items ) <EOL> elif isinstance ( other , Note ) or isinstance ( other , Rest ) : <EOL> return NoteSeq ( [ other ] + self . items ) <EOL> def __mul__ ( self , n ) : <EOL> return NoteSeq ( self . items * n ) <EOL> @ property <EOL> def verbose ( self ) : <EOL> string = "<STR_LIT:U+002CU+0020>" . join ( [ note . verbose for note in self . items ] ) <EOL> return "<STR_LIT>" . format ( string ) <EOL> def retrograde ( self ) : <EOL> return NoteSeq ( list ( reversed ( self . items ) ) ) <EOL> def insert ( self , i , value ) : <EOL> self . items . insert ( i , value ) <EOL> def transposition ( self , index ) : <EOL> return NoteSeq ( [ x . transposition ( index ) if isinstance ( x , Note ) else x <EOL> for x in self . items ] ) <EOL> def _make_note ( self , item ) : <EOL> return Note ( item ) if ( isinstance ( item , int ) or isinstance ( item , str ) ) else item <EOL> def transposition_startswith ( self , note_start ) : <EOL> note = self . _make_note ( note_start ) <EOL> return self . transposition ( note - self . items [ <NUM_LIT:0> ] ) <EOL> def inversion ( self , index = <NUM_LIT:0> ) : <EOL> initial_octave = self . items [ <NUM_LIT:0> ] . octave <EOL> return NoteSeq ( [ x . inversion ( index , initial_octave ) if isinstance ( x , Note ) <EOL> else x for x in self . items ] ) <EOL> def inversion_startswith ( self , note_start ) : <EOL> note = self . _make_note ( note_start ) <EOL> inv = self . transposition_startswith ( Note ( <NUM_LIT:0> , note . octave ) ) . inversion ( ) <EOL> return inv . transposition_startswith ( note ) <EOL> def harmonize ( self , interval = <NUM_LIT:3> , size = <NUM_LIT:3> ) : <EOL> return [ NoteSeq ( note . harmonize ( self , interval , size ) ) for note in self ] <EOL> def rotate ( self , n = <NUM_LIT:1> ) : <EOL> modn = n % len ( self ) <EOL> result = self . items [ modn : ] + self . items [ <NUM_LIT:0> : modn ] <EOL> return NoteSeq ( result ) <EOL> def stretch_dur ( self , factor ) : <EOL> return NoteSeq ( [ x . stretch_dur ( factor ) for x in self . items ] ) <EOL> def intervals ( self ) : <EOL> v1 = self [ : ] <EOL> v2 = self . rotate ( ) <EOL> return [ y - x for x , y in zip ( v1 , v2 [ : - <NUM_LIT:1> ] ) ] <EOL> def stretch_interval ( self , factor ) : <EOL> intervals = [ x + factor for x in self . intervals ( ) ] <EOL> note = copy . copy ( self [ <NUM_LIT:0> ] ) <EOL> result = NoteSeq ( [ note ] ) <EOL> for i in intervals : <EOL> note = note . transposition ( i ) <EOL> result . append ( note ) <EOL> return result <EOL> transp = transposition_startswith <EOL> inv = inversion_startswith </s>
