From e12dbff4dda5aafbaac98f75f0467ef00dc06c32 Mon Sep 17 00:00:00 2001 From: Nat Date: Thu, 13 Sep 2007 15:55:52 +0000 Subject: Activity split --- (limited to 'common/Generation') diff --git a/common/Generation/Drunk.py b/common/Generation/Drunk.py new file mode 100755 index 0000000..1bc3bbb --- /dev/null +++ b/common/Generation/Drunk.py @@ -0,0 +1,162 @@ +# 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 + +class Drunk: + def __init__( self, minValue, maxValue, trackLength=None ): + self.minValue = min(minValue, maxValue) + self.maxValue = max(minValue, maxValue) + self.lastValue = random.randint( self.minValue, self.maxValue ) + + + def getNextValue( self, maxStepSize, maxValue ): + if self.lastValue < 0 or self.lastValue > maxValue: + return random.randint( self.minValue, 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 ) + + if self.lastValue < self.minValue: + self.lastValue = self.minValue + elif self.lastValue > maxValue: #instead of 14... + self.lastValue = maxValue + else: + self.lastValue = self.lastValue + + 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, minValue, maxValue, trackLength=None ): + Drunk.__init__( self, minValue, maxValue, trackLength=None ) + self.minValue = min(minValue, maxValue) + self.maxValue = max(minValue, maxValue) + self.beforeLastValue = random.randint( self.minValue, self.maxValue ) #self.minValue + 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 ) < 42: + return Drunk.getStepSize( self, direction, maxStepSize, maxValue ) + else: + return Drunk.getStepSize( self, direction, 0, maxValue ) + +class Repeter( Drunk ): + def __init__( self, minValue, maxValue, trackLength=None ): + Drunk.__init__( self, minValue, maxValue, trackLength=None) + self.minValue = min(minValue, maxValue) + self.maxValue = max(minValue, maxValue) + self.lastValue = random.randint( self.minValue, self.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 ) < 20: + return Drunk.getStepSize( self, direction, maxStepSize, maxValue ) + else: + return Drunk.getStepSize( self, direction, 0, maxValue ) + +class Loopseg( Drunk ): + def __init__( self, minValue, maxValue, trackLength=None ): + Drunk.__init__( self, minValue, maxValue, trackLength=None ) + 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 + +class Line: + def __init__(self, minValue, maxValue, trackLength=20): + maxVal = max(minValue, maxValue) + if maxVal == minValue: + self.reverse = True + minVal = maxValue + self.lastValue = maxVal + else: + self.reverse = False + minVal = minValue + self.lastValue = minVal + + scale = float(maxVal - minVal) + if self.reverse: + self.inc = -scale/trackLength + else: + self.inc = scale/trackLength + + def getNextValue(self, rand, maxValue): + self.val = self.lastValue + int(random.randint(0, rand)*random.choice([-0.5,0.5])) + if self.val < 0: + self.val = 0 + elif self.val > maxValue: + self.val = maxValue + else: + self.val = self.val + self.lastValue = self.val+self.inc + return self.val + diff --git a/common/Generation/GenerationConstants.py b/common/Generation/GenerationConstants.py new file mode 100755 index 0000000..29dd28b --- /dev/null +++ b/common/Generation/GenerationConstants.py @@ -0,0 +1,184 @@ +import random + +class GenerationConstants: + + TWO_ROOT_TWELVE = pow( 2, 1./12 ) + MAX_NOTES_PER_BAR = 12 + + PHRASE_LENGTH = 4 + PHRASE_COMPLEXITY = .5 + + TABLE_ONSET_VALUES = [ 3, 3, 6, 3, 6, 12, 4, 3, 6, 6, 12, 6, 12, 18, 8, 6, 12, 18, 12, 24, 12, 18, 36, 24, 36, 24, 48 ] + LOOP_TABLE_ONSET_VALUES = [ 3, 3, 6, 3, 6, 12, 6, 3, 6, 6, 12, 6, 12, 18, 12, 6, 12, 18, 12, 24, 12, 18, 12, 24, 18, 24, 24 ] + + # scaling constants + MAJOR = 0 + HARMONIC_MINOR = 1 + NATURAL_MINOR = 2 + PHRYGIEN = 3 + DORIEN = 4 + LYDIEN = 5 + MYXOLYDIEN = 6 + + SCALES = { MAJOR : [ -12, -10, -8, -7, -5, -3, -1, 0, 2, 4, 5, 7, 9, 11, 12 ], + HARMONIC_MINOR : [ -12, -10, -9, -7, -5, -4, -1, 0, 2, 3, 5, 7, 8, 11, 12 ], + NATURAL_MINOR : [ -12, -10, -9, -7, -5, -4, -2, 0, 2, 3, 5, 7, 8, 10, 12 ], + PHRYGIEN : [ -12, -11, -9, -7, -5, -4, -2, 0, 1, 3, 5, 7, 8, 10, 12 ], + DORIEN : [ -12, -10, -9, -7, -5, -3, -2, 0, 2, 3, 5, 7, 9, 10, 12 ], + LYDIEN : [ -12, -10, -8, -6, -5, -3, -1, 0, 2, 4, 6, 7, 9, 11, 12 ], + MYXOLYDIEN : [ -12, -10, -8, -7, -5, -3, -2, 0, 2, 4, 5, 7, 9, 10, 12 ]} + + + # Default parameters for algorithmic generation + + RYTHM_DENSITY_BANK = [.25, .88, .72, 1, .25] + RYTHM_REGU_BANK = [.75, .8, .85, .4, .5] + PITCH_REGU_BANK = [.5, .8, 0, .85, .9] + PITCH_STEP_BANK = [.5, .3, 1, .22, .85] + DURATION_BANK = [.8, 1, .8, 1, 1] + SILENCE_BANK = [.2, .5, .25, .55, .12] + SCALE_BANK = [MAJOR, NATURAL_MINOR, LYDIEN, HARMONIC_MINOR, MYXOLYDIEN] + + chooseDefault = random.randint(0,4) + DEFAULT_DENSITY = RYTHM_DENSITY_BANK[chooseDefault] + DEFAULT_RYTHM_REGULARITY = RYTHM_REGU_BANK[chooseDefault] + DEFAULT_PITCH_REGULARITY = PITCH_REGU_BANK[chooseDefault] + DEFAULT_STEP = PITCH_STEP_BANK[chooseDefault] + DEFAULT_DURATION = DURATION_BANK[chooseDefault] + DEFAULT_SILENCE = SILENCE_BANK[chooseDefault] + DEFAULT_PATTERN = [random.randint(0,3) for x in range(4)] + DEFAULT_SCALE = SCALE_BANK[chooseDefault] + + DEFAULT_RYTHM_METHOD = 0 + DEFAULT_PITCH_METHOD = 0 + DEFAULT_PAN = 0.5 + + DEFAULT_PITCH_VARIATION = 0 # 0 = 'melodic' 1 = 'harmonic' + DEFAULT_RYTHM_VARIATION = 0 # 0 = 'Cellule' 1 = 'Xnoise' + + 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 = .6 + ARTICULATION_SCALE_MAX_MAPPING = 1 + ARTICULATION_SCALE_STEPS = 10 + + # 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 ] ] + + DRUM_PUNCH_ACCENTS = [[], [0], [0, 12], [0, 24, 12], [0, 24, 36, 12], [0, 36, 24, 48, 12], [0, 36, 24, 60, 12, 48], [0, 24, 48, 72, 60, 36, 12], [0, 48, 24, 72, 36, 84, 60, 12], [0, 48, 72, 24, 96, 60, 36, 84, 12], [0, 72, 48, 96, 24, 60, 84, 36, 108, 12], [0, 48, 72, 120, 96, 24, 60, 84, 108, 36, 12], [0, 72, 48, 24, 96, 120, 84, 60, 36, 108, 132, 12]] + DRUM_LOW_ACCENTS = [[], [0], [0, 12], [0, 24, 12], [0, 24, 36, 12], [0, 36, 24, 48, 12], [0, 36, 24, 60, 12, 48], [0, 24, 48, 72, 60, 36, 12], [0, 48, 24, 72, 36, 84, 60, 12], [0, 48, 72, 24, 96, 60, 36, 84, 12], [0, 72, 48, 96, 24, 60, 84, 36, 108, 12], [0, 48, 72, 120, 96, 24, 60, 84, 108, 36, 12], [0, 72, 48, 24, 96, 120, 84, 60, 36, 108, 132, 12]] + DRUM_MID_ACCENTS = [[], [0, 6], [0, 12, 18, 6], [0, 12, 24, 18, 6, 30], [0, 24, 36, 12, 42, 6, 18, 30], [0, 36, 24, 48, 12, 6, 30, 18, 54, 42], [0, 36, 66, 30, 18, 54, 60, 12, 48, 42, 6, 24], [0, 24, 48, 72, 60, 78, 66, 54, 18, 12, 36, 30, 42, 6], [0, 48, 24, 72, 36, 84, 12, 60, 42, 90, 6, 54, 18, 66, 30, 78], [0, 48, 96, 24, 72, 84, 36, 12, 60, 42, 90, 6, 54, 18, 102, 66, 30, 78], [0, 60, 48, 24, 96, 72, 36, 84, 108, 12, 42, 54, 90, 18, 6, 114, 30, 66, 78, 102], [0, 48, 60, 96, 24, 120, 36, 72, 108, 84, 12, 54, 42, 18, 90, 126, 114, 6, 30, 66, 102, 78], [0, 60, 48, 24, 96, 36, 120, 132, 108, 72, 12, 84, 42, 54, 90, 18, 114, 6, 126, 30, 138, 102, 66, 78]] + DRUM_HIGH_ACCENTS = [[], [6, 0], [6, 18, 12, 0], [30, 6, 18, 24, 12, 0], [30, 18, 6, 42, 12, 36, 24, 0], [42, 54, 18, 30, 6, 12, 48, 24, 36, 0], [24, 6, 42, 30, 18, 54, 60, 12, 48, 66, 36, 0], [6, 42, 48, 30, 60, 78, 66, 54, 18, 12, 36, 72, 24, 0], [78, 30, 66, 18, 54, 6, 90, 60, 42, 12, 84, 36, 72, 24, 48, 0], [78, 30, 66, 102, 18, 54, 6, 90, 42, 60, 12, 36, 84, 72, 24, 96, 48, 0], [102, 78, 66, 30, 114, 6, 18, 90, 54, 42, 12, 108, 84, 36, 72, 96, 24, 48, 60, 0], [78, 102, 66, 30, 6, 114, 126, 90, 18, 42, 54, 12, 84, 108, 72, 36, 120, 24, 96, 60, 48, 0], [78, 66, 102, 138, 30, 126, 6, 114, 18, 90, 54, 42, 84, 12, 72, 108, 132, 120, 36, 96, 24, 48, 60, 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 } + + DRUM_COMPLEXITY1 = [ [ 24 ], [30] , [ 40 ], [ 46 ] ] + DRUM_COMPLEXITY2 = [ [ 24, 28 ], [ 30, 32 ], [ 36, 40 ], [ 46, 48 ] ] + DRUM_COMPLEXITY3 = [ [ 24, 26, 28 ], [ 30, 32, 34 ], [ 36, 38, 40 ], [ 42, 46, 48 ] ] + DRUM_COMPLEXITY4 = [ [ 24, 26, 28 ], [ 30, 32, 34 ], [ 36, 38, 40 ], [ 42, 44, 46, 48 ] ] + + 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/common/Generation/GenerationParametersWindow.py b/common/Generation/GenerationParametersWindow.py new file mode 100755 index 0000000..bde409d --- /dev/null +++ b/common/Generation/GenerationParametersWindow.py @@ -0,0 +1,383 @@ +import pygtk +pygtk.require('2.0') +import gtk +import shelve +from Generation.Generator import GenerationParameters +from Generation.GenerationConstants import GenerationConstants +from Util.ThemeWidgets import * +import Config + +Tooltips = Config.Tooltips() + +class GenerationParametersWindow( gtk.VBox ): + def __init__( self, generateFunction, handleCloseWindowCallback ): + gtk.VBox.__init__( self ) + self.handleCloseWindowCallback = handleCloseWindowCallback + self.tooltips = gtk.Tooltips() + + self.rythmMethod = GenerationConstants.DEFAULT_RYTHM_METHOD + self.pitchMethod = GenerationConstants.DEFAULT_PITCH_METHOD + self.pattern = GenerationConstants.DEFAULT_PATTERN + self.scale = GenerationConstants.DEFAULT_SCALE + self.sourceVariation = 1 + self.generateFunction = generateFunction + self.setupWindow() + self.show_all() + + def setupWindow( self ): + self.GUI = {} + self.rythmDensity = GenerationConstants.DEFAULT_DENSITY + self.rythmRegularity = GenerationConstants.DEFAULT_RYTHM_REGULARITY + self.pitchRegularity = GenerationConstants.DEFAULT_PITCH_REGULARITY + self.pitchStep = GenerationConstants.DEFAULT_STEP + self.duration = GenerationConstants.DEFAULT_DURATION + self.silence = GenerationConstants.DEFAULT_SILENCE + + # Generation Panel Setup + generationBox = RoundVBox(fillcolor=Config.INST_BCK_COLOR, bordercolor=Config.PANEL_BCK_COLOR) + generationBox.set_border_width(1) + generationBox.set_radius(10) + XYSlidersBox = gtk.HBox() + + self.col = gtk.gdk.color_parse(Config.PANEL_COLOR) + + XYSlider1Box = gtk.VBox() + XYSlider1UpBox = RoundHBox(fillcolor=Config.PANEL_COLOR, bordercolor=Config.INST_BCK_COLOR) + XYSlider1UpBox.set_border_width(3) + XYSlider1UpBox.set_radius(10) + self.XYSlider1DownBox = RoundHBox(fillcolor=Config.PANEL_COLOR, bordercolor=Config.INST_BCK_COLOR) + self.XYSlider1DownBox.set_border_width(3) + self.XYSlider1DownBox.set_radius(10) + + self.slider1Label = gtk.DrawingArea() + self.slider1Label.modify_bg(gtk.STATE_NORMAL, self.col) + colormap = self.slider1Label.get_colormap() + self.bgColor = colormap.alloc_color( Config.PANEL_COLOR, True, True ) + self.slider1Label.set_size_request(228, 60) + self.slider1Label.connect("expose-event", self.draw ) + XYSliderBox1 = self.formatRoundBox( RoundFixed(), Config.PANEL_COLOR ) + XYSliderBox1.set_size_request( 250, 250 ) + self.GUI["XYButton1"] = ImageToggleButton( Config.IMAGE_ROOT+"XYbut.png", Config.IMAGE_ROOT+"XYbutDown.png", backgroundFill=Config.PANEL_COLOR ) + self.XAdjustment1 = gtk.Adjustment( self.rythmDensity*100, 0, 100, 1, 1, 1 ) + self.XAdjustment1.connect("value-changed", self.handleXAdjustment1) + self.YAdjustment1 = gtk.Adjustment( self.rythmRegularity*100, 0, 100, 1, 1, 1 ) + self.YAdjustment1.connect("value-changed", self.handleYAdjustment1) + self.GUI["xySlider1"] = XYSlider( XYSliderBox1, self.GUI["XYButton1"], self.XAdjustment1, self.YAdjustment1, False, True ) + XYSlider1UpBox.pack_start( self.GUI["xySlider1"], False, False ) + + self.XYSlider1DownBox.pack_start(self.slider1Label, False, False, 5) + XYSlider1Box.pack_start(XYSlider1UpBox) + XYSlider1Box.pack_start(self.XYSlider1DownBox) + XYSlidersBox.pack_start(XYSlider1Box, False, False, 5) + + + XYSlider2Box = gtk.VBox() + XYSlider2UpBox = RoundHBox(fillcolor=Config.PANEL_COLOR, bordercolor=Config.INST_BCK_COLOR) + XYSlider2UpBox.set_border_width(3) + XYSlider2UpBox.set_radius(10) + self.XYSlider2DownBox = RoundHBox(fillcolor=Config.PANEL_COLOR, bordercolor=Config.INST_BCK_COLOR) + self.XYSlider2DownBox.set_border_width(3) + self.XYSlider2DownBox.set_radius(10) + + self.slider2Label = gtk.DrawingArea() + self.slider2Label.modify_bg(gtk.STATE_NORMAL, self.col) + self.slider2Label.set_size_request(228, 60) + self.slider2Label.connect("expose-event", self.draw2 ) + XYSliderBox2 = self.formatRoundBox( RoundFixed(), Config.PANEL_COLOR ) + XYSliderBox2.set_size_request( 250, 250 ) + self.GUI["XYButton2"] = ImageToggleButton( Config.IMAGE_ROOT+"XYbut.png", Config.IMAGE_ROOT+"XYbutDown.png", backgroundFill=Config.PANEL_COLOR ) + self.XAdjustment2 = gtk.Adjustment( self.pitchRegularity*100, 0, 100, 1, 1, 1 ) + self.XAdjustment2.connect("value-changed", self.handleXAdjustment2) + self.YAdjustment2 = gtk.Adjustment( self.pitchStep*100, 0, 100, 1, 1, 1 ) + self.YAdjustment2.connect("value-changed", self.handleYAdjustment2) + self.GUI["xySlider2"] = XYSlider( XYSliderBox2, self.GUI["XYButton2"], self.XAdjustment2, self.YAdjustment2, False, True ) + XYSlider2UpBox.pack_start( self.GUI["xySlider2"], False, False ) + + self.XYSlider2DownBox.pack_start(self.slider2Label, False, False, 5) + XYSlider2Box.pack_start(XYSlider2UpBox) + XYSlider2Box.pack_start(self.XYSlider2DownBox) + XYSlidersBox.pack_start(XYSlider2Box, False, False, 5) + + + XYSlider3Box = gtk.VBox() + XYSlider3UpBox = RoundHBox(fillcolor=Config.PANEL_COLOR, bordercolor=Config.INST_BCK_COLOR) + XYSlider3UpBox.set_border_width(3) + XYSlider3UpBox.set_radius(10) + self.XYSlider3DownBox = RoundHBox(fillcolor=Config.PANEL_COLOR, bordercolor=Config.INST_BCK_COLOR) + self.XYSlider3DownBox.set_border_width(3) + self.XYSlider3DownBox.set_radius(10) + + self.slider3Label = gtk.DrawingArea() + self.slider3Label.modify_bg(gtk.STATE_NORMAL, self.col) + self.slider3Label.set_size_request(228, 60) + self.slider3Label.connect("expose-event", self.draw3 ) + XYSliderBox3 = self.formatRoundBox( RoundFixed(), Config.PANEL_COLOR ) + XYSliderBox3.set_size_request( 250, 250 ) + self.GUI["XYButton3"] = ImageToggleButton( Config.IMAGE_ROOT+"XYbut.png", Config.IMAGE_ROOT+"XYbutDown.png", backgroundFill=Config.PANEL_COLOR ) + self.XAdjustment3 = gtk.Adjustment( self.duration*100, 0, 100, 1, 1, 1 ) + self.XAdjustment3.connect("value-changed", self.handleXAdjustment3) + self.YAdjustment3 = gtk.Adjustment( self.silence*100, 0, 100, 1, 1, 1 ) + self.YAdjustment3.connect("value-changed", self.handleYAdjustment3) + self.GUI["xySlider3"] = XYSlider( XYSliderBox3, self.GUI["XYButton3"], self.XAdjustment3, self.YAdjustment3, False, True ) + XYSlider3UpBox.pack_start( self.GUI["xySlider3"], False, False ) + + self.XYSlider3DownBox.pack_start(self.slider3Label, False, False, 5) + XYSlider3Box.pack_start(XYSlider3UpBox) + XYSlider3Box.pack_start(self.XYSlider3DownBox) + XYSlidersBox.pack_start(XYSlider3Box, False, False, 5) + + generationBox.pack_start(XYSlidersBox, False, False, 5) + + self.pack_start(generationBox) + + # Meta Algo panel setup + metaAlgoBox = RoundVBox(fillcolor=Config.INST_BCK_COLOR, bordercolor=Config.PANEL_BCK_COLOR) + metaAlgoBox.set_border_width(1) + metaAlgoBox.set_radius(10) + + methodBox = gtk.HBox() + self.firstButton = None + methodNames = ['drunk', 'droneJump', 'repeat', 'loopSeg'] + for meth in methodNames: + self.GUI[meth] = ImageRadioButton(self.firstButton, Config.IMAGE_ROOT + meth + '.png', Config.IMAGE_ROOT + meth + 'Down.png', Config.IMAGE_ROOT + meth + 'Over.png', backgroundFill=Config.INST_BCK_COLOR ) + if self.firstButton == None: + self.firstButton = self.GUI[meth] + self.GUI[meth].connect('clicked' , self.handleMethod , methodNames.index(meth)) + if methodNames.index(meth) == self.pattern: + self.GUI[meth].set_active(True) + methodBox.pack_start(self.GUI[meth], False, False) + metaAlgoBox.pack_start(methodBox, False, False, 5) + + scaleBox = gtk.HBox() + self.firstButton = None + scaleNames = ['majorKey', 'minorHarmKey', 'minorKey', 'phrygienKey', 'dorienKey', 'lydienKey', 'myxoKey'] + for scale in scaleNames: + self.GUI[scale] = ImageRadioButton(self.firstButton, Config.IMAGE_ROOT + scale + '.png', Config.IMAGE_ROOT + scale + 'Down.png', Config.IMAGE_ROOT + scale + 'Over.png', backgroundFill=Config.INST_BCK_COLOR ) + if self.firstButton == None: + self.firstButton = self.GUI[scale] + self.GUI[scale].connect('clicked' , self.handleScale , scaleNames.index(scale)) + if scaleNames.index(scale) == self.scale: + self.GUI[scale].set_active(True) + scaleBox.pack_start(self.GUI[scale], False, False) + metaAlgoBox.pack_start(scaleBox, False, False) + + self.pack_start(metaAlgoBox) + + # Transport Panel Setup + transportBox = RoundVBox(fillcolor=Config.INST_BCK_COLOR, bordercolor=Config.PANEL_BCK_COLOR) + transportBox.set_border_width(1) + transportBox.set_radius(10) + + # Create save/load presets + transButtonBox = RoundHBox(fillcolor=Config.INST_BCK_COLOR, bordercolor=Config.PANEL_BCK_COLOR) + transButtonBox.set_radius(10) + + self.GUI["saveButton"] = ImageButton(Config.TAM_TAM_ROOT + '/Resources/Images/save.png', backgroundFill=Config.INST_BCK_COLOR ) + self.GUI["saveButton"].connect("clicked", self.handleSave, None) + #transButtonBox.pack_start(self.GUI["saveButton"], False, False, 2) + + self.GUI["loadButton"] = ImageButton(Config.TAM_TAM_ROOT + '/Resources/Images/load.png', backgroundFill=Config.INST_BCK_COLOR ) + self.GUI["loadButton"].connect("clicked", self.handleLoad, None) + #transButtonBox.pack_start(self.GUI["loadButton"], False, False, 2) + + # create cancel/check button + self.GUI["checkButton"] = ImageButton(Config.IMAGE_ROOT + 'check.png', backgroundFill=Config.INST_BCK_COLOR ) + self.GUI["checkButton"].connect("clicked", self.generate) + + self.GUI["cancelButton"] = ImageButton(Config.IMAGE_ROOT + 'closeA.png', backgroundFill=Config.INST_BCK_COLOR ) + self.GUI["cancelButton"].connect("clicked", self.cancel) + + # create play/stop buttons + playButton = ImageToggleButton(Config.IMAGE_ROOT + 'playTogOff.png', Config.IMAGE_ROOT + 'playTogOn.png', backgroundFill=Config.INST_BCK_COLOR ) + selButton = ImageToggleButton(Config.IMAGE_ROOT + 'playAll.png', Config.IMAGE_ROOT + 'playSel.png', backgroundFill=Config.INST_BCK_COLOR ) + transButtonBox.pack_end(self.GUI["checkButton"], False, False, 10) + transButtonBox.pack_end(self.GUI["cancelButton"], False, False) + #transButtonBox.pack_end(selButton, False, False) + #transButtonBox.pack_end(playButton, False, False) + transportBox.pack_start(transButtonBox) + + self.pack_start(transportBox) + self.loadPixmaps() + # set tooltips + for key in self.GUI: + if Tooltips.ALGO.has_key(key): + self.tooltips.set_tip(self.GUI[key],Tooltips.ALGO[key]) + + def loadPixmaps( self ): + win = gtk.gdk.get_default_root_window() + self.gc = gtk.gdk.GC( win ) + self.gc.foreground = self.bgColor + + self.arrowPixmap = [] + for i in range(2): + pix = gtk.gdk.pixbuf_new_from_file(Config.IMAGE_ROOT + ['arrowSide.png', 'arrowUp.png'][i]) + map = gtk.gdk.Pixmap( win, pix.get_width(), pix.get_height() ) + map.draw_rectangle( self.gc, True, 0, 0, pix.get_width(), pix.get_height() ) + map.draw_pixbuf( self.gc, pix, 0, 0, 0, 0, pix.get_width(), pix.get_height(), gtk.gdk.RGB_DITHER_NONE ) + self.arrowPixmap.append(map) + + self.rythDensPixmap = [] + self.rythRegPixmap = [] + self.pitchRegPixmap = [] + self.pitchStepPixmap = [] + self.durPixmap = [] + self.silencePixmap = [] + pixmaps = [self.rythDensPixmap, self.rythRegPixmap, self.pitchRegPixmap, self.pitchStepPixmap, self.durPixmap, self.silencePixmap] + pixmapNames = ['rythDens', 'rythReg', 'pitReg', 'pitStep', 'durLen', 'durDens'] + + for inc in range(6): + imgName = pixmapNames[inc] + pixmap = pixmaps[inc] + for i in range(6): + pix = gtk.gdk.pixbuf_new_from_file(Config.IMAGE_ROOT + imgName + str(i+1) + '.png') + map = gtk.gdk.Pixmap( win, pix.get_width(), pix.get_height() ) + map.draw_rectangle( self.gc, True, 0, 0, pix.get_width(), pix.get_height() ) + map.draw_pixbuf( self.gc, pix, 0, 0, 0, 0, pix.get_width(), pix.get_height(), gtk.gdk.RGB_DITHER_NONE ) + pixmap.append(map) + + + def draw( self, widget, event ): + imgX = 5 - int(self.rythmDensity * 5) + imgY = 5 - int(self.rythmRegularity * 5) + widget.window.draw_drawable( self.gc, self.arrowPixmap[0], 0, 0, 0, 18, 24, 24 ) + widget.window.draw_drawable( self.gc, self.rythDensPixmap[imgX], 0, 0, 24, 0, 90, 60 ) + widget.window.draw_drawable( self.gc, self.arrowPixmap[1], 0, 0, 114, 18, 24, 24 ) + widget.window.draw_drawable( self.gc, self.rythRegPixmap[imgY], 0, 0, 138, 0, 90, 60 ) + return True + + def draw2( self, widget, event ): + imgX = 5 - int(self.pitchRegularity * 5) + imgY = 5 - int(self.pitchStep * 5) + widget.window.draw_drawable( self.gc, self.arrowPixmap[0], 0, 0, 0, 18, 24, 24 ) + widget.window.draw_drawable( self.gc, self.pitchRegPixmap[imgX], 0, 0, 24, 0, 90, 60 ) + widget.window.draw_drawable( self.gc, self.arrowPixmap[1], 0, 0, 114, 18, 24, 24 ) + widget.window.draw_drawable( self.gc, self.pitchStepPixmap[imgY], 0, 0, 138, 0, 90, 60 ) + return True + + def draw3( self, widget, event ): + imgX = int(self.duration * 5) + imgY = int(self.silence * 5) + widget.window.draw_drawable( self.gc, self.arrowPixmap[0], 0, 0, 0, 18, 24, 24 ) + widget.window.draw_drawable( self.gc, self.durPixmap[imgX], 0, 0, 24, 0, 90, 60 ) + widget.window.draw_drawable( self.gc, self.arrowPixmap[1], 0, 0, 114, 18, 24, 24 ) + widget.window.draw_drawable( self.gc, self.silencePixmap[imgY], 0, 0, 138, 0, 90, 60 ) + return True + + + def handleXAdjustment1( self, data ): + self.rythmDensity = self.XAdjustment1.value * .01 + self.slider1Label.queue_draw() + + def handleYAdjustment1( self, data ): + self.rythmRegularity = self.YAdjustment1.value * .01 + self.slider1Label.queue_draw() + + def handleXAdjustment2( self, data ): + self.pitchRegularity = self.XAdjustment2.value * .01 + self.slider2Label.queue_draw() + + def handleYAdjustment2( self, data ): + self.pitchStep = self.YAdjustment2.value * .01 + self.slider2Label.queue_draw() + + def handleXAdjustment3( self, data ): + self.duration = self.XAdjustment3.value * .01 + self.slider3Label.queue_draw() + + def handleYAdjustment3( self, data ): + self.silence = self.YAdjustment3.value * .01 + self.slider3Label.queue_draw() + + + def getGenerationParameters( self ): + return GenerationParameters( self.rythmDensity, + self.rythmRegularity, + self.pitchStep, + self.pitchRegularity, + self.duration, + self.silence, + self.rythmMethod, + self.pitchMethod, + self.pattern, + self.scale ) + + def cancel( self, widget, data=None ): + self.handleCloseWindowCallback() + + def generate(self, widget, data=None): + self.generateFunction( self.getGenerationParameters() ) + self.handleCloseWindowCallback() + + def handleMethod( self, widget, method ): + if widget.get_active(): + self.pattern = method + + def handleScale( self, widget, scale ): + if widget.get_active(): + self.scale = scale + + def formatRoundBox( self, box, fillcolor ): + box.set_radius( 10 ) + box.set_border_width( 1 ) + box.set_fill_color( fillcolor ) + box.set_border_color( Config.INST_BCK_COLOR ) + return box + + +#=========================== PRESETS ================================ + + def handleSave(self, widget, data): + chooser = gtk.FileChooserDialog(title=None,action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK)) + + if chooser.run() == gtk.RESPONSE_OK: + try: + print 'INFO: save preset file %s' % chooser.get_filename() + f = shelve.open( chooser.get_filename(), 'n') + self.saveState(f) + f.close() + except IOError: + print 'ERROR: failed to save preset to file %s' % chooser.get_filename() + + chooser.destroy() + + def handleLoad(self, widget, data): + + chooser = gtk.FileChooserDialog(title=None,action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) + + if chooser.run() == gtk.RESPONSE_OK: + try: + print 'INFO: load preset state from file %s' % chooser.get_filename() + f = shelve.open( chooser.get_filename(), 'r') + self.loadState(f) + f.close() + except IOError: + print 'ERROR: failed to load preset state from file %s' % chooser.get_filename() + + def loadState( self, state ): + pass + self.rythmDensity = state['rythmDensity'] + self.rythmRegularity = state['rythmRegularity'] + self.pitchRegularity = state['pitchRegularity'] + self.pitchStep = state['pitchStep'] + self.duration = state['duration'] + self.silence = state['silence'] + self.pattern = state['pattern'] + self.scale = state['scale'] + + self.XAdjustment1.set_value(self.rythmDensity*100) + self.YAdjustment1.set_value(self.rythmRegularity*100) + self.XAdjustment2.set_value(self.pitchRegularity*100) + self.YAdjustment2.set_value(self.pitchStep*100) + self.XAdjustment3.set_value(self.duration*100) + self.YAdjustment3.set_value(self.silence*100) + + def saveState( self, state ): + pass + state['rythmDensity'] = self.rythmDensity + state['rythmRegularity'] = self.rythmRegularity + state['pitchRegularity'] = self.pitchRegularity + state['pitchStep'] = self.pitchStep + state['duration'] = self.duration + state['silence'] = self.silence + state['pattern'] = self.pattern + state['scale'] = self.scale diff --git a/common/Generation/GenerationPitch.py b/common/Generation/GenerationPitch.py new file mode 100644 index 0000000..4012589 --- /dev/null +++ b/common/Generation/GenerationPitch.py @@ -0,0 +1,40 @@ +import random +import Drunk + +import common.Config as Config +from Generation.GenerationConstants import GenerationConstants + +class GenerationPitch: + def __init__( self ): + MIN = 0 + MAX = 14 + self.drunkMethod = Drunk.Drunk( MIN, MAX ) + self.droneMethod = Drunk.DroneAndJump( MIN, MAX ) + self.repeatMethod = Drunk.Repeter( MIN, MAX ) + self.loopMethod = Drunk.Loopseg( MIN, MAX ) + self.methodList = [self.drunkMethod, self.droneMethod, self.repeatMethod, self.loopMethod] + + def drunkPitchSequence(self, length, parameters, table_pitch, trackId): + pitchSequence = [] + append = pitchSequence.append + numberOfPitch = int( ( 1 - (parameters.pitchRegularity*.8) ) * 10 + 1 ) + step = -(int(parameters.step * 10)) + max = len(table_pitch)-1 + nextValue = self.methodList[parameters.pattern[trackId]].getNextValue + tonique = GenerationConstants.DEFAULT_TONIQUE + for i in range(numberOfPitch): + append((table_pitch[nextValue(step, max)]) + tonique) + restOfNotes = range( length - numberOfPitch ) + for i in restOfNotes: + position = i % numberOfPitch + append( pitchSequence[ position ] ) + return pitchSequence + + def drumPitchSequence(self, length, parameters, drumPitch, table_pitch=None): + pitchSequence = [] + append = pitchSequence.append + max = len(drumPitch) - 1 + rand = random.randint + for i in range(length): + append(drumPitch[ rand( 0, max ) ] ) + return pitchSequence diff --git a/common/Generation/GenerationRythm.py b/common/Generation/GenerationRythm.py new file mode 100644 index 0000000..718c1ec --- /dev/null +++ b/common/Generation/GenerationRythm.py @@ -0,0 +1,213 @@ +import Utils +import random +from math import sqrt +import common.Config as Config +from Generation.GenerationConstants import GenerationConstants + +class GenerationRythm: + + def celluleRythmSequence(self, parameters, barLength, trackInstrument=None ): + rythmSequence = [0, ] + self.count = 0 + lastOnsetTime = 0 + onsetLen = len(GenerationConstants.TABLE_ONSET_VALUES) + + onsetValue = int( ( 1 - (parameters.density*0.98+0.02) ) * onsetLen ) + onsetDeviation = int( ( 1 - parameters.rythmRegularity ) * 20 ) + currentOnsetValue = onsetValue + ( random.randint( 0, onsetDeviation ) - ( onsetDeviation / 2 ) ) + if currentOnsetValue < 0: + currentOnsetValue = 0 + elif currentOnsetValue >= onsetLen: + currentOnsetValue = onsetLen - 1 + else: + currentOnsetValue = currentOnsetValue + + onsetDelta = GenerationConstants.TABLE_ONSET_VALUES[ currentOnsetValue ] + listLen = range( int( barLength / Config.TICKS_PER_BEAT * 8 ) ) + randInt = random.randint + for i in listLen: + if self.count == 0: + currentOnsetValue = onsetValue + ( randInt( 0, onsetDeviation ) - ( onsetDeviation / 2 ) ) + if currentOnsetValue < 0: + currentOnsetValue = 0 + elif currentOnsetValue >= onsetLen: + currentOnsetValue = onsetLen - 1 + else: + currentOnsetValue = currentOnsetValue + onsetDelta = GenerationConstants.TABLE_ONSET_VALUES[ currentOnsetValue ] + + if onsetDelta == GenerationConstants.DOUBLE_TICK_DUR: + if self.count < (GenerationConstants.DOUBLE_HOW_MANY - 1): + self.count += 1 + else: + self.count = 0 + onsetTime = onsetDelta + lastOnsetTime + lastOnsetTime = onsetTime + if onsetTime < barLength-2: + rythmSequence.append(onsetTime) + continue + else: + break + elif onsetDelta == GenerationConstants.HALF_TRIPLET_TICK_DUR: + if self.count < (GenerationConstants.HALF_TRIPLET_HOW_MANY - 1): + self.count += 1 + else: + self.count = 0 + onsetTime = onsetDelta + lastOnsetTime + lastOnsetTime = onsetTime + if onsetTime < barLength-2: + rythmSequence.append(onsetTime) + continue + else: + break + elif onsetDelta == GenerationConstants.HOLE_TRIPLET_TICK_DUR: + if self.count < (GenerationConstants.HOLE_TRIPLET_HOW_MANY - 1): + self.count += 1 + else: + self.count = 0 + onsetTime = onsetDelta + lastOnsetTime + lastOnsetTime = onsetTime + if onsetTime < barLength-2: + rythmSequence.append(onsetTime) + continue + else: + break + + onsetTime = onsetDelta + lastOnsetTime + lastOnsetTime = onsetTime + if onsetTime < barLength-2: + rythmSequence.append(onsetTime) + else: + break + return rythmSequence + + def xnoiseRythmSequence(self, parameters, barLength ): + 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(( barLength - 1) / GenerationConstants.DOUBLE_TICK_DUR))) * GenerationConstants.DOUBLE_TICK_DUR + + if onsetTime < 0: + onsetTime = 0 + elif onsetTime > ( barLength - GenerationConstants.DOUBLE_TICK_DUR): + onsetTime = ( barLength - GenerationConstants.DOUBLE_TICK_DUR) + else: + onsetTime = onsetTime + + rythmSequence.append(onsetTime) + + rythmSequence.sort() + return rythmSequence + + def drumRythmSequence(self, parameters, trackInstrument, barLength ): + density = sqrt(parameters.density) + rythmSequence = [] + binSelection = [] + downBeats = [] + upBeats = [] + beats = [] + countDown = 0 + onsetTime = None + beatsPerPage = int( barLength / Config.TICKS_PER_BEAT ) + randInt = random.randint + + upBeatsAppend = upBeats.append + + if Config.INSTRUMENTS[ trackInstrument ].instrumentRegister == Config.PUNCH: + registerDensity = 0.5 + downBeatRecurence = 4 + upBeatOffset = Config.TICKS_PER_BEAT / 2 + downBeats = [x for x in GenerationConstants.DRUM_PUNCH_ACCENTS[ beatsPerPage ]] + for downBeat in downBeats: + upBeatsAppend( downBeat + upBeatOffset ) + + elif Config.INSTRUMENTS[ trackInstrument ].instrumentRegister == Config.LOW: + registerDensity = 1.5 + downBeatRecurence = 4 + upBeatOffset = Config.TICKS_PER_BEAT / 2 + downBeats = [x for x in GenerationConstants.DRUM_LOW_ACCENTS[ beatsPerPage ]] + for downBeat in downBeats: + upBeatsAppend( downBeat + upBeatOffset ) + + elif Config.INSTRUMENTS[ trackInstrument ].instrumentRegister == Config.MID: + registerDensity = 1 + downBeatRecurence = 1 + upBeatOffset = Config.TICKS_PER_BEAT / 4 + downBeats = [x for x in GenerationConstants.DRUM_MID_ACCENTS[ beatsPerPage ]] + for downBeat in downBeats: + upBeatsAppend( downBeat + upBeatOffset ) + + elif Config.INSTRUMENTS[ trackInstrument ].instrumentRegister == Config.HIGH: + registerDensity = 1.5 + downBeatRecurence = 1 + upBeatOffset = Config.TICKS_PER_BEAT / 4 + downBeats = [x for x in GenerationConstants.DRUM_HIGH_ACCENTS[ beatsPerPage ]] + for downBeat in downBeats: + upBeatsAppend( downBeat + upBeatOffset ) + + list = range( int( density * registerDensity * len( downBeats ) ) ) + rand = random.random + binCount = binSelection.count + binAppend = binSelection.append + for i in list: + if rand() < ( parameters.rythmRegularity * downBeatRecurence ) and binCount( 1 ) < len( downBeats ): + binAppend( 1 ) + else: + if binCount( 0 ) < len( downBeats ): + binAppend( 0 ) + else: + binAppend( 1 ) + + countDown = binCount( 1 ) + + seqAppend = rythmSequence.append + length = len(downBeats) - 1 + downPop = downBeats.pop + for i in range( countDown ): + ran1 = randInt(0, length) + ran2 = randInt(0, length) + randMin = min(ran1, ran2) + onsetTime = downPop(randMin) + seqAppend( onsetTime ) + length -= 1 + + length = len(upBeats) - 1 + upPop = upBeats.pop + for i in range( len( binSelection ) - countDown ): + ran1 = randInt(0, length) + ran2 = randInt(0, length) + randMin = min(ran1, ran2) + onsetTime = upPop(randMin) + seqAppend( onsetTime ) + length -= 1 + + 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/common/Generation/Generator.py b/common/Generation/Generator.py new file mode 100755 index 0000000..b5640a6 --- /dev/null +++ b/common/Generation/Generator.py @@ -0,0 +1,167 @@ +import random +import math + +import Utils +import Drunk + +import common.Config as Config +from Util.CSoundNote import CSoundNote +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_DURATION, + silence = GenerationConstants.DEFAULT_SILENCE, + 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.silence = silence + self.rythmMethod = rythmMethod + self.pitchMethod = pitchMethod + self.pattern = pattern + self.scale = scale + +def generator1( + parameters, # algorithm-specific parameters + volume, # [trackId: float(volume) ] + instrument, # [pageId][trackId: instrument] + tempo, # integer bpm + nbeats, # map [ pageId : beats ] + trackIds, # list of trackIds to generate + pageIds, # list of pageIds to generate + trackDictionary, # map [ trackId : [ pageId : events ] ] + nPagesCycle = 4 # META ALGO number of pages in a section + ): + + makeRythm = GenerationRythm() + makePitch = GenerationPitch() + + def makeGainSequence( onsetList ): + gainSequence = [] + append = gainSequence.append + rand = random.uniform + max = GenerationConstants.GAIN_MAX_BOUNDARY + midMax = GenerationConstants.GAIN_MID_MAX_BOUNDARY + midMin = GenerationConstants.GAIN_MID_MIN_BOUNDARY + min = GenerationConstants.GAIN_MIN_BOUNDARY + for onset in onsetList: + if onset == 0: + append(rand(midMax, max)) + elif ( onset % Config.TICKS_PER_BEAT) == 0: + append(rand(midMin, midMax)) + else: + append(rand(min, midMin)) + return gainSequence + + def makeDurationSequence( onsetList, parameters, table_duration, barLength, currentInstrument ): + durationSequence = [] + if Config.INSTRUMENTS[currentInstrument].soundClass == 'drum': + duration = GenerationConstants.DOUBLE_TICK_DUR / 2 + durationSequence = [duration] * len(onsetList) + return durationSequence + + append = durationSequence.append + proba = Utils.prob2 + if len( onsetList ) > 1: + for i in range(len(onsetList) - 1): + append((onsetList[i+1] - onsetList[i]) * proba( table_duration )) + append(( barLength - onsetList[-1]) * proba( table_duration )) + elif len( onsetList ) == 1: + append( ( barLength - onsetList[0] ) * proba( table_duration )) + return durationSequence + + def pageGenerate(parameters, trackId, pageId, trackOfNotes, drumPitch = None): + + trackNotes = trackOfNotes + + if drumPitch: + currentInstrument = Config.INSTRUMENTS[instrument[pageId][trackId]].kit[drumPitch[0]].name + rythmSequence = makeRythm.drumRythmSequence(parameters, currentInstrument, barLength) + pitchSequence = makePitch.drumPitchSequence(len(rythmSequence), parameters, drumPitch, table_pitch ) + else: + currentInstrument = instrument[pageId][trackId] + rythmSequence = makeRythm.celluleRythmSequence(parameters, barLength, currentInstrument) + pitchSequence = makePitch.drunkPitchSequence(len(rythmSequence),parameters, table_pitch, trackId) + + gainSequence = makeGainSequence(rythmSequence) + durationSequence = makeDurationSequence(rythmSequence, parameters, table_duration, barLength, currentInstrument) + + numOfNotes = range(len(rythmSequence)) + rand = random.random + append = trackNotes.append + pan = GenerationConstants.DEFAULT_PAN + instrument_id = Config.INSTRUMENTS[instrument[pageId][trackId]].instrumentId + for i in numOfNotes: + if drumPitch: + if ( rand() * fillDrum ) > ( parameters.silence * .5 ): + if fillDrum != 1: + if rythmSequence[i] not in trackOnsets or pitchSequence[i] not in trackPitchs: + append( CSoundNote( rythmSequence[i], pitchSequence[i], gainSequence[i], pan, durationSequence[i], trackId, instrument_id, 0.002, 0.098, 0.1, 0, 1000, False, 'edit' ) ) + else: + append( CSoundNote( rythmSequence[i], pitchSequence[i], gainSequence[i], pan, durationSequence[i], trackId, instrument_id, 0.002, 0.098, 0.1, 0, 1000, False, 'edit' ) ) + else: + if rand() > parameters.silence: + append( CSoundNote( rythmSequence[i], pitchSequence[i], gainSequence[i], pan, durationSequence[i], trackId, instrument_id, 0.002, 0.1, 0.1, 0, 1000, False, 'edit' ) ) + + trackDictionary[ trackId ][ pageId ] = trackNotes + +################################################################################## + # begin generate() + + 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] + + for trackId in trackIds: + if trackId == 4: # drum index + if parameters.rythmRegularity > 0.75: + streamOfPitch = GenerationConstants.DRUM_COMPLEXITY1 + elif parameters.rythmRegularity > 0.5: + streamOfPitch = GenerationConstants.DRUM_COMPLEXITY2 + elif parameters.rythmRegularity > 0.25: + streamOfPitch = GenerationConstants.DRUM_COMPLEXITY3 + else: + streamOfPitch = GenerationConstants.DRUM_COMPLEXITY4 + selectedPageCount = 0 + lastPageId = 0 + for pageId in pageIds: + barLength = Config.TICKS_PER_BEAT * nbeats[ pageId ] + trackOfNotes = [] + pageCycle = selectedPageCount % nPagesCycle + + if instrument[pageId][trackId][0:4] == 'drum': + if pageCycle not in [0,nPagesCycle-1] and nbeats[pageId] == nbeats[lastPageId]: + trackDictionary[trackId][pageId] = [] + for n in trackDictionary[trackId][lastPageId]: + trackDictionary[trackId][pageId].append(n.clone()) + elif pageCycle == (nPagesCycle-1) and nbeats[pageId] == nbeats[lastPageId]: + for n in trackDictionary[trackId][lastPageId]: + trackOfNotes.append(n.clone()) + trackOnsets = [n.onset for n in trackOfNotes] + trackPitchs = [n.pitch for n in trackOfNotes] + fillDrum = .5 + rythmRegTemp = parameters.rythmRegularity + parameters.rythmRegularity = 0.5 + for drumPitch in GenerationConstants.DRUM_COMPLEXITY4: + pageGenerate( parameters, trackId, pageId, trackOfNotes, drumPitch ) + parameters.rythmRegularity = rythmRegTemp + else: + fillDrum = 1 + for drumPitch in streamOfPitch: + pageGenerate( parameters, trackId, pageId, trackOfNotes, drumPitch ) + + else: + pageGenerate( parameters, trackId, pageId, trackOfNotes, drumPitch = None ) + selectedPageCount += 1 + lastPageId = pageId diff --git a/common/Generation/Utils.py b/common/Generation/Utils.py new file mode 100755 index 0000000..e5ea295 --- /dev/null +++ b/common/Generation/Utils.py @@ -0,0 +1,74 @@ +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 = [] + + up = 1.-val + if up <= 0.5: + low_val = (pow(1.-(up*2.),4.)*(-50.5)+0.5) + else: + low_val = up + + if val <= 0.5: + high_val = (pow(1.-(val * 2.),4.)*(-50.5)+0.5) + else: + high_val = val + + step = (maxi - mini) * (1. / length) + + calc = (1. / length) * (high_val - low_val) + append = slope.append + for i in range(length + 1): + temp = i * calc + low_val + if temp < 0: + temp = 0 + elif temp > 1: + temp = 1 + else: + temp = temp + + append(((step * i) + mini, int(temp * 100))) + + return slope + +def midtotrans(x): + return pow(1.059463, x - 36) diff --git a/common/Generation/VariationPitch.py b/common/Generation/VariationPitch.py new file mode 100644 index 0000000..5a2b151 --- /dev/null +++ b/common/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/common/Generation/VariationRythm.py b/common/Generation/VariationRythm.py new file mode 100644 index 0000000..5fb6111 --- /dev/null +++ b/common/Generation/VariationRythm.py @@ -0,0 +1,74 @@ +import random + +import common.Config as Config + +# remplacer position dans notesList par l'attribut de CSoundNote +class RythmShuffle: + + def getNewList( self, notesList, nbeats ): + self.barLength = Config.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 = Config.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() + + 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/common/Generation/__init__.py b/common/Generation/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/common/Generation/__init__.py diff --git a/common/Generation/bList.py b/common/Generation/bList.py new file mode 100644 index 0000000..26aed12 --- /dev/null +++ b/common/Generation/bList.py @@ -0,0 +1,97 @@ +import common.Config as Config +from Generation.GenerationConstants import GenerationConstants + +def gen(): + punch_list = [[], ] + low_list = [[], ] + mid_list = [[], ] + high_list = [[], ] + + f = open('/home/olpc/tamtam/Generation/drumTablesList', 'w') + g = open('/home/olpc/tamtam/Generation/drumStraightTables', 'w') + + # gen punch list + beatsList = [[], ] + for beatsPerPage in [1,2,3,4,5,6,7,8,9,10,11,12]: + accents = [] + for j in GenerationConstants.PUNCH_ACCENTS[beatsPerPage]: + accents.append(j * Config.TICKS_PER_BEAT) + beatsList.append(accents) + beats = [] + downBeats = [] + for beat in range( beatsPerPage ): + beats.append( beat * Config.TICKS_PER_BEAT ) + for i in range( len( beats ) ): + downBeats.append( ( beats[ GenerationConstants.PUNCH_ACCENTS[ beatsPerPage ][ i ] ], int( pow( float( len( beats ) - i) / len( beats ), 1.5 ) * 100.) ) ) + punch_list.append(downBeats) + + string = ' DRUM_PUNCH_PROB = ' + str(punch_list) + '\n' + f.write(string) + string = ' DRUM_PUNCH_ACCENT = ' + str(beatsList) + '\n' + g.write(string) + + # gen low list + beatsList = [[], ] + for beatsPerPage in [1,2,3,4,5,6,7,8,9,10,11,12]: + accents = [] + for j in GenerationConstants.LOW_ACCENTS[beatsPerPage]: + accents.append(j * Config.TICKS_PER_BEAT) + beatsList.append(accents) + beats = [] + downBeats = [] + 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 ] ], int( pow( float( len( beats ) - i) / len( beats ), 1.5 ) * 100.) ) ) + low_list.append(downBeats) + + string = ' DRUM_LOW_PROB = ' + str(low_list) + '\n' + f.write(string) + string = ' DRUM_LOW_ACCENT = ' + str(beatsList) + '\n' + g.write(string) + + # gen mid list + beatsList = [[], ] + for beatsPerPage in [1,2,3,4,5,6,7,8,9,10,11,12]: + accents = [] + for j in GenerationConstants.MID_ACCENTS[beatsPerPage]: + accents.append(j * Config.TICKS_PER_BEAT / 2) + beatsList.append(accents) + beats = [] + downBeats = [] + 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 ] ], int( pow( float( len( beats ) - i) / len( beats ), 1.5 ) * 100.) ) ) + mid_list.append(downBeats) + + string = ' DRUM_MID_PROB = ' + str(mid_list) + '\n' + f.write(string) + string = ' DRUM_MID_ACCENT = ' + str(beatsList) + '\n' + g.write(string) + + # gen high list + beatsList = [[], ] + for beatsPerPage in [1,2,3,4,5,6,7,8,9,10,11,12]: + accents = [] + for j in GenerationConstants.HIGH_ACCENTS[beatsPerPage]: + accents.append(j * Config.TICKS_PER_BEAT / 2) + beatsList.append(accents) + beats = [] + downBeats = [] + 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 ] ], int( pow( float( len( beats ) - i) / len( beats ), 1.5 ) * 100.) ) ) + high_list.append(downBeats) + + string = ' DRUM_HIGH_PROB = ' + str(high_list) + '\n' + f.write(string) + string = ' DRUM_HIGH_ACCENT = ' + str(beatsList) + '\n' + g.write(string) + + f.close() + g.close() + -- cgit v0.9.1