I've been working on an algorithmic music-generating program written in Python. It uses the function below to convert its numerical output (the same output that is converted to sound) into Lilypond text output, thus automatically producing scores (or midi files).
I thought it might be of interest to those working in similar areas. Any feedback appreciated. Regards, John Python code: def auto_lily(arg, tempo=120, percussion=False, bass=False, midi=False, filename="auto_lily"): """Translate arg into a Lilypond score or midi file. Arg must be a list of bars. A bar is a list of 2-tuples, of which the first element is a list of integers representing pitches, and the second is an integer representing duration. For example: [ [([0, 4, 7], 4), ([0, 4, 7], 4)], [([0, 4, 7], 8)] ] will be converted to a bar of two C-major chords each four quavers in length, followed by a bar of one C-major chord eight quavers in length.""" pitch_dict = { 0:" c", 1:" cis", 2:" d", 3:" dis", 4:" e", 5:" f", 6:" fis", 7:" g", 8:" gis", 9:" a", 10:" ais", 11:" b", "rest":"r" } duration_dict = {1:str(8), 2:str(4), 3:str(4)+"." , 4:str(2) , 6:str(2)+".", 7:str(2) + "." + ".", 8:str(1) } if percussion: clef = "percussion" elif bass: clef = "bass" else: clef = "treble" clef = "\n \\clef " + clef tempo = " \n \\tempo 4 = " + str(tempo) score = [" \\score { \n\n \\version \"2.10.33\" { ", clef, tempo] last_octave = "" last_time_sig = "" for bar in arg: highest = max([max(event[0]) for event in bar]) lowest = min([min(event[0]) for event in bar]) middle = (highest + lowest) / 2 if middle >= 30 : octave = 2 elif middle in range(18, 30): octave = 1 elif middle in range(-18, 18): octave = 0 elif middle in range(-30, -18): octave = -1 elif middle < -30 : octave = -2 octave =" #(set-octavation " + str(octave) +")" if octave == last_octave: octave = "" else: last_octave = octave numerator = sum([event[1] for event in bar]) if (numerator != 6) and (numerator != 12) and not numerator % 2: numerator /= 2 time_sig = " \n \\time " + str(numerator) + "/4" else: time_sig = " \n \\time " + str(numerator) + "/8" if time_sig == last_time_sig: time_sig = "" else: last_time_sig = time_sig newbar = ["\n", time_sig, octave, "\n"] for event in bar: duration = event[1] if duration == 0: continue else: if len(event) > 1: openchord , closechord = " < ", " > " else: openchord , closechord = "", "" pitches = [openchord] for i in event[0] : tag = [""] if i >= 0: for _ in range(((i)/12 + 1)) : tag.append("'") else: for _ in range(abs(((i)/12 + 1))) : tag.append(",") pitches += [pitch_dict[(i) % 12]] + tag pitches.append(closechord) pitches = ''.join(pitches) if duration == 5: newbar += [pitches, " 2", " ~", pitches, "8"] elif duration <= 8: newbar += [pitches, duration_dict[duration]] else: semibreves = duration/8 newbar += [pitches, " 1"] for _ in range(1, semibreves): newbar += ["~", pitches, " 1"] if duration % 8 == 5: newbar += [" ~", pitches, " 2" , "~", pitches, "8"] elif duration % 8: newbar += ["~", pitches, duration_dict[ duration % 8]] score += newbar if midi: score.append("\n }\n \\midi \n{ }\n } ") else: score.append("\n }\n }") score = ''.join(score) return score
_______________________________________________ lilypond-user mailing list lilypond-user@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-user