Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Generation
diff options
context:
space:
mode:
authorjaberg <james@localhost.localdomain>2007-01-07 21:24:04 (GMT)
committer jaberg <james@localhost.localdomain>2007-01-07 21:24:04 (GMT)
commit1becac24dfa6bd0cee4ae46f4c0b8630bfbb6269 (patch)
tree70d602342d546fd8c268143b54d46b8ca580a7ed /Generation
parent2a940a71469b2b5964e8deab3ed6db0254424671 (diff)
unify_edit init
Diffstat (limited to 'Generation')
-rwxr-xr-xGeneration/Drunk.py118
-rwxr-xr-xGeneration/GenerationConstants.py160
-rwxr-xr-xGeneration/GenerationParametersWindow.py206
-rw-r--r--Generation/GenerationPitch.py58
-rw-r--r--Generation/GenerationRythm.py174
-rwxr-xr-xGeneration/Generator.py243
-rwxr-xr-xGeneration/Utils.py71
-rw-r--r--Generation/VariationPitch.py82
-rw-r--r--Generation/VariationRythm.py75
-rw-r--r--Generation/__init__.py0
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