diff options
author | jaberg <james@localhost.localdomain> | 2007-01-07 21:24:04 (GMT) |
---|---|---|
committer | jaberg <james@localhost.localdomain> | 2007-01-07 21:24:04 (GMT) |
commit | 1becac24dfa6bd0cee4ae46f4c0b8630bfbb6269 (patch) | |
tree | 70d602342d546fd8c268143b54d46b8ca580a7ed /Generation | |
parent | 2a940a71469b2b5964e8deab3ed6db0254424671 (diff) |
unify_edit init
Diffstat (limited to 'Generation')
-rwxr-xr-x | Generation/Drunk.py | 118 | ||||
-rwxr-xr-x | Generation/GenerationConstants.py | 160 | ||||
-rwxr-xr-x | Generation/GenerationParametersWindow.py | 206 | ||||
-rw-r--r-- | Generation/GenerationPitch.py | 58 | ||||
-rw-r--r-- | Generation/GenerationRythm.py | 174 | ||||
-rwxr-xr-x | Generation/Generator.py | 243 | ||||
-rwxr-xr-x | Generation/Utils.py | 71 | ||||
-rw-r--r-- | Generation/VariationPitch.py | 82 | ||||
-rw-r--r-- | Generation/VariationRythm.py | 75 | ||||
-rw-r--r-- | Generation/__init__.py | 0 |
10 files changed, 1187 insertions, 0 deletions
diff --git a/Generation/Drunk.py b/Generation/Drunk.py new file mode 100755 index 0000000..5a36b11 --- /dev/null +++ b/Generation/Drunk.py @@ -0,0 +1,118 @@ +# Random: +# Randomly choose, within a certain range, a new next value +# arg 1: maxStepSize (negative value not allowed stepSize == 0) +# arg 2: maximum value allowed + +import random + +# TODO: replace magic numbers with constants +class Drunk: + def __init__( self, maxValue ): + self.lastValue = random.randint( 0, maxValue ) + + def getNextValue( self, maxStepSize, maxValue ): + if self.lastValue < 0 or self.lastValue > maxValue: + return random.randint( 0, maxValue ) + + direction = self.getDirection( maxValue ) + stepSize = self.getStepSize( direction, abs(maxStepSize), maxValue ) + + if maxStepSize < 0: + minStepSize = 1 + else: + minStepSize = 0 + + self.lastValue += direction * random.randint( minStepSize, stepSize ) + return self.lastValue + + def getDirection( self, maxValue ): + if self.lastValue == 0: + return 1 + elif self.lastValue == maxValue: + return -1 + else: + return random.choice( [ 1, -1 ] ) + + def getStepSize( self, direction, maxStepSize, maxValue, ): + if direction == -1: + return min( maxStepSize, self.lastValue ) + else: + return min( maxStepSize, maxValue - self.lastValue ) + +class DroneAndJump( Drunk ): + def __init__( self, maxValue ): + Drunk.__init__( self, maxValue ) + self.beforeLastValue = random.randint( 0, maxValue ) + self.lastValue = self.beforeLastValue + 1 + + def getNextValue( self, maxStepSize, maxValue ): + if self.beforeLastValue != self.lastValue: + self.lastValue = self.beforeLastValue + return self.beforeLastValue + + self.beforeLastValue = self.lastValue + self.lastValue = Drunk.getNextValue( self, abs(maxStepSize), maxValue ) + return self.lastValue + + def getStepSize( self, direction, maxStepSize, maxValue ): + if random.randint( 0, 100 ) < 25: + return Drunk.getStepSize( self, direction, maxStepSize, maxValue ) + else: + return Drunk.getStepSize( self, direction, 0, maxValue ) + +class Repeter( Drunk ): + def __init__( self, maxValue ): + Drunk.__init__( self, maxValue) + self.lastValue = random.randint( 0, maxValue) + + def getNextValue( self, maxStepSize, maxValue ): + self.lastValue = Drunk.getNextValue( self, abs(maxStepSize), maxValue ) + return self.lastValue + + def getStepSize( self, direction, maxStepSize, maxValue ): + if random.randint( 0, 100 ) < 15: + return Drunk.getStepSize( self, direction, maxStepSize, maxValue ) + else: + return Drunk.getStepSize( self, direction, 0, maxValue ) + +class Loopseg( Drunk ): + def __init__( self, maxValue ): + Drunk.__init__( self, maxValue ) + self.recordedValues = [] + self.recordState = 2 + self.recordPlayback = 0 + self.loopPlayback = 1 + self.recordLength = random.randint( 3, 6 ) + self.recordLoopTime = random.randint( 1, 4 ) + + def getNextValue( self, maxStepSize, maxValue ): + if self.recordState == 2: + self.lastValue = Drunk.getNextValue( self, maxStepSize, maxValue ) + self.recordState = random.choice([2, 2, 2, 1]) + + if len(self.recordedValues) != self.recordLength and self.recordState == 1: + self.lastValue = Drunk.getNextValue( self, maxStepSize, maxValue ) + self.recordedValues.append( self.lastValue ) + elif self.recordState == 1 or self.recordState == 0: + self.recordState = 0 + if self.recordPlayback < self.recordLength: + self.loopAround() + else: + if self.loopPlayback < self.recordLoopTime: + self.recordPlayback = 0 + self.loopPlayback += 1 + self.loopAround() + else: + self.recordedValues = [] + self.recordState = 2 + self.recordPlayback = 0 + self.loopPlayback = 1 + self.recordLength = random.randint( 3, 6 ) + self.recordLoopTime = random.randint( 1, 4 ) + self.lastValue = Drunk.getNextValue( self, maxStepSize, maxValue ) + self.recordedValues = [self.lastValue] + return self.lastValue + + def loopAround( self ): + self.lastValue = self.recordedValues[self.recordPlayback] + self.recordPlayback += 1 diff --git a/Generation/GenerationConstants.py b/Generation/GenerationConstants.py new file mode 100755 index 0000000..74b1aec --- /dev/null +++ b/Generation/GenerationConstants.py @@ -0,0 +1,160 @@ +class GenerationConstants: + + TWO_ROOT_TWELVE = pow( 2, 1./12 ) + MAX_NOTES_PER_BAR = 12 + + #STANDALONE_BEAT_LENGTH = 12 + + # Default parameters for algorithmic generation + DEFAULT_DENSITY = 0.7 + DEFAULT_RYTHM_REGULARITY = .75 + DEFAULT_STEP = -3 + DEFAULT_PITCH_REGULARITY = 0.5 + DEFAULT_ARTICULE = 0.7 + + DEFAULT_RYTHM_METHOD = 0 + DEFAULT_PITCH_METHOD = 0 + DEFAULT_PAN = 0.5 + + DEFAULT_PATTERN = 0 + + DEFAULT_PITCH_VARIATION = 0 + DEFAULT_RYTHM_VARIATION = 0 + + TABLE_ONSET_VALUES = [ 3, 4, 6, 8, 12, 18, 24, 36, 48 ] + + # scaling constants + MAJOR_SCALE = 0 + HARMONIC_MINOR_SCALE = 1 + NATURAL_MINOR_SCALE =2 + PHRYGIEN_SCALE = 3 + PENTATONIC_SCALE = 4 + BLUES_SCALE = 5 + + + SCALES = { MAJOR_SCALE : [ -12, -10, -8, -7, -5, -3, -1, 0, 2, 4, 5, 7, 9, 11, 12 ], + HARMONIC_MINOR_SCALE : [ -12, -10, -9, -7, -5, -4, -1, 0, 2, 3, 5, 7, 8, 11, 12 ], + NATURAL_MINOR_SCALE : [ -12, -10, -9, -7, -5, -4, -2, 0, 2, 3, 5, 7, 8, 10, 12 ], + PENTATONIC_SCALE : [ -12, -10, -7, -5, -3, 0, 2, 5, 7, 9, 12 ], + BLUES_SCALE : [ -12, -10, -9, -8, -7, -5, -3, -2, 0, 2, 3, 4, 5, 7, 9, 10, 12 ], + PHRYGIEN_SCALE : [ -12, -11, -9, -7, -5, -4, -2, 0, 1, 3, 5, 7, 8, 10, 12 ] } + + DEFAULT_SCALE = MAJOR_SCALE + + DEFAULT_TONIQUE = 36 + + I = [ 0, 2, 4, 7, 9, 11, 14 ] + II = [ 1, 3, 5, 8, 10, 12 ] + III = [ 2, 4, 6, 9, 11, 13 ] + IV = [ 0, 3, 5, 7, 10, 12, 14 ] + V = [ 1, 4, 6, 8, 11, 13 ] + VI = [ 0, 2, 5, 7, 9, 12, 14 ] + VII = [ 1, 3, 6, 8, 10, 13 ] + + CHORDS_TABLE = [ I, V, I, II, V, I, VI, II, V, I, IV, VI, II, V, I, V, VI ] +# CHORDS_TABLE = [I, V, I, V, I, V, I, V, I, V, I, V, I, V ] + # pitch patterns constants + # PITCH_PATTERNS = [ 'Drunk', 'DroneAndJump', 'Repeter', 'Loopseg' ] + + # Parameters for probability scaling function + REPETITION_SCALE_MIN_MAPPING = 0 + REPETITION_SCALE_MAX_MAPPING = 25 + REPETITION_SCALE_STEPS = 25 + DENSITY_SCALE_MIN_MAPPING = 0 + DENSITY_SCALE_MAX_MAPPING = 38 + DENSITY_SCALE_STEPS = 38 + ARTICULATION_SCALE_MIN_MAPPING = .3 + ARTICULATION_SCALE_MAX_MAPPING = 1 + ARTICULATION_SCALE_STEPS = 30 + + # Rythmic durations, in ticks, and how many to complete figure (celluleRythmSequence) + DOUBLE_TICK_DUR = 3 + DOUBLE_HOW_MANY = 2 + HALF_TRIPLET_TICK_DUR = 4 + HALF_TRIPLET_HOW_MANY = 3 + HOLE_TRIPLET_TICK_DUR = 8 + HOLE_TRIPLET_HOW_MANY = 3 + + # Random generators default values (xnoiseRythmSequence) + RANDOM_BETA_PARAM = 0.004 + RANDOM_EXPO_PARAM = 5 + RANDOM_GAUSS_PARAM1 = 0.5 + RANDOM_GAUSS_PARAM2 = 0.1 + RANDOM_WEIBULL_PARAM1 = 0.5 + + RANDOM_WEIBULL_PARAM2 = 2.5 + + # Onsets probability tables (drumRythmSequence) + + PUNCH_ACCENTS = [ [], + [ 0 ], + [ 0, 1 ], + [ 0, 2, 1 ], + [ 0, 2, 3, 1 ], + [ 0, 3, 2, 4, 1], + [ 0, 3, 2, 5, 1, 4 ], + [ 0, 2, 4, 6, 5, 3, 1 ], + [ 0, 4, 2, 6, 3, 7, 5, 1 ], + [ 0, 4, 6, 2, 8, 5, 3, 7, 1], + [ 0, 6, 4, 8, 2, 5, 7, 3, 9, 1], + [ 0, 4, 6, 10, 8, 2, 5, 7, 9, 3, 1], + [0, 6, 4, 2, 8, 10, 7, 5, 3, 9, 11, 1] ] + + + LOW_ACCENTS = [ [], + [ 0 ], + [ 0, 1 ], + [ 0, 2, 1 ], + [ 0, 2, 3, 1 ], + [ 0, 3, 2, 4, 1 ], + [ 0, 3, 2, 5, 1, 4 ], + [ 0, 2, 4, 6, 5, 3, 1 ], + [ 0, 4, 2, 6, 3, 7, 5, 1 ], + [ 0, 4, 6, 2, 8, 5, 3, 7, 1 ], + [ 0, 6, 4, 8, 2, 5, 7, 3, 9, 1 ], + [ 0, 4, 6, 10, 8, 2, 5, 7, 9, 3, 1 ], + [0, 6, 4, 2, 8, 10, 7, 5, 3, 9, 11, 1 ] ] + + MID_ACCENTS = [ [], + [ 0, 1 ], + [ 0, 2, 3, 1 ], + [ 0, 2, 4, 3, 1, 5 ], + [ 0, 4, 6, 2, 7, 1, 3, 5 ], + [ 0, 6, 4, 8, 2, 1, 5, 3, 9, 7 ], + [ 0, 6, 11, 5, 3, 9, 10, 2, 8, 7, 1, 4 ], + [ 0, 4, 8, 12, 10, 13, 11, 9, 3, 2, 6, 5, 7, 1 ], + [ 0, 8, 4, 12, 6, 14, 2, 10, 7, 15, 1, 9, 3, 11, 5, 13 ], + [ 0, 8, 16, 4, 12, 14, 6, 2, 10, 7, 15, 1, 9, 3, 17, 11, 5, 13], + [ 0, 10, 8, 4, 16, 12, 6, 14, 18, 2, 7, 9, 15, 3, 1, 19, 5, 11, 13, 17], + [ 0, 8, 10, 16, 4, 20, 6, 12, 18, 14, 2, 9, 7, 3, 15, 21, 19, 1, 5, 11, 17, 13], + [ 0, 10, 8, 4, 16, 6, 20, 22, 18, 12, 2, 14, 7, 9, 15, 3, 19, 1, 21, 5, 23, 17, 11, 13] ] + + HIGH_ACCENTS = [ [], + [ 1, 0 ], + [ 1, 3, 2, 0 ], + [ 5, 1, 3, 4, 2, 0 ], + [ 5, 3, 1, 7, 2, 6, 4, 0 ], + [ 7, 9, 3, 5, 1, 2, 8, 4, 6, 0 ], + [ 4, 1, 7, 5, 3, 9, 10, 2, 8, 11, 6, 0 ], + [ 1, 7, 8, 5, 10, 13, 11, 9, 3, 2, 6, 12, 4, 0 ], + [ 13, 5, 11, 3, 9, 1, 15, 10, 7, 2, 14, 6, 12, 4, 8, 0 ], + [ 13, 5, 11, 17, 3, 9, 1, 15, 7, 10, 2, 6, 14, 12, 4, 16, 8, 0 ], + [ 17, 13, 11, 5, 19, 1, 3, 15, 9, 7, 2, 18, 14, 6, 12, 16, 4, 8, 10, 0 ], + [ 13, 17, 11, 5, 1, 19, 21, 15, 3, 7, 9, 2, 14, 18, 12, 6, 20, 4, 16, 10, 8, 0 ], + [ 13, 11, 17, 23, 5, 21, 1, 19, 3, 15, 9, 7, 14, 2, 12, 18, 22, 20, 6, 16, 4, 8, 10, 0 ] ] + + # Gain boundaries + GAIN_MAX_BOUNDARY = 1. + GAIN_MID_MAX_BOUNDARY = .9 + GAIN_MID_MIN_BOUNDARY = .75 + GAIN_MIN_BOUNDARY = .65 + + # pitch mapping for drum kit + DRUMPITCH = {25: 24, 27: 26, 29: 28, 31: 30, 33: 32, 35: 34, 37: 36, 39: 38, 41: 40, 43: 42, 45: 44, 47: 46 } + + TRANSPOSE = [0.5, 0.52973154717964765, 0.56123102415468651, 0.59460355750136051, 0.6299605249474366, 0.66741992708501718, 0.70710678118654757, 0.74915353843834076, 0.79370052598409979, 0.8408964152537145, 0.89089871814033927, 0.94387431268169353, 1.0, 1.0594630943592953, 1.122462048309373, 1.189207115002721, 1.2599210498948732, 1.3348398541700344, 1.4142135623730951, 1.4983070768766815, 1.5874010519681994, 1.681792830507429, 1.7817974362806785, 1.8877486253633868, 2.0] + + CELLULES_MARKERS = [ 8, 16, 21, 24 ] + CELLULES = [ [ 3, 3, 3, 3 ], [ 3, 3, 6 ], [ 3, 6, 3 ], [ 6, 3, 3 ], [ 4, 4, 4 ], [ 4, 8 ], [ 8, 4 ], [ 6, 6 ], [ 12 ], [ 6, 12, 6 ], [ 8, 8, 8 ], [ 8, 16 ], [ 16, 8 ], [ 12, 12 ], [ 18, 6 ], + [ 6, 18 ], [ 24 ], [ 12, 12, 12 ], [ 18, 18 ], [ 24, 12 ], [ 12, 24 ], [ 36 ], [ 12, 24, 12 ], [ 24, 24 ], [ 48 ] ] + diff --git a/Generation/GenerationParametersWindow.py b/Generation/GenerationParametersWindow.py new file mode 100755 index 0000000..5964566 --- /dev/null +++ b/Generation/GenerationParametersWindow.py @@ -0,0 +1,206 @@ +import pygtk +pygtk.require('2.0') +import gtk + +from Generation.Generator import GenerationParameters +from Generation.Generator import VariationParameters +from Generation.GenerationConstants import GenerationConstants + +class GenerationParametersWindow( gtk.Window ): + def __init__( self, generateFunction, variateFunction, handleCloseWindowCallback ): + gtk.Window.__init__( self, gtk.WINDOW_TOPLEVEL ) + self.rythmMethod = GenerationConstants.DEFAULT_RYTHM_METHOD + self.pitchMethod = GenerationConstants.DEFAULT_PITCH_METHOD + self.pattern = GenerationConstants.DEFAULT_PATTERN + self.scale = GenerationConstants.DEFAULT_SCALE + self.pitchVariation = GenerationConstants.DEFAULT_PITCH_VARIATION + self.rythmVariation = GenerationConstants.DEFAULT_RYTHM_VARIATION + self.generateFunction = generateFunction + self.variateFunction = variateFunction + self.sourceVariation = 0 + self.setupWindow( handleCloseWindowCallback ) + + def setupWindow( self, handleCloseWindowCallback ): + self.set_position( gtk.WIN_POS_CENTER_ON_PARENT ) + self.set_title("Algorithmic generator") + self.set_border_width(5) + self.connect( "delete_event", handleCloseWindowCallback ) + self.mainBox = gtk.VBox(False, 5) + self.generationBox = gtk.VBox(False, 2) + self.variationBox = gtk.VBox(False, 2) + self.sliderBox = gtk.VBox(False, 2) + self.labelRythmMethodBox = gtk.VBox(False, 2) + self.rythmMethodBox = gtk.HBox(False, 2) + self.labelSourceVariationBox = gtk.VBox(False, 2) + self.sourceVariationBox = gtk.HBox(False, 2) + self.labelPitchMethodBox = gtk.VBox(False, 2) + self.pitchMethodBox = gtk.HBox(False, 2) + self.labelPatternBox = gtk.VBox(False, 2) + self.patternBox = gtk.HBox(False, 2) + self.labelScaleBox = gtk.VBox(False, 2) + self.scaleBox = gtk.HBox(False, 2) + self.buttonBox = gtk.HBox(False, 2) + + self.labelPitchVariationBox = gtk.VBox(False, 2) + self.pitchVariationBox = gtk.HBox(False, 2) + self.labelRythmVariationBox = gtk.VBox(False, 2) + self.rythmVariationBox = gtk.HBox(False, 2) + + self.generationBox.pack_start( gtk.Label( "GENERATION" ), False, False, 0 ) + # Create parameters sliders box + #TODO: remove magic numbers + self.densityAdjust = self.initSlider("density", GenerationConstants.DEFAULT_DENSITY, 0, 1, 0.01, 0, 2) + self.rythmRegularityAdjust = self.initSlider("rythm regularity", GenerationConstants.DEFAULT_RYTHM_REGULARITY, 0, 1, 0.01, 0, 2) + self.pitchStepAdjust = self.initSlider("pitch max step", GenerationConstants.DEFAULT_STEP, -10, 10, 1, 2, 0) + self.pitchRegularityAdjust = self.initSlider("pitch regularity", GenerationConstants.DEFAULT_PITCH_REGULARITY, 0, 1, 0.01, 0, 2) + self.articulationAdjust = self.initSlider("stacato / legato", GenerationConstants.DEFAULT_ARTICULE, 0, 1, 0.01, 0, 2) + self.generationBox.pack_start(self.sliderBox, 5) + + # Create melodic rythm methods box + self.labelRythmMethodBox.pack_start(gtk.Label("melodic rythm generation method"), False, False, 0) + self.generationBox.pack_start(self.labelRythmMethodBox, 3) + rythmMethodType = ['Cellule', 'Xnoise' ] + self.initRadioButton( rythmMethodType, self.rythmMethodCallback, self.rythmMethodBox ) + self.generationBox.pack_start(self.rythmMethodBox, 3) + + # Create pitch generation methods box + self.labelPitchMethodBox.pack_start(gtk.Label("pitch generation method"), False, False, 0) + self.generationBox.pack_start(self.labelPitchMethodBox, 3) + pitchMethodType = [ 'melodic', 'harmonic' ] + self.initRadioButton( pitchMethodType, self.pitchMethodCallback, self.pitchMethodBox ) + self.generationBox.pack_start(self.pitchMethodBox, 3) + + # Create pitch patterns box + self.labelPatternBox.pack_start(gtk.Label("pitch pattern"), False, False, 0) + self.generationBox.pack_start(self.labelPatternBox, 3) + patternType = [ 'Drunk', 'DroneJump', 'Repeter', 'Loopseg' ] + self.initRadioButton( patternType, self.patternCallback, self.patternBox ) + self.generationBox.pack_start(self.patternBox, 3) + + # Create scales box + self.labelScaleBox.pack_start(gtk.Label("scales"), False, False, 0) + self.generationBox.pack_start(self.labelScaleBox, 3) + scalesType = [ 'Major', 'Minor H', 'Minor N', 'Phrygien' ] + self.initRadioButton( scalesType, self.scaleCallback, self.scaleBox ) + self.generationBox.pack_start(self.scaleBox, 3) + + # create generate button + generateButton = gtk.Button('Generate') + generateButton.connect("clicked", self.generate) + self.buttonBox.pack_start(generateButton) + self.generationBox.pack_start(self.buttonBox, 3) + + # create variation box + self.variationBox.pack_start( gtk.Label( "VARIATION" ), False, False, 0 ) + + # create source variation box + self.labelSourceVariationBox.pack_start(gtk.Label("pages sources"), False, False, 0) + self.variationBox.pack_start(self.labelSourceVariationBox, 3) + sourceVariationType = [ 1, 2, 3, 4, 5 ] + self.initSourceRadioButton( sourceVariationType, self.sourceVariationCallback, self.sourceVariationBox ) + self.variationBox.pack_start(self.sourceVariationBox, 3) + + # create pitch variation box + self.labelPitchVariationBox.pack_start(gtk.Label("pitch variation"), False, False, 0) + self.variationBox.pack_start(self.labelPitchVariationBox, 3) + pitchVariationType = [ 'Copy', 'Markov', 'Reverse', 'Sort', 'Shuffle' ] + self.initRadioButton( pitchVariationType, self.pitchVariationCallback, self.pitchVariationBox ) + self.variationBox.pack_start(self.pitchVariationBox, 3) + + # create rythm variation box + self.labelRythmVariationBox.pack_start(gtk.Label("rythm variation"), False, False, 0) + self.variationBox.pack_start(self.labelRythmVariationBox, 3) + rythmVariationType = [ 'Copy', 'Reverse', 'Shuffle' ] + self.initRadioButton( rythmVariationType, self.rythmVariationCallback, self.rythmVariationBox ) + self.variationBox.pack_start(self.rythmVariationBox, 3) + + # create variate button + variateButton = gtk.Button('Variate') + variateButton.connect("clicked", self.variate) + self.variationBox.pack_start(variateButton, 3) + + self.mainBox.pack_start(self.generationBox) + self.mainBox.pack_start(self.variationBox) + + self.add(self.mainBox) + + def getGenerationParameters( self ): + return GenerationParameters( self.densityAdjust.value, + self.rythmRegularityAdjust.value, + self.pitchStepAdjust.value, + self.pitchRegularityAdjust.value, + self.articulationAdjust.value, + self.rythmMethod, + self.pitchMethod, + self.pattern, + self.scale ) + + def generate(self, data=None): + self.generateFunction( self.getGenerationParameters() ) + + def getVariationParameters( self ): + return VariationParameters( self.sourceVariation, + self.pitchVariation, + self.rythmVariation ) + + def variate( self, data=None ): + self.variateFunction( self.getVariationParameters() ) + + def rythmMethodCallback( self, widget, rythmMethod ): + if widget.get_active(): + self.rythmMethod = rythmMethod + + def pitchMethodCallback( self, widget, pitchMethod ): + if widget.get_active(): + self.pitchMethod = pitchMethod + + def patternCallback( self, widget, pattern ): + if widget.get_active(): + self.pattern = pattern + + def scaleCallback( self, widget, scale ): + if widget.get_active(): + self.scale = scale + + def sourceVariationCallback( self, widget, data ): + if widget.get_active(): + self.sourceVariation = int( data ) + + def pitchVariationCallback( self, widget, data ): + if widget.get_active(): + self.pitchVariation = data + + def rythmVariationCallback( self, widget, data ): + if widget.get_active(): + self.rythmVariation = data + + def initSlider(self, label, initValue, minValue, maxValue, incStep, policy, digits): + sliderAdjust = gtk.Adjustment(initValue, minValue, maxValue, incStep, incStep, 0) + slider = gtk.HScale(sliderAdjust) + slider.set_update_policy(policy) + slider.set_digits(digits) + slider.set_value_pos(1) + slider.set_size_request(250, 25) + self.sliderBox.pack_start(gtk.Label(label), False, False, 0) + self.sliderBox.pack_start(slider) + return sliderAdjust + + def initRadioButton( self, labelList, methodCallback, box ): + for i in range( len( labelList ) ): + if i == 0: + button = gtk.RadioButton( None, labelList[ i ] ) + else: + button = gtk.RadioButton( button, labelList[ i ] ) + button.connect( "toggled", methodCallback, i ) + box.pack_start( button, True, True, 0 ) + + def initSourceRadioButton( self, labelList, methodCallback, box ): + for i in range( len( labelList ) ): + if i == 0: + button = gtk.RadioButton(None, str( labelList[ i ] ) ) + else: + button = gtk.RadioButton( button, str( labelList[ i ] ) ) + button.connect( "toggled", methodCallback, i ) + box.pack_start( button, True, True, 0 ) + if i == 0: + button.set_active(True) diff --git a/Generation/GenerationPitch.py b/Generation/GenerationPitch.py new file mode 100644 index 0000000..bc38ee1 --- /dev/null +++ b/Generation/GenerationPitch.py @@ -0,0 +1,58 @@ +import random +import Drunk + +import Config +from Generation.GenerationConstants import GenerationConstants + +class GenerationPitch: + def __init__( self ): + fakeMaximum = 4 + self.drunk = Drunk.Drunk( fakeMaximum ) + self.droneAndJump = Drunk.DroneAndJump( fakeMaximum ) + self.repeter = Drunk.Repeter( fakeMaximum ) + self.loopseg = Drunk.Loopseg( fakeMaximum ) + + self.harmonicDrunk = Drunk.Drunk( fakeMaximum ) + self.harmonicDroneAndJump = Drunk.DroneAndJump( fakeMaximum ) + self.harmonicRepeter = Drunk.Repeter( fakeMaximum ) + self.harmonicLoopseg = Drunk.Loopseg( fakeMaximum ) + + def chooseMethod( self, pattern ): + if pattern == 0: return self.drunk + elif pattern == 1: return self.droneAndJump + elif pattern == 2: return self.repeter + elif pattern == 3: return self.loopseg + + def harmonicChooseMethod( self, pattern ): + if pattern == 0: return self.harmonicDrunk + elif pattern == 1: return self.harmonicDroneAndJump + elif pattern == 2: return self.harmonicRepeter + elif pattern == 3: return self.harmonicLoopseg + + def drunkPitchSequence(self, length, parameters, table_pitch): + pitchMethod = self.chooseMethod( parameters.pattern ) + pitchSequence = [] + numberOfPitch = int( ( 1 - parameters.pitchRegularity ) * 10 + 1 ) + for i in range(numberOfPitch): + pitchSequence.append((table_pitch[pitchMethod.getNextValue(parameters.step, (len(table_pitch)-1))]) + GenerationConstants.DEFAULT_TONIQUE) + for i in range( length - numberOfPitch ): + position = i % numberOfPitch + pitchSequence.append( pitchSequence[ position ] ) + return pitchSequence + + def drumPitchSequence(self, length, parameters, drumPitch, table_pitch=None): + pitchSequence = [] + for i in range(length): + pitchSequence.append(drumPitch[ random.randint( 0, ( len( drumPitch ) - 1 ) ) ] ) + return pitchSequence + + def harmonicPitchSequence( self, rythmSequence, parameters, table_pitch, harmonicSequence ): + pitchSequence = [] + pitchMethod = self.harmonicChooseMethod( parameters.pattern ) + for onset in rythmSequence: + beat = int( onset / Config.TICKS_PER_BEAT ) + pitchSequence.append( ( table_pitch[ harmonicSequence[ beat ] [ pitchMethod.getNextValue(3, ( len( harmonicSequence[ beat ]) - 1) ) ]] ) + GenerationConstants.DEFAULT_TONIQUE ) + # pitchSequence.append( ( table_pitch[ random.choice( harmonicSequence[ beat ] ) ] ) + GenerationConstants.DEFAULT_TONIQUE ) + return pitchSequence + + diff --git a/Generation/GenerationRythm.py b/Generation/GenerationRythm.py new file mode 100644 index 0000000..fef9d42 --- /dev/null +++ b/Generation/GenerationRythm.py @@ -0,0 +1,174 @@ +import Utils +import random + +import Config +from Generation.GenerationConstants import GenerationConstants + +class GenerationRythm: + def __init__( self, trackInstrument, barLength ): + self.trackInstrument = trackInstrument + self.barLength = barLength + + def celluleRythmSequence(self, parameters ): + rythmSequence = [0, ] + self.count = 0 + lastOnsetTime = 0 + + onsetValue = int( ( 1 - parameters.density ) * 8 ) + onsetDeviation = int( ( 1 - parameters.rythmRegularity ) * 4 ) + currentOnsetValue = onsetValue + ( random.randint( 0, onsetDeviation ) - ( onsetDeviation / 2 ) ) + if currentOnsetValue < 0: + currentOnsetValue == 0 + elif currentOnsetValue > 8: + currentOnsetValue == 8 + else: + currentOnsetValue = currentOnsetValue + + onsetDelta = GenerationConstants.TABLE_ONSET_VALUES[ currentOnsetValue ] + + for i in range( int( self.barLength / Config.TICKS_PER_BEAT * 8 ) ): + if self.count == 0: + currentOnsetValue = onsetValue + ( random.randint( 0, onsetDeviation ) - ( onsetDeviation / 2 ) ) + if currentOnsetValue < 0: + currentOnsetValue == 0 + elif currentOnsetValue > 8: + currentOnsetValue == 8 + else: + currentOnsetValue = currentOnsetValue + onsetDelta = GenerationConstants.TABLE_ONSET_VALUES[ currentOnsetValue ] + + self.makeCellule(onsetDelta, GenerationConstants.DOUBLE_TICK_DUR, GenerationConstants.DOUBLE_HOW_MANY) + self.makeCellule(onsetDelta, GenerationConstants.HALF_TRIPLET_TICK_DUR, GenerationConstants.HALF_TRIPLET_HOW_MANY) + self.makeCellule(onsetDelta, GenerationConstants.HOLE_TRIPLET_TICK_DUR, GenerationConstants.HOLE_TRIPLET_HOW_MANY) + + onsetTime = onsetDelta + lastOnsetTime + lastOnsetTime = onsetTime + + if onsetTime < self.barLength: + rythmSequence.append(onsetTime) + else: + break + return rythmSequence + + def xnoiseRythmSequence(self, parameters ): + rythmSequence = [] + onsetTime = None + randomParamScaler = parameters.rythmRegularity * 2 + 0.5 +# need radioButton with 0 for random choose and each generator independant + whichRandomGenerator = random.randint(0, 4) + maximumNumberOfNotes = int( (parameters.density) * GenerationConstants.MAX_NOTES_PER_BAR) + + for i in range(maximumNumberOfNotes): + while onsetTime in rythmSequence: + if whichRandomGenerator == 0: + onsetTime = random.expovariate(GenerationConstants.RANDOM_EXPO_PARAM * randomParamScaler) + elif whichRandomGenerator == 1: + onsetTime = 1 - random.expovariate(GenerationConstants.RANDOM_EXPO_PARAM * randomParamScaler) + elif whichRandomGenerator == 2: + onsetTime = random.gauss(GenerationConstants.RANDOM_GAUSS_PARAM1, + GenerationConstants.RANDOM_GAUSS_PARAM2 * (3 - randomParamScaler)) + elif whichRandomGenerator == 3: + onsetTime = random.betavariate(GenerationConstants.RANDOM_BETA_PARAM * randomParamScaler, + GenerationConstants.RANDOM_BETA_PARAM * randomParamScaler) + elif whichRandomGenerator == 4: + onsetTime = random.weibullvariate(GenerationConstants.RANDOM_WEIBULL_PARAM1, + GenerationConstants.RANDOM_WEIBULL_PARAM2 * randomParamScaler) + + onsetTime = int(onsetTime * (int(( self.barLength - 1) / GenerationConstants.DOUBLE_TICK_DUR))) * GenerationConstants.DOUBLE_TICK_DUR + + if onsetTime < 0: + onsetTime = 0 + elif onsetTime > ( self.barLength - GenerationConstants.DOUBLE_TICK_DUR): + onsetTime = ( self.barLength - GenerationConstants.DOUBLE_TICK_DUR) + else: + onsetTime = onsetTime + + rythmSequence.append(onsetTime) + + rythmSequence.sort() + return rythmSequence + + def drumRythmSequence(self, parameters ): + rythmSequence = [] + binSelection = [] + downBeats = [] + upBeats = [] + beats = [] + countDown = 0 + onsetTime = None + beatsPerPage = int( self.barLength / Config.TICKS_PER_BEAT ) + + if Config.INSTRUMENTS[ self.trackInstrument ].instrumentRegister == Config.PUNCH: + registerDensity = 0.5 + downBeatRecurence = 4 + for beat in range( beatsPerPage ): + beats.append( beat * Config.TICKS_PER_BEAT ) + for i in range( len( beats ) ): + print ( beats[ GenerationConstants.PUNCH_ACCENTS[ beatsPerPage ][ i ] ], pow( float( len( beats ) - i) / len( beats ), 1.5 ) * 100.) + downBeats.append( ( beats[ GenerationConstants.PUNCH_ACCENTS[ beatsPerPage ][ i ] ], pow( float( len( beats ) - i) / len( beats ), 1.5 ) * 100.) ) + for downBeat in downBeats: + upBeats.append( ( downBeat[ 0 ] + Config.TICKS_PER_BEAT , downBeat[ 1 ] ) ) + + if Config.INSTRUMENTS[ self.trackInstrument ].instrumentRegister == Config.LOW: + registerDensity =1.5 + downBeatRecurence = 4 + for beat in range( beatsPerPage ): + beats.append( beat * Config.TICKS_PER_BEAT ) + for i in range( len( beats ) ): + downBeats.append( ( beats[ GenerationConstants.LOW_ACCENTS[ beatsPerPage ][ i ] ], pow( float( len( beats ) - i) / len( beats ), 1.5 ) * 100.) ) + for downBeat in downBeats: + upBeats.append( ( downBeat[ 0 ] + Config.TICKS_PER_BEAT / 2 , downBeat[ 1 ] ) ) + + if Config.INSTRUMENTS[ self.trackInstrument ].instrumentRegister == Config.MID: + registerDensity = 1 + downBeatRecurence = 1 + for beat in range( beatsPerPage ): + beats.append( beat * Config.TICKS_PER_BEAT ) + beats.append( beat * Config.TICKS_PER_BEAT + ( Config.TICKS_PER_BEAT / 2 ) ) + for i in range( len( beats ) ): + downBeats.append( ( beats[ GenerationConstants.MID_ACCENTS[ beatsPerPage ][ i ] ], pow( float( len( beats ) - i) / len( beats ), 1.5 ) * 100.) ) + for downBeat in downBeats: + upBeats.append( ( downBeat[ 0 ] + Config.TICKS_PER_BEAT / 4 , downBeat[ 1 ] ) ) + + if Config.INSTRUMENTS[ self.trackInstrument ].instrumentRegister == Config.HIGH: + registerDensity = 1.5 + downBeatRecurence = 1 + for beat in range( beatsPerPage ): + beats.append( beat * Config.TICKS_PER_BEAT ) + beats.append( beat * Config.TICKS_PER_BEAT + ( Config.TICKS_PER_BEAT / 2 ) ) + for i in range( len( beats ) ): + downBeats.append( ( beats[ GenerationConstants.HIGH_ACCENTS[ beatsPerPage ][ i ] ], pow( float( len( beats ) - i) / len( beats ), 1.5 ) * 100.) ) + for downBeat in downBeats: + upBeats.append( ( downBeat[ 0 ] + Config.TICKS_PER_BEAT / 4 , downBeat[ 1 ] ) ) + + for i in range( int( parameters.density * registerDensity * len( downBeats ) ) ): + if random.randint( 0, 100 ) < ( parameters.rythmRegularity * 100 * downBeatRecurence ) and binSelection.count( 1 ) < len( downBeats ): + binSelection.append( 1 ) + else: + if binSelection.count( 0 ) < len( downBeats ): + binSelection.append( 0 ) + else: + binSelection.append( 1 ) + + countDown = binSelection.count( 1 ) + + for i in range( countDown ): + while onsetTime in rythmSequence or onsetTime == None: + onsetTime = Utils.prob2( downBeats ) + rythmSequence.append( onsetTime ) + + for i in range( len( binSelection ) - countDown ): + while onsetTime in rythmSequence or onsetTime == None: + onsetTime = Utils.prob2( upBeats ) + rythmSequence.append( onsetTime ) + + rythmSequence.sort() + return rythmSequence + + def makeCellule( self, currentDuration, targetDuration, threshold ): + threshold = threshold - 1 + if currentDuration == targetDuration: + if self.count < threshold: + self.count += 1 + else: + self.count = 0 diff --git a/Generation/Generator.py b/Generation/Generator.py new file mode 100755 index 0000000..447f24c --- /dev/null +++ b/Generation/Generator.py @@ -0,0 +1,243 @@ +import random +import math + +import Utils +import Drunk + +import Config +from Util.CSoundNote import CSoundNote +from Generation.VariationPitch import * +from Generation.VariationRythm import * +from Generation.GenerationConstants import GenerationConstants +from Generation.GenerationRythm import GenerationRythm +from Generation.GenerationPitch import GenerationPitch + +class GenerationParameters: + def __init__( self, + density = GenerationConstants.DEFAULT_DENSITY, + rythmRegularity = GenerationConstants.DEFAULT_RYTHM_REGULARITY, + step = GenerationConstants.DEFAULT_STEP, + pitchRegularity = GenerationConstants.DEFAULT_PITCH_REGULARITY, + articule = GenerationConstants.DEFAULT_ARTICULE, + rythmMethod = GenerationConstants.DEFAULT_RYTHM_METHOD, + pitchMethod = GenerationConstants.DEFAULT_PITCH_METHOD, + pattern = GenerationConstants.DEFAULT_PATTERN, + scale = GenerationConstants.DEFAULT_SCALE ): + self.density = density + self.rythmRegularity = rythmRegularity + self.step = step + self.pitchRegularity = pitchRegularity + self.articule = articule + self.rythmMethod = rythmMethod + self.pitchMethod = pitchMethod + self.pattern = pattern + self.scale = scale + +def generator1( + parameters, # algorithm-specific parameters + volume, # [trackID: float(volume) ] + instrument, # [trackID: instrument] + tempo, # integer bpm + nbeats, # integer + trackIDs, # list of trackIDs to generate + pageIDs, # list of pageIDs to generate + trackDictionary # map [ trackID : [ pageID : events ] ] + ): + + pitchMarkov = PitchMarkov() + pitchReverse = PitchReverse() + pitchSort = PitchSort() + pitchShuffle = PitchShuffle() + + makePitch = GenerationPitch() + makeHarmonicSequence = Drunk.Drunk( 7 ) + + rythmShuffle = RythmShuffle( ) + rythmReverse = RythmReverse( ) + + def makeGainSequence( onsetList ): + gainSequence = [] + for onset in onsetList: + if onset == 0: + gain = random.uniform(GenerationConstants.GAIN_MID_MAX_BOUNDARY, GenerationConstants.GAIN_MAX_BOUNDARY) + elif ( onset % Config.TICKS_PER_BEAT) == 0: + gain = random.uniform(GenerationConstants.GAIN_MID_MIN_BOUNDARY, GenerationConstants.GAIN_MID_MAX_BOUNDARY) + else: + gain = random.uniform(GenerationConstants.GAIN_MIN_BOUNDARY, GenerationConstants.GAIN_MID_MIN_BOUNDARY) + gainSequence.append(gain) + return gainSequence + + def makeDurationSequence( onsetList, parameters, table_duration, barLength, currentInstrument ): + durationSequence = [] + fullDurationSequence = [] + if len( onsetList ) > 1: + for i in range(len(onsetList) - 1): + duration = (onsetList[i+1] - onsetList[i]) * Utils.prob2( table_duration ) + if duration == (onsetList[i+1] - onsetList[i]): + fullDurationSequence.append(True) + else: + fullDurationSequence.append(False) + + if Config.INSTRUMENTS[ currentInstrument ].soundClass == 'drum': + duration = GenerationConstants.DOUBLE_TICK_DUR / 2 + + durationSequence.append(duration) + + if Config.INSTRUMENTS[ currentInstrument ].soundClass == 'drum': + durationSequence.append( GenerationConstants.DOUBLE_TICK_DUR / 2) + else: + durationSequence.append(( barLength - onsetList[-1]) * Utils.prob2( table_duration )) + fullDurationSequence.append(False) + elif len( onsetList ) == 1: + if Config.INSTRUMENTS[ currentInstrument ].soundClass == 'drum': + durationSequence.append( GenerationConstants.DOUBLE_TICK_DUR / 2 ) + else: + durationSequence.append( ( barLength - onsetList[ 0 ] ) * Utils.prob2( table_duration )) + fullDurationSequence.append( False ) + return durationSequence, fullDurationSequence + + def pageGenerate( parameters, trackID, pageID, selectedPageCount, lastPageID, trackOfNotes, drumPitch = None ): + trackNotes = trackOfNotes + barLength = Config.TICKS_PER_BEAT * nbeats + if drumPitch: + currentInstrument = Config.DRUM1INSTRUMENTS[ drumPitch[ 0 ] ] + else: + drumPitch = [ 36 ] + currentInstrument = instrument[ trackID ] + + makeRythm = GenerationRythm( currentInstrument, barLength ) + + table_duration = Utils.scale(parameters.articule, GenerationConstants.ARTICULATION_SCALE_MIN_MAPPING, + GenerationConstants.ARTICULATION_SCALE_MAX_MAPPING, + GenerationConstants.ARTICULATION_SCALE_STEPS) + table_pitch = GenerationConstants.SCALES[parameters.scale] + + if Config.INSTRUMENTS[ currentInstrument ].soundClass == 'drum': + rythmSequence = makeRythm.drumRythmSequence(parameters) + pitchSequence = makePitch.drumPitchSequence(len(rythmSequence), parameters, drumPitch, table_pitch ) + elif Config.INSTRUMENTS[ currentInstrument ].soundClass == 'melo': + if parameters.rythmMethod == 0: + rythmSequence = makeRythm.celluleRythmSequence(parameters) + elif parameters.rythmMethod == 1: + rythmSequence = makeRythm.xnoiseRythmSequence(parameters) + if parameters.pitchMethod == 0: + pitchSequence = makePitch.drunkPitchSequence(len(rythmSequence), parameters, table_pitch) + elif parameters.pitchMethod == 1: + pitchSequence = makePitch.harmonicPitchSequence( rythmSequence, parameters, table_pitch, harmonicSequence ) + gainSequence = makeGainSequence(rythmSequence) + durationSequence, fullDurationSequence = makeDurationSequence(rythmSequence, parameters, table_duration, barLength, currentInstrument) + + for i in range(len(rythmSequence)): + trackNotes.append( CSoundNote( rythmSequence[i], pitchSequence[i], gainSequence[i], + GenerationConstants.DEFAULT_PAN, durationSequence[i], trackID, + fullDurationSequence[i], instrument[ trackID ] ) ) +# del trackDictionary[ trackID ][ pageID ] + trackDictionary[ trackID ][ pageID ] = trackNotes + +################################################################################## + # begin generate() + harmonicSequence = [] + for i in range( nbeats ): + harmonicSequence.append( + GenerationConstants.CHORDS_TABLE[ makeHarmonicSequence.getNextValue( 2, len( GenerationConstants.CHORDS_TABLE ) - 1 ) ] ) + + for trackID in trackIDs: + if instrument[ trackID ] == 'drum1kit': + if parameters.rythmRegularity > 0.75: + pitchOfStream = [ [ 24 ], [30] , [ 40 ], [ 46 ] ] + elif parameters.rythmRegularity > 0.5: + pitchOfStream = [ [ 24, 28 ], [ 30, 32 ], [ 36, 38, 40 ], [ 46, 48 ] ] + elif parameters.rythmRegularity > 0.25: + pitchOfStream = [ [ 24, 26, 28 ], [ 30, 32, 34 ], [ 38, 40 ], [ 42, 46, 48 ] ] + else: + pitchOfStream = [ [ 24, 26, 28 ], [ 30, 32, 34 ], [ 38, 40 ], [ 42, 44, 46, 48 ] ] + selectedPageCount = 0 + lastPageID = 0 + for pageID in pageIDs: + trackOfNotes = [] +# del trackDictionary[ trackID ][ pageID ] + if instrument[ trackID ] == 'drum1kit': + for drumPitch in pitchOfStream: + pageGenerate( parameters, trackID, pageID, selectedPageCount, lastPageID, trackOfNotes, drumPitch ) + else: + pageGenerate( parameters, trackID, pageID, selectedPageCount, lastPageID, trackOfNotes, drumPitch = None ) + + selectedPageCount += 1 + lastPageID = pageID + +class VariationParameters: + def __init__( self, sourceVariation, pitchVariation = 0, rythmVariation = 0 ): + self.sourceVariation = sourceVariation + self.pitchVariation = pitchVariation + self.rythmVariation = rythmVariation + + +def variate( + parameters, # algorithm-specific parameters + volume, # [trackID: float(volume) ] + instrument, # [trackID: instrument] + tempo, # integer bpm + nbeats, # integer + trackIDs, # list of trackIDs to generate + pageIDs, # list of pageIDs to generate + trackDictionary # map [ trackID : [ pageID : events ] ] + ): + + pitchMarkov = PitchMarkov() + pitchReverse = PitchReverse() + pitchSort = PitchSort() + pitchShuffle = PitchShuffle() + + makePitch = GenerationPitch() + makeHarmonicSequence = Drunk.Drunk( 7 ) + rythmShuffle = RythmShuffle( ) + rythmReverse = RythmReverse( ) + + def pageVariate( parameters, trackID, pageID ): + tempTrackNotes = [] + trackNotes = [] + for note in trackDictionary[ trackID ][ parameters.sourceVariation ]: + tempTrackNotes.append( note.clone() ) + + if parameters.rythmVariation == 0: + for note in tempTrackNotes: + trackNotes.append( note.clone() ) + if parameters.rythmVariation == 1: + for note in rythmReverse.getNewList( tempTrackNotes, nbeats ): + trackNotes.append( note.clone() ) + if parameters.rythmVariation == 2: + for note in rythmShuffle.getNewList( tempTrackNotes , nbeats): + trackNotes.append( note.clone() ) + + del trackDictionary[ trackID ][ pageID ] + trackDictionary[ trackID ][ pageID ] = trackNotes + + tempTrackNotes = [] + trackNotes = [] + for note in trackDictionary[ trackID ][ parameters.sourceVariation ]: + tempTrackNotes.append( note.clone() ) + + if parameters.pitchVariation == 0: + for note in tempTrackNotes: + trackNotes.append( note.clone() ) + elif parameters.pitchVariation == 1: + for note in pitchMarkov.getNewList( tempTrackNotes, 1 ): + trackNotes.append( note.clone() ) + elif parameters.pitchVariation == 2: + for note in pitchReverse.reorderPitch( tempTrackNotes ): + trackNotes.append( note.clone() ) + elif parameters.pitchVariation == 3: + for note in pitchSort.reorderPitch( tempTrackNotes ): + trackNotes.append( note.clone() ) + elif parameters.pitchVariation == 4: + for note in pitchShuffle.reorderPitch( tempTrackNotes ): + trackNotes.append( note.clone() ) + + del trackDictionary[ trackID ][ pageID ] + trackDictionary[ trackID ][ pageID ] = trackNotes + + for trackID in trackIDs: + for pageID in pageIDs: + pageVariate( parameters, trackID, pageID ) + + diff --git a/Generation/Utils.py b/Generation/Utils.py new file mode 100755 index 0000000..7f00525 --- /dev/null +++ b/Generation/Utils.py @@ -0,0 +1,71 @@ +import random +import time +import math + +#---------------------------------------------------------------------- +# TODO: replace magic numbers with constants +# http://en.wikipedia.org/wiki/Magic_number_(programming) +#---------------------------------------------------------------------- + +def prob(x): + sum1 = 0 + sum2 = 0 + + for i in x: + sum1 = sum1 + i + + val = sum1 * random.randint(0, 32767) / 32768 + + for i in range(len(x)): + sum2 = sum2 + x[i] + if x[i]: + if sum2 >= val: + return i + break + +def prob2(x): + sum1 = 0 + sum2 = 0 + + for i in x: + sum1 = sum1 + i[1] + + val = sum1 * random.randint(0, 32767) / 32768 + + for i in x: + sum2 = sum2 + i[1] + if i[1]: + if sum2 >= val: + return i[0] + break + +def scale(val, mini=0., maxi=1., length=100): + slope = [] + + if (1.- val) <= 0.5: + low_val = (pow(1.-((1.- val)*2.),4.)*(-50.5)+0.5) + else: + low_val = 1.- val + + if val <= 0.5: + high_val = (pow(1.-(val * 2.),4.)*(-50.5)+0.5) + else: + high_val = val + + step = (maxi - mini) * (1. / length) + + for i in range(length + 1): + temp = i * (1. / length) * (high_val - low_val) + low_val + if temp < 0: + temp = 0 + elif temp > 1: + temp = 1 + else: + temp = temp + + slope.append(((step * i) + mini, int(temp * 100))) + + return slope + +def midtotrans(x): + return pow(1.059463, x - 36) diff --git a/Generation/VariationPitch.py b/Generation/VariationPitch.py new file mode 100644 index 0000000..5a2b151 --- /dev/null +++ b/Generation/VariationPitch.py @@ -0,0 +1,82 @@ +import random + +class PitchReverse: + def __init__( self ): + self.pitchList = [] + + def reorderPitch( self, notesList ): + self.extractOneValue(notesList) + self.pitchList.reverse() + for i in range(len(notesList)): + notesList[i].pitch = self.pitchList[i] + + return notesList + + def extractOneValue( self, notesList ): + self.pitchList = [] + for note in notesList: + self.pitchList.append(note.pitch) + +class PitchSort( PitchReverse ): + def __init__( self ): + PitchReverse.__init__( self ) + + def reorderPitch( self, notesList ): + PitchReverse.extractOneValue(self, notesList) + self.pitchList.sort() + for i in range(len(notesList)): + notesList[i].pitch = self.pitchList[i] + + return notesList + +class PitchShuffle( PitchReverse ): + def __init__( self ): + PitchReverse.__init__ ( self ) + + def reorderPitch( self, notesList ): + PitchReverse.extractOneValue(self, notesList) + self.pitchList = random.sample(self.pitchList, len(self.pitchList)) + for i in range(len(notesList)): + notesList[i].pitch = self.pitchList[i] + + return notesList + +class PitchMarkov: + def __init__( self ): + self.originalList = [] + + def getNewList( self, notesList, order=1 ): + self.playedNotes = [] + self.extractOneValue( notesList, order ) + self.playedNotes = self.originalList[:order] + + for i in range(len(self.originalList) - order): + self.playedNotes.append(self.pickupNewValue(order)) + + for i in range(len(notesList)): + notesList[i].pitch = self.playedNotes[i] + + return notesList + + def extractOneValue( self, notesList, order ): + self.originalList = [] + for note in notesList: + self.originalList.append(note.pitch) + for i in range(order): + self.originalList.append(self.originalList[i]) + + def pickupNewValue( self, order ): + condition = False + self.probTable = [] + for ilist in range(len(self.originalList) - order): + for iord in range(order): + if self.playedNotes[len(self.playedNotes) - (iord + 1)] != self.originalList[(order - 1) + ilist - iord]: + condition = False + break + else: + condition = True + + if condition == True: + self.probTable.append(self.originalList[ilist + order]) + + return self.probTable[random.randint(0, (len(self.probTable) - 1))] diff --git a/Generation/VariationRythm.py b/Generation/VariationRythm.py new file mode 100644 index 0000000..460f4f4 --- /dev/null +++ b/Generation/VariationRythm.py @@ -0,0 +1,75 @@ +import random + +from Framework.Constants import Constants + +# remplacer position dans notesList par l'attribut de CSoundNote +class RythmShuffle: + + def getNewList( self, notesList, nbeats ): + self.barLength = Constants.TICKS_PER_BEAT * nbeats + self.onsetDelta = 0 + self.newOnsetList = [] + self.oldDuration = [] + self.newDuration = [] + self.extractOnsetValue(notesList) + + self.newOnsetList = random.sample(range(len(self.originalList)), len(self.originalList)) + self.getOldDuration(notesList) + self.getNewDuration(notesList) + + for i in range(len(notesList)): + notesList[i].onset = self.onsetDelta + notesList[i].duration = self.oldDuration[i] * self.newDuration[i] + self.onsetDelta = self.onsetDelta + self.originalList[self.newOnsetList[i]] + + return notesList + + def extractOnsetValue( self, notesList ): + self.originalList = [] + for note in notesList: + self.originalList.append(note.onset) + + for i in range(len(self.originalList) -1): + self.originalList[i] = self.originalList[i+1] - self.originalList[i] + + self.originalList[-1] = self.barLength - (self.originalList[-1] % self.barLength) + + def getOldDuration( self, notesList ): + for i in range(len(notesList)): + if (i+1) == len(notesList): + self.oldDuration.append(notesList[i].duration / (self.barLength - (notesList[i].onset % self.barLength))) + else: + self.oldDuration.append(notesList[i].duration / (notesList[i+1].onset - notesList[i].onset)) + + def getNewDuration( self, notesList ): + for i in self.newOnsetList: + if (i+1) == len(notesList): + self.newDuration.append(self.barLength - (notesList[i].onset % self.barLength)) + else: + self.newDuration.append(notesList[i+1].onset - notesList[i].onset) + +class RythmReverse( RythmShuffle ): + + def getNewList( self, notesList, nbeats ): + self.barLength = Constants.TICKS_PER_BEAT * nbeats + self.onsetDelta = 0 + self.newOnsetList = [] + self.oldDuration = [] + self.newDuration = [] + RythmShuffle.extractOnsetValue( self, notesList ) + + for i in range( len( self.originalList ) ): + self.newOnsetList.append( i ) + + self.newOnsetList.reverse() + print len( self.newOnsetList ), len( notesList ) + + RythmShuffle.getOldDuration( self, notesList ) + RythmShuffle.getNewDuration( self, notesList ) + + for i in range(len(notesList)): + notesList[i].onset = self.onsetDelta + notesList[i].duration = self.oldDuration[i] * self.newDuration[i] + self.onsetDelta = self.onsetDelta + self.originalList[self.newOnsetList[i]] + + return notesList diff --git a/Generation/__init__.py b/Generation/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Generation/__init__.py |