def __init__(self, pits = [], durs = [], chord = [], sub_chunks = None, key = 0, name='', scale = [0,2,4,5,7,9,11], dynamics = 'mf'): self.sub_chunks = sub_chunks self.name = name self.chord = chord #find depth if sub_chunks == None or sub_chunks == []: self.depth = 0 else: self.depth = sub_chunks[0].depth self.key = key self.setKey(key) self.scale = scale #find pits/durs if pits == [] and self.depth > 0: pits = fh.concat([i.pits for i in self.cells]) durs = fh.concat([i.durs for i in self.cells]) self.pits = pits self.durs = durs #get ctype - basically only useful for cells self.ctype = self.getCtype(self.pits) #get beat rhythms and pitches self.beat_durs = [] self.beat_pits = [] self.resetBeatPitsAndDurs() self.length = [] self.setLength()
def __init__(self, pits = [], durs = [], ctype = -1, chord = [], sub_chunks = None, key = 0): self.sub_chunks = sub_chunks self.chord = chord #find depth self.depth = getMaxDepth(self) #get cells self.cells = getCells(self) self.key = key self.setKey(key) #find pits/durs if pits == [] and self.depth > 0: pits = fh.concat([i.pits for i in self.cells]) durs = fh.concat([i.durs for i in self.cells]) self.pits = pits self.durs = durs #get ctype - basically only useful for cells self.ctype = ctype #get beat rhythms and pitches self.beat_durs = [] self.beat_pits = [] self.resetBeatPitsAndDurs()
def fitsBasicIdeaPref(motifs): if sum([sum(i.durs) for i in motifs]) != 8.0: return False if motifs[0].pits == motifs[1].pits and motifs[0].durs == motifs[1].durs: return False if abs(motifs[0].pits[-1] - motifs[1].pits[0]) > 2: return False all_pits = fh.concat([i.pits for i in motifs]) all_durs = fh.concat([i.durs for i in motifs]) if len(set(all_pits)) < 3: return False if all_durs.count(2.0) > 2: return False return True
def __init__(self, sub_chunks = None, cells = None, pits = [], durs = [], ctype = -1, name = '', names = {}, harm = None, structure = '', start_time = 0, depth = -1): self.sub_chunks = sub_chunks #find depth self.depth = getMaxDepth(self) self.max_depth = getMaxDepth(self) self.min_depth = getMinDepth(self) #set names of substructures and name of larger structure self.name = name self.names = names self.name = '' self.setName(name) #set harmony self.harm = harm #set structure if structure == '': self.structure = getStructure(self) else: self.structure = structure #create a dict of all of the different sub_chunks of all sizes self.all_chunks = getAllChunks(self) #get cells if cells == None: self.cells = getCells(self) #self.resetStructure() else: self.cells = cells #find pits/durs if pits == [] and self.depth > 0: pits = fh.concat([i.pits for i in self.cells.values()]) durs = fh.concat([i.durs for i in self.cells.values()]) self.pits = pits self.durs = durs #set ctype - basically only useful for cells self.ctype = ctype #set start time self.start_time = start_time #get beat rhythms and pitches self.beat_durs = [] self.beat_pits = [] self.resetBeatPitsAndDurs()
def goodCells(cells): if not all([len(i.pits) == len(i.durs) for i in cells]): return False pits = fh.concat([j.pits for j in cells]) #no leaping from non-tone chord if not hm.inChord(cells[0].pits[-1], cells[0].chord) and abs(cells[0].pits[-1] - cells[1].pits[0]) > 1: return False pit_diffs = [abs(pits[i] - pits[i - 1]) for i in range(1, len(pits))] #no three in a row for i in range(2, len(pits)): if abs(pits[i] - pits[i - 1]) == 6: return False if pits[i] == pits[i - 1] and pits[i - 2] == pits[i]: return False if (pits[i] % 7) == 3 and (pits[i - 1] % 7) == 6 or (pits[i] % 7) == 6 and (pits[i - 1] % 7) == 3: return False #no jumps bigger than 4 if max(pit_diffs) > 4: return False #no notes lower than -3 if min(pits) < -3: return False if max(pits) > 20: return False for i in range(1, len(cells)): if (cells[i - 1].pits[-1] % 7) == 3 and cells[i].chord == [0,2,4] and (cells[i].pits[0] % 7) != 2: return False if (cells[i - 1].pits[-1] % 7) == 6 and cells[i].chord == [0,2,4] and (cells[i].pits[0] % 7) != 0: return False if len(cells) > 1: if max(pits) - min(pits) < 4: return False return True
def closestNoteDegreeInChord(note, chord, same = True, up_down = 0): #print(note) #print(chord) allnotes = fh.concat([map(lambda j: i + j, chord) for i in range(-14,14,7)]) tmp_allnotes = allnotes if up_down == 1: allnotes = filter(lambda i: i >= note, allnotes) elif up_down == -1: allnotes = filter(lambda i: i <= note, allnotes) if allnotes == [] and up_down == 1: allnotes = [tmp_allnotes[-1]] elif allnotes == [] and up_down == -1: allnotes = [tmp_allnotes[0]] dChords = map(lambda i: abs(note - i), allnotes) if same: minindex = min(enumerate(dChords), key=itemgetter(1))[0] return allnotes[minindex] else: minnotsameindex = -1 minnotsame = 1000 for i in range(0, len(dChords)): if dChords[i] != 0 and dChords[i] < minnotsame: minnotsame = dChords[i] minnotsameindex = i return allnotes[minnotsameindex]
def showCells(cells, degrees = True): pitches = [] mpitches = ([i.pits for i in cells]) for i in range(0, len(mpitches)): pitches.extend(mpitches[i][:len(cells[i].pits)]) if degrees: pitches = sc.degreesToNotes(pitches) durs = fh.concat([i.durs for i in cells]) score = listsToStream(pitches, durs) score.show()
def writeCells(cells, fname, degrees = True): pitches = [] mpitches = ([i.pits for i in cells]) for i in range(0, len(mpitches)): pitches.extend(mpitches[i][:len(cells[i].pits)]) if degrees: pitches = sc.degreesToNotes(pitches) durs = fh.concat([i.durs for i in cells]) score = listsToStream(pitches, durs) score.write(fmt = 'musicxml', fp = fname)
def writePhrase(motifs, fname, degrees = True): pitches = [] mpitches = ([i.l0p for i in motifs]) for i in range(0, len(mpitches)): pitches.extend(mpitches[i][:len(motifs[i].l0d)]) if degrees: pitches = sc.degreesToNotes(pitches) durs = fh.concat([i.l0d for i in motifs]) score = listsToStream(pitches, durs) score.write(fmt = 'musicxml', fp = fname)
def genBasicIdea(prev_note = random.choice([0,2,4,7]), chords = [[0,2,4], [4,6,8], [0,2,4], [0,2,4]], motif1 = None, cell1 = None): if motif1 == None: motif1 = gm.genMotif(prev_note = prev_note, chords = chords[:2], cell1 = cell1) motif1_durs = fh.concat([i.durs for i in motif1]) if 2.0 in motif1_durs or motif1_durs == [1.0,1.0,1.0,1.0]: motif2 = gm.genMotif(prev_note=motif1[1].pits[-1], chords = chords[2:]) return Chunk(sub_chunks = motif1 + motif2, ctype='bi') else: motif2 = tf.transformMotif(transform_motif=motif1, prev_cell=motif1[0], chords=chords[2:]) return Chunk(sub_chunks = motif1 + motif2, ctype='bi')
def cellsToPart(cells, leading = True, octave = 5): durs = fh.concat([i.durs for i in cells]) pitches = [i.pits for i in cells] #if there is a stretch where too low or high, fix midi_pitches = [] for i in range(0, len(pitches)): midi_pitches.extend(sc.degreesToNotes(pitches[i], scale = scales["C major"], octave = octave)) #pitches, durs = smooth.smoothOut(pitches, durs, leading) score = listsToPart(midi_pitches, durs) return score
def fitsMotifPref(cells): if sum([sum(i.durs) for i in cells]) != 4.0: return False if cells[0].pits == cells[1].pits and cells[0].durs == cells[1].durs: #print('in same') return False if abs(cells[0].pits[-1] - cells[1].pits[0]) > 2: #print('in too far apart') return False all_pits = fh.concat([i.pits for i in cells]) all_durs = fh.concat([i.durs for i in cells]) if len(all_pits) > 4 and len(set(all_pits)) < 3: #print('in not enough pits') return False if all_durs.count(1.0) > 3: #print('in too many 1.0') return False if all_durs.count(2.0) > 1: #print('in too many 2.0') return False return True
def getDefiningRhythm(cells): durs = fh.concat([i.durs for i in cells]) if 0.75 in durs: if random.uniform(0,1) < 0.7: return [0.75,0.25,0.75,0.25] else: return [0.75,0.25,0.5,0.5] elif 1.5 in durs: return [1.5, 0.25, 0.25] elif 0.33333333 in durs: return [1.0,0.33333333,0.33333333,0.33333333] else: return randomDuration(2.0, triplets = False)
def pitchesDursToPart(pitches, durs, key_area, octave = 5): durs = fh.concat(durs) midi_pitches = [] for i in range(0, len(pitches)): skale = scales["G major"] if key_area[i] == 7 else scales["C major"] for j in range(0, len(pitches[i])): if type(pitches[i][j]) == tuple: cord = tuple(sc.degreeToNote(pitch, octave, scale = skale) for pitch in pitches[i][j]) midi_pitches.append(cord) else: midi_pitches.append(sc.degreeToNote(pitches[i][j], octave = octave, scale = skale)) #pitches, durs = smooth.smoothOut(pitches, durs, leading) score = listsToPart(midi_pitches, durs) return score
def randomDuration(length = 2.0, same = '', avoid = []): if length == 2.0: new_prob_dict = {} for val, prob in two_prob_dict.items(): if val not in avoid: new_prob_dict[val] = prob return strToRhy(ph.probDictToChoice(new_prob_dict)) elif length == 4.0: if same == '': same = random.choice([True, False]) if same: a = notHalfNote() return fh.concat([a,a]) else: if random.uniform(0,1) < 0.1 and '3.0 1.0' not in avoid and '3.0 0.5 0.5' not in avoid and '1.0 2.0 1.0' not in avoid: a = strToRhy(ph.probDictToChoice({'3.0 1.0':0.2, '3.0 0.5 0.5':0.4, '1.0 2.0 1.0': 0.6})) return a else: return randomDuration(2.0, avoid=avoid) + randomDuration(2.0, avoid=avoid)
def closenessDistribution(chord, prev_note, dist): if chord == []: return prev_note + random.choice([-1,-1,1,1,-2,2]) if dist == 'close': far_dict = {0:0.6, 1:0.4} elif dist == 'med': far_dict = {0:0.4, 1:0.35, 2:0.2, 3:0.05} n = ph.probDictToChoice((far_dict)) #get note in chord that is nth away from prev_note all_notes_in_chord = fh.concat([[root_note + octave for root_note in chord] for octave in range(-21,21,7)]) #get distances between notes and prev_note notes_distances = map(lambda i: (i, abs(i - prev_note)), all_notes_in_chord) #sort notes_distances by the distance notes_distances = sorted(notes_distances, key = itemgetter(1)) return notes_distances[n][0]
def motifsToPart(motifs, key_area, leading = True, octave = 5): durs = fh.concat([i.l0d for i in motifs]) pitches = [i.l0p for i in motifs] """ prev = pitches[0][0] tot_durs = [sum(durs[:i]) for i in range(0, len(durs)) ] n = 0 for i in range(0, len(pitches)): if i > 0: prev = pitches[i - 1][-1] for j in range(1, len(pitches[i])): if tot_durs[n] % 1.0 != 0: if pitches[i] == prev: pitches[i] += random.choice([1,-1]) if pitches[i][j] > 14: if abs(prev - pitches[i][j] - 7) < 4: pitches[i][j] = pitches[i][j] - 7 elif pitches[i][j] < 0: if abs(prev - pitches[i][j] + 7) < 4: pitches[i][j] = pitches[i][j] + 7 #elif abs(pitches[i][j] - prev) > 4: # pitches[i][j] = pth.getClosestPCDegree(pitches[i][j - 1], pitches[i][j]) prev = pitches[i][j] n += 1 """ #if there is a stretch where too low or high, fix midi_pitches = [] for i in range(0, len(pitches)): if key_area[i] == 0: midi_pitches.extend(sc.degreesToNotes(pitches[i], scale = scales["C major"], octave = octave)) elif key_area[i] == 7: new_pitches = sc.degreesToNotes(pitches[i], scale = scales["G major"], octave = octave) midi_pitches.extend(new_pitches) #pitches, durs = smooth.smoothOut(pitches, durs, leading) score = listsToPart(midi_pitches, durs) return score
motif_patterns.append(reused_pattern) phrs_motifs = ([motifs[i] for i in random.choice(prev_types)]) else: phrs_motifs = [motifs[which_to_start]] which_second = random.choice(range(0, len(motifs))) phrs_motifs.append(mlh.alterMotif(motifs[which_second], random.uniform(0,0.3), random.uniform(0,0.3))) #now, append third motif phrs_motifs.append(mlh.genMotif(4)) #append to list of motifs and motif patterns motifs.append(phrs_motifs[-1]) motif_patterns.append([which_to_start, which_second, len(motifs) - 1]) else: phrs_motifs = [mlh.genMotif(4), mlh.genMotif(4), mlh.genMotif(4)] motifs.extend(phrs_motifs) motif_patterns.append([len(motifs) - 3, len(motifs) - 2, len(motifs) - 1]) #then, divide into phrases phrase_functions_list = dict([(o[0], o[1]) for o in getmembers(ngp) if isfunction(o[1])]) #the probability dict containing names of functions phrase_functions_probs = dict( [ (o[0], probPhraseType(o[0])) for o in getmembers(ngp) if isfunction(o[1]) ]) phrase_type = phrase_functions_list[ph.probDictToChoice(phrase_functions_probs)] phrases.append(phrase_type(phrs_motifs)) phrases = [shiftMotifs(phrase) for phrase in phrases] p = fh.concat(phrases) degrees = fh.concat([i.l0p for i in p]) rhythms = fh.concat([i.l0d for i in p]) degrees, rhythms = smooth.smoothOut(degrees, rhythms) score = mh.listsDegreesToStream(degrees, rhythms, scale = scales["dorian"]) score.show()
__author__ = 'halley' import fitness import functionalhelpers as fh from music21 import * from Note import * candidates = [] for i in range(0,400): fitnesses_and_candidates = zip(map(fitness.fitness, candidates), candidates) fitnesses_and_candidates.sort(reverse=True, key=lambda i:i[0]) bests = [i[1] for i in fitnesses_and_candidates[:50]] candidates = fh.concat(map(genVariations, bests)) best_score = stream.Score() for note_ in bests[0]: n = note.Note(pitToPitch(note_.pit)) n.quarterLength = note_.dur best_score.append(n) best_score.show()
def goodCells(cells, melody = True): for cell in cells: if len(cell.pits) != len(cell.durs): return False if not all([len(i.pits) == len(i.durs) for i in cells]): return False pits = fh.concat([j.pits for j in cells]) durs = fh.concat([j.durs for j in cells]) beat_pits = fh.concat([j.beat_pits for j in cells]) beat_durs = fh.concat([j.beat_durs for j in cells]) #no more than 4 half notes if durs.count(2.0) > 4: return False #no leaping from non-tone chord if not hm.inChord(cells[0].pits[-1], cells[0].chord) and abs(cells[0].pits[-1] - cells[1].pits[0]) > 1: return False pit_diffs = [abs(pits[i] - pits[i - 1]) for i in range(1, len(pits))] for i in range(1, len(pits)): #no jumps of a seventh if abs(pits[i] - pits[i - 1]) == 6: return False #no tritones if (pits[i] % 7) == 3 and (pits[i - 1] % 7) == 6 or (pits[i] % 7) == 6 and (pits[i - 1] % 7) == 3: return False #no three in a row for i in range(2, len(pits)): if pits[i] == pits[i - 1] and pits[i - 2] == pits[i]: return False #no jumps more than an octave if max(pit_diffs) > 7: return False #no two arpeggiated cells for i in range(0, len(beat_pits) - 3): if max(beat_pits[i]) - min(beat_pits[i]) > 4: if max(beat_pits[i + 3]) - min(beat_pits[i + 3]) > 4 or max(beat_pits[i + 1]) - min(beat_pits[i + 1]) > 4 or max(beat_pits[i + 2]) - min(beat_pits[i + 2]) > 4: return False #no more than 3 half notes for i in range(0, len(durs) - 1): if durs[i] == 2.0 and durs[i + 1] == 2.0: return False #no more than 8 quarter notes for i in range(0, len(durs) - 9): if durs[i] == 1.0 and durs[i + 1] == 1.0 and durs[i + 2] == 1.0 and durs[i + 3] == 1.0 and durs[i + 4] == 1.0 and durs[i + 5] == 1.0 and durs[i+6] == 1.0 and durs[i + 7] == 1.0 and durs[i +8] == 1.0: return False #no notes lower than -3 if min(pits) < -3: return False if max(pits) > 20: return False for i in range(1, len(cells)): if (cells[i - 1].pits[-1] % 7) == 3 and cells[i].chord == [0,2,4] and (cells[i].pits[0] % 7) != 2: return False if (cells[i - 1].pits[-1] % 7) == 6 and cells[i].chord == [0,2,4] and (cells[i].pits[0] % 7) != 0: return False if len(cells) > 1: if max(pits) - min(pits) < 4: return False #no doubles of sixteenth notes for i in range(1, len(pits)): if pits[i] == pits[i - 1] and (durs[i] == 0.25 or durs[i - 1] == 0.25): return False if melody: #no annoying 16ths for i in range(0, len(pits) - 3): if durs[i] == 0.25 and durs[i + 1] == 0.25 and durs[i + 2] == 0.25 and durs[i + 3] == 0.25: if pits[i] == pits[i + 2] and pits[i + 1] == pits[i + 3]: return False #no more than 8 eighth notes for i in range(0, len(beat_durs) - 3): if beat_durs[i] == [0.5,0.5] and beat_durs[i + 1] == [0.5,0.5] and beat_durs[i+2] == [0.5,0.5] and beat_durs[i + 3] == [0.5,0.5]: return False #no ending on leading tone for beat_pit in beat_pits: if beat_pit[-1] % 7 == 6: return False return True
def closeChordNotes(chord, start_note, max_distance): allnotes = fh.concat([map(lambda j: i + j, chord) for i in range(-14,14,7)]) allnotes = filter(lambda i: abs(i - start_note) <= max_distance, allnotes) allnotes.sort(key=lambda i: abs(start_note - i)) return allnotes
def closestNoteDegreeInTriad(note, chord): allnotes = fh.concat([[i,i+2,i+4] for i in range(-14,14,7)]) dChords = map(lambda i: abs(note - i), allnotes) minindex = min(enumerate(dChords), key=itemgetter(1))[0] return allnotes[minindex]
# -*- coding: utf-8 -*- """ Created on Mon Dec 29 10:18:04 2014 @author: halley """ import functionalhelpers as fh import music21helpers as mh from music21 import * import scale as sc from constants import * import rhythms as rhy import pitchhelpers as pth #Etude 1: up and down the scale durs = fh.concat([[0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,1.0] for i in range(0,8)]) degs = fh.concat([map(lambda j: j + i, [0,1,2,3,4,3,2,1,0]) for i in range(0,8)]) score = mh.listsDegreesToPart(degs, durs) score.insert(0, meter.TimeSignature('5/4')) #score.show('musicxml') #Etude 2: up and down different scales durs = fh.concat([[0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,1.0] for i in range(0,8)]) degs = fh.concat([sc.degreesToNotes([0,1,2,3,4,3,2,1,0], scale = map(lambda j: j + i, scales["major"])) for i in scales["major"] + [12]]) score = mh.listsToPart(degs, durs) score.insert(0, meter.TimeSignature('5/4')) #score.show('musicxml') #Etude 3: up and down scale with intervals of 2
def getCells(self, chunk): if chunk.depth == 0: return [chunk] else: return fh.concat([self.getCells(i) for i in chunk.sub_chunks])
def closestNotesInChord(note, chord): all_notes = fh.concat([map(lambda j: i + j, chord) for i in range(-14,14,7)]) dChords = [(i, abs(note - i)) for i in all_notes] dChords.sort(key=lambda tup:tup[1]) return [i[0] for i in dChords]