@ -34,8 +34,13 @@ class Pattern(object):
""" A pattern can be in only one track.
In fact having it as its own object is only for code readability
A pattern is an unordered list of dicts . Each dicts is an step , or a note .
{ " index " : int 0 - timesigLength , " factor " : float , " pitch " , int 0 - 7 , " velocity " : int 0 - 127 }
A pattern is an unordered list of dicts .
Each dict is an step , or a note .
{ " index " : from 0 to parentTrack . parentData . howManyUnits ,
" factor " : float ,
" pitch " : int 0 - 7 ,
" velocity " : int 0 - 127 ,
}
The pitch is determined is by a scale , which is a list of len 7 of midi pitches . Our " pitch " is
an index in this list .
@ -113,6 +118,67 @@ class Pattern(object):
lst . append ( { " index " : index , " factor " : 1 , " pitch " : pitchindex , " velocity " : vel } )
self . data = lst
def _getRow ( self , pitchindex ) :
""" Returns a row of steps, sorted by index/column.
Includes the original mutable dictionaries , which can be changed
"""
return sorted ( [ d for d in self . data if d [ " pitch " ] == pitchindex ] , key = lambda i : i [ " index " ] )
def _putRow ( self , pitchindex , rowAsListOfSteps ) :
""" Replace a row with the given one """
self . clearRow ( pitchindex )
self . data . extend ( rowAsListOfSteps )
def clearRow ( self , pitchindex ) :
""" pure convenience. This could be done with
repeatFromStep on the first empty step """
existingSteps = self . _getRow ( pitchindex )
for step in existingSteps :
self . data . remove ( step )
def _rowAsBooleans ( self , pitchindex ) :
""" Existence or not """
existingSteps = self . _getRow ( pitchindex )
existingIndices = set ( s [ " index " ] for s in existingSteps )
result = [ False ] * self . parentTrack . parentData . howManyUnits
for i in existingIndices :
result [ i ] = True
return result
def repeatFromStep ( self , pitchindex , stepIndex ) :
""" Includes the given step.
Uses average velocities
"""
vel = self . averageVelocity
rowAsBools = self . _rowAsBooleans ( pitchindex )
toRepeatChunk = rowAsBools [ : stepIndex + 1 ]
numberOfRepeats , rest = divmod ( self . parentTrack . parentData . howManyUnits , stepIndex + 1 )
index = 0
newRow = [ ]
for i in range ( numberOfRepeats ) :
for b in toRepeatChunk :
if b :
newRow . append ( { " index " : index , " factor " : 1 , " pitch " : pitchindex , " velocity " : vel } )
index + = 1
self . _putRow ( pitchindex , newRow )
def invertRow ( self , pitchindex ) :
vel = self . averageVelocity
existingSteps = self . _getRow ( pitchindex )
existingIndices = set ( s [ " index " ] for s in existingSteps )
for step in existingSteps :
self . data . remove ( step )
for index in range ( self . parentTrack . parentData . howManyUnits ) :
if not index in existingIndices :
self . data . append ( { " index " : index , " factor " : 1 , " pitch " : pitchindex , " velocity " : vel } )
def stepByIndexAndPitch ( self , index , pitch ) :
for d in self . data :
if d [ " index " ] == index and d [ " pitch " ] == pitch :