def _getMelody(self, lengthInBars, scale, slowToFast = 0.9, simpleToComplex = 0.1, lowToHigh = 0.8, breakAmount = 0.5, ): """Returns a Track instance with a melody, mostly containing single notes.""" lengthInBars = int(lengthInBars) track = Track() pos = 0.0 while pos < lengthInBars: """Length of the note(s). Calculating length as 2 ** length. -> 0 is a whole, -1 is a half, etc. """ maxLength = 2 # 4 wholes minLength = -5 # 1/32 mode = (3.0 * slowToFast + simpleToComplex) / 4.0 steepness = 10 length = 2 ** int(round(((-abs(maxLength-minLength)) * beta(mode, steepness)) + maxLength)) if random.random() < breakAmount: chord = Chord() """Number of notes taken.""" maxNumberOfNotes = 3 mode = simpleToComplex steepness = 100 numberOfNotes = int(round(maxNumberOfNotes * beta(mode, steepness) ** 4.0)) + 1 """Deciding if pentatonic or not.""" pentatonic = simpleToComplex <= 0.5 """Length of the note(s). Calculating length as 2 ** length. -> 0 is a whole, -1 is a half, etc. """ maxLength = 2 # 4 wholes minLength = -5 # 1/32 mode = (3.0 * slowToFast + simpleToComplex) / 4.0 steepness = 10 length = 2 ** int(round(((-abs(maxLength-minLength)) * beta(mode, steepness)) + maxLength)) """Octaves of the note(s). I was a little bit tired when I wrote this code... irgh """ # number of octaves maxNumberOfOctaves = 7 mode = (4.0 * simpleToComplex + (1.0 - lowToHigh)) / 5.0 steepness = 40 numOctaves = int(round(beta(mode, steepness) * (maxNumberOfOctaves-1))) + 1 # choosing specific octaves minOctave = 0 maxOctave = 7 mode = (4.0 * lowToHigh + simpleToComplex) / 5.0 steepness = 400 octave = beta(mode, steepness) * (maxOctave - minOctave) + minOctave if lowToHigh <= 0.5: octave = math.floor(octave) else: octave = math.ceil(octave) minOctave = int(octave) maxOctave = int(octave) cnt = 0 if lowToHigh <= 0.5: while numOctaves > 1: if cnt % 2 == 0: minOctave -= 1 else: maxOctave += 1 numOctaves -= 1 cnt += 1 else: while numOctaves > 1: if cnt % 2 == 0: maxOctave += 1 else: minOctave -= 1 numOctaves -= 1 cnt += 1 chord = scale.getRandomChord(minOctave = minOctave, maxOctave = maxOctave, minSize = numberOfNotes, maxSize = numberOfNotes, # number of notes in the chord keyAsBase = True, # only baseNote is the key, models getRandomNote basicOnly = False, # contain only I, IV, V and parallel as base note seconds = True, # if chords may contain seconds thirds = True, # if chords may contain thirds fourths = (not pentatonic), # if chords may contain fourths fifths = True, # if chords may contain fourths sixths = True, # if chords may contain sixths sevenths = (not pentatonic), # if chords may contain sevenths allowDirectSemitones = True, # if direct semitones shall be allowed in the chord) ) track.appendChord(chord, length) else: track.appendBreak(length) pos += length return track
def getSynth(self, samplerate, melodyToPad = 0.5, calmToExciting = 0.5, brightToDark = 0.5, softToHard = 0.5, clearToRich = 0.5, ): """This method returns a Synth matching the requirements. It uses REALLY COOL algorithms to embed the parameters into the Synth. Python's random module is used to generate random parameters. Therefore, a seed can be used to generate the exact same song twice. That seed needs to be fed to the Composer instance. The beta-distribution is used a lot in this code as its density function can be centered very easily and it naturally yields values in [0.0, 1.0]. More on the beta distribution in the misc.additionalmath module. """ """Set up synth.""" synth = Synth(samplerate) """Waveforms""" synth.setParameter(SynthParameters.OSC_ALL_WAVEFORM, Waveform.SAW) """Oscillator gain""" #synth.setParameter(SynthParameters.OSC_ALL_GAIN, 1.0) synth.setParameter(SynthParameters.OSC_1_GAIN, 1.0) synth.setParameter(SynthParameters.OSC_2_GAIN, 1.0) synth.setParameter(SynthParameters.OSC_3_GAIN, 1.0) """Oscillator detune Depends on - brightToDark - clearToRich """ for i in range(SynthParameters.NUM_OSCILLATORS): mode = (brightToDark + 2.0 * clearToRich) / 3.0 steepness = 1000 # high steepness, we dont want to much detune maxDetune = 50.0 # 50 cents detune = 2.0 * maxDetune * beta(mode, steepness) - maxDetune synth.setParameter(SynthParameters.OSC_1_DETUNE + i, detune) """Volume envelope Depends on: - melodyToPad - calmToExciting - softToHard """ maxAttack = 4.0 maxDecay = 3.0 maxRelease = 10.0 for i in range(SynthParameters.NUM_OSCILLATORS): mode = (5.0 * melodyToPad + (1.0 - calmToExciting) + (1.0 - softToHard)) / 7.0 steepness = 40 attack = maxAttack * beta(mode, steepness) ** 1.5 decay = maxDecay * beta(mode, steepness) ** 1.5 mode = (3.0 * melodyToPad + (1.0 - calmToExciting) + (1.0 - softToHard)) / 5.0 steepness = 40 release = maxRelease * beta(mode, steepness) synth.setParameter(SynthParameters.OSC_1_VOLUME_ENEVELOPE_ATTACK + i, attack) synth.setParameter(SynthParameters.OSC_1_VOLUME_ENEVELOPE_DECAY + i, decay) synth.setParameter(SynthParameters.OSC_1_VOLUME_ENEVELOPE_RELEASE + i, release) """Cutoff + Resonance Depend on: - melodyToPad (resonance not) - calmToExciting - softToHard """ # for i in range(SynthParameters.NUM_OSCILLATORS): # cutoff mode = ((1.0 - melodyToPad) + calmToExciting + 3.0 * softToHard) / 5.0 steepness = 20 cutoff = beta(mode, steepness) ** 3.0 # resonance mode = (calmToExciting + softToHard) / 2.0 steepness = 2 resonance = beta(mode, steepness) ** 1.5 synth.setParameter(SynthParameters.OSC_ALL_CUTOFF, cutoff) synth.setParameter(SynthParameters.OSC_ALL_RESONANCE, resonance) """LFO Depend on - calmToExciting - softToHard """ mode = calmToExciting steepness = 3 frequency = beta(mode, steepness) ** 2.0 mode = (calmToExciting + softToHard) / 2.0 steepness = 20 lfoToVolume = beta(mode, steepness) ** 6.0 mode = (calmToExciting + softToHard) / 2.0 steepness = 20 lfoToFilter = beta(mode, steepness) ** 6.0 synth.setParameter(SynthParameters.LFO_FREQUENCY, frequency) synth.setParameter(SynthParameters.LFO_TO_VOLUME, lfoToVolume) synth.setParameter(SynthParameters.LFO_TO_FILTER, lfoToFilter) return synth