def cello(score, knum): """ Creates the cello part on channel 2. Parameters ---------- score : Score The musical score to add events to. knum : int The midi key number of the clarinet. """ score.add(Note(time=score.now, duration=.05, pitch=knum-18, amplitude=.9, instrument=2)) score.add(Note(time=score.now, duration=.05, pitch=knum-23, amplitude=.9, instrument=2)) yield -1
def playpenta(score, num, dur, amp, keys): pat = jumble(keys) for _ in range(num): k = next(pat) n = Note(time=score.now, duration=dur * 2, pitch=k, amplitude=amp) score.add(n) yield odds(.2, 0, dur)
def playmicro(score, key, rhy, divs): inc = 1 / divs for i in range(12 * divs + 1): note = Note(time=score.now, duration=rhy, pitch=key) score.add(note) key += inc yield rhy
def fm_improv(score, line, beat): """ Uses a contour line of carrier frequencies (specified as midi keynums) to produces fm spectra that creates both melodic and harmoinc gestures. The inputs and outputs of the fmspectrum() calls are printed during the improvisation. """ amp = .7 dur = beat for knum in line: ismel = odds(.7) rhy = pick(dur, dur / 2, dur / 4) f, r, x = hertz(knum), between(1.1, 1.9), pick(1, 2, 3) #print("\ncarrier=",f,"c/m ratio=",r,"fm index=",x) spec = fmspectrum(f, r, x) keys = spec.keynums(unique=True, minkey=knum - 14, maxkey=knum + 14) if ismel: random.shuffle(keys) sub = rhy / len(keys) if ismel else 0 #print("melody:" if ismel else "chord:", "time=", score.now, "duration=", rhy, "keys=", keys) for i, k in enumerate(keys): m = Note(time=score.now + (i * sub), duration=dur, pitch=k, amplitude=amp) score.add(m) yield rhy
def piano_phase(score, end, keys, rate): """ Composes a piano part for Steve Reich's Piano Phase. Parameters ---------- score : Score The scheduling queue to run the composer in. end : int | float The total duration of the piece. keys : list A list of midi key numbers to play in a loop. rate : int | float The rhythm to use. """ # Create a cyclic pattern to produce the key numbers. pattern = cycle(keys) # Stop playing when score time is >= end. while score.now < end: # Get the next key number. knum = next(pattern) # Create a midi note to play it. note = Note(time=score.now, duration=rate, pitch=knum, amplitude=.9) # Add the midi note to the score. score.add(note) # Return the amount of time until this composer runs again. yield rate
def ghosts(score): """ Creates mid-range clarinet line and decorates it with calls to the other instrument composers. Parameters ---------- score : Score The musical score to add events to. """ for _ in range(12): here = score.elapsed ahead = (here + 1/2) * 2 melody = between(53, 77) high = (melody >= 65) amp = .2 if high else .4 rhy = choice([1/4, 1/2, 3/4]) # the clarinet line midi = Note(time=score.now, duration=rhy + .2, pitch=melody, amplitude=amp, instrument=1) score.add(midi) # add decorations to the clarinet melody if high: score.compose([ahead, flute(score, melody, ahead)]) score.compose([ahead * 2, harp(score, melody, rhy / 4)]) elif (rhy == 3/4): score.compose([1/2, cello(score, melody)]) yield rhy
def sierpinski(score, tone, shape, trans, levels, dur, amp): """ Generates a melodic shape based on successive transpositions (levels) of itself. Parameters ---------- score : Score The musical score to add events to. tone : keynum The melodic tone on which to base the melody for the current level. shape : list A list of intervals defining the melodic shape. levels : int The number of levels the melody should be reproduced on. dur : int | float The duration of the process. amp : float The amplitude of the process. """ num = len(shape) for i in shape: k = tone + i # play current tone in melody n = Note(time=score.now, duration=dur, pitch=min(k,127), amplitude=amp, instrument=0) score.add(n) if (levels > 1): # sprout melody on tone at next level score.compose(sierpinski(score, (k + trans), shape, trans, levels - 1, dur / num, amp)) yield dur
def motive1(score, octave, limit, chan): """ Motive1 generates three notes in random order but always with a whole step and minor seventh sounding. The motive can be randomly transposed within limit half-steps. Parameters ---------- score : Score The score. octave : int The octave to play the notes in. limit : int The maximum transposition in half steps. chan : int The midi channel to assign to the notes. """ # the basic pitches to transpose and jumble e.g. [F#4 E4 D5]. pitches = jumble([6, 4, 14]) # one of the three pitches will be louder than the others. amps = jumble([.75, .5, .5]) # randomly chosen transpostion within a limit offset = random.randrange(limit) for _ in range(3): knum = next(pitches) + (octave * 12) + offset note = Note(time=score.now, duration=.1, pitch=knum, amplitude=next(amps), instrument=chan) score.add(note) yield .2
def accompaniment(score, reps, dur, set1, set2): """ Creates the accompanyment part from the ring modulation input specta. Parameters ---------- score : Score The musical score. reps : int The number of sections to compose. dur : int The surface rhythm set1 : list Ring modulation input 1. set2 : list Ring modulation input 2. """ # Create a cycle of the two inputs pat = cycle([set1, set2]) for _ in range(reps * 2): # Get the next set. keys = next(pat) # Iterate the keys, play as a chord. for k in keys: # Create a midi note at the current time. n = Note(time=score.now, duration=dur, pitch=k, amplitude=.3, instrument=0) # Add it to our output seq. score.add(n) # Wait till the next chord. yield dur
def melody(score, reps, dur, set3): """ Creates the melodic part out of the ring modulated output specta. Parameters ---------- score : Score The musical score. reps : int The number of sections to compose. dur : int The surface rhythm keys : list List of keynums from ring modulation output. """ # Create a cycle of the two inputs pat = cycle(set3) for _ in range(2 * reps): n = Note(time=score.now, duration=dur / 2, pitch=next(pat), amplitude=.7, instrument=1) score.add(n) # Wait till the next note yield dur
def playbells(score, peal, bells, rhy, dur, amp): # each bell represented by its 'prime' harmonic. primes = {k: bells[k][1] for k in bells.keys()} # play the peal (the ordered list of bells to play) for b in peal: # emphasize top and bottom bell by playing all its harmonics. if b in ['a', 'j']: # keynums are quantized to 25 cents for k in [x for x in bells[b]]: m = Note(time=score.now, duration=dur * 4, pitch=k, amplitude=amp) score.add(m) else: # else play single 'prime' note k = primes[b] m = Note(time=score.now, duration=dur, pitch=k, amplitude=amp) score.add(m) yield rhy
def motive2(score, octave, limit, chan): """Motive2 generates a repeated tone with one tone accented.""" amps = jumble([.75, .5, .5]) rhys = jumble([.2, .2, .4]) offset = random.randrange(limit) for _ in range(3): knum = 0 + (octave * 12) + offset note = Note(time=score.now, duration=.1, pitch=knum, amplitude=next(amps), instrument=chan) score.add(note) yield next(rhys)
def register(score, rhy, dur, low, high, amp): """ Generates a chromatic scale betwen low and high choosing notes from the scale in random. """ pat = jumble(scale(low, high - low + 1, 1)) while score.elapsed < dur: keyn = next(pat) note = Note(time=score.now, duration=rhy, pitch=keyn, amplitude=amp) score.add(note) yield rhy
def jazz_cymbals(score, tmpo, ampl): """ The cymbals process performs a constant stream of triplet eighths in which the ride1 cymbal is played on the beginning of every quarter note. The second and third triplets of each beat are either rests or a random choice between ride1, ride2 or a rest. This is the beat map for a measure of the process, where '1' means the ride cymbal 1 is played, '-' means a rest, and 'x' means a random choice between ride1, ride2 or a rest: ```text Triplet 8th: 1 2 3 4 5 6 7 8 9 10 11 12 Cymbals: 1 - x 1 - 1 1 x x 1 x 1 ``` """ ride1 = 51 ride2 = 59 rhy = intempo(1 / 3, tmpo) amps = cycle([.6, .5, .9, .7, .5, 1, .6, .5, .9, .7, .5, 1]) def subpat(wt): r1 = choose([ride1, 'r'], [1, wt]) r2 = choose([ride2, 'r'], [1, wt]) return choose([r1, r2], [1.5, 1]) # the events that happen on each triplet of the measure meas = { 0: ride1, 1: 'r', 2: subpat(5), 3: ride1, 4: 'r', 5: ride1, 6: ride1, 7: subpat(7), 8: subpat(7), 9: ride1, 10: subpat(3), 11: ride1 } for b in meas: k = meas[b] if k != 'r': if type(k) is not int: # k is a subpattern k = next(next(k)) if k != 'r': a = next(amps) m = Note(time=score.now, duration=rhy, pitch=k, amplitude=a * ampl, instrument=9) score.add(m) yield rhy
def fm_chords(score, reps, cen, cm1, cm2, in1, in2, rhy): """ Generates a series of FM chords with random fluctuations in its C/M ratios and indexes to yield variations of chordal notes. """ for _ in reps: spec = fmspectrum(hertz(cen), between(cm1, cm2), between(in1, in2)) for k in spec.keynums(minpitch=48, maxpitch=72): m = Note(time=score.now, duration=rhy, pitch=k, amplitude=.5) score.add(m) yield rhy
def flute(score, knum, dur): """ Creates the flute part on channel 0. Parameters ---------- score : Score The musical score to add events to. knum : int The midi keynumber of the clarinet. dur : int | float The duration of the note. """ score.add(Note(time=score.now, duration=dur, pitch=knum+24, amplitude=.2, instrument=0)) yield -1
def harp(score, knum, rate): """ Creates an arpeggiating harp part on channel 3. Parameters ---------- score : Score The musical score to add events to. knum : int The midi keynumber of the clarinet. rate : int | float The rhythm of the arpeggio. """ for k in steps(39 + (knum % 13), 13, 5): m = Note(time=score.now, duration=10, pitch=k, amplitude=.5, instrument=3) score.add(m) yield rate
def jazz_bass(score, on, tmpo, ampl): """ The bass part plays a melodic line built out of tones from the jazz-scale's tonic seventh chord alternating with color tones outside the tonic chord. The bass plays a series of 12 triplets per measure, on each triplet only one of the two sets is possible. On all but the first triplet a rest is also possible. """ # 5 possible patterns for triplets 1-4 a = choose(['trrc', 'trrr', 'trtc', 'tctc', 'tctr'], [1.0, .25, .22, .065, .014]) # 5 possible patterns for 5-7 b = choose(['rrt', 'rrr', 'rct', 'tct', 'tcr'], [1.0, .25, .22, .038, .007]) # 5 possible patterns for 8-10 c = choose(['rrc', 'rtc', 'rrr', 'ctc', 'ctr'], [1.0, .415, .25, .11, .018]) # two possible values for 11 d = choose(['r', 't'], [1, .25]) # two possible values for 12 e = choose(['r', 'c'], [1, .25]) # the measure map meas = next(a) + next(b) + next(c) + next(d) + next(e) rhy = intempo(1 / 3, tmpo) tonics = choose([jazz_scale[i] for i in [0, 2, 4, 6, 7]]) colors = choose([jazz_scale[i] for i in [1, 3, 5, 6, 8]]) amps = cycle([.5, .4, 1.0, .9, .4, .9, .5, .4, 1.0, .9, .5, .9]) durs = cycle([2 / 3, 1 / 3, 1 / 3]) for x in meas: k = -1 if x == 't': k = next(tonics) elif x == 'c': k = next(colors) if k > -1: a = next(amps) d = next(durs) m = Note(time=score.now, duration=d, pitch=on + k, amplitude=ampl * a, instrument=1) score.add(m) yield rhy
def jazz_high_hat(score, tmpo, ampl): """ Plays the High Hat on the second and fourth quarter of every measure and rests on the first and third beats. Each sound lasts for the duration one triplet eighth note i.e. 1/3 of a beat. """ rhy = intempo(1, tmpo) dur = intempo(1 / 3, tmpo) amp = .5 pat = cycle(['r', 42, 'r', 42]) # 'r' is rest for _ in range(4): x = next(pat) if x != 'r': m = Note(time=score.now, duration=dur, pitch=x, amplitude=amp * ampl, instrument=9) score.add(m) yield rhy
def composer_stephen_foster(score, num, shift=0, chan=0): # A second-order markov process generates the melody. melody = pattern_stephen_foster() # randomly select rhythmic patterns characterisitic of Foster's style rhythms = choose( [[2, 2], [1, 1, 1, 1], [2, 1, 1], [1, 1, 2], [1, 2, 1], [4]], [.375, .125, .125, .125, .25, .125]) for _ in range(num): n = 0 for r in next(rhythms): k = keynum(next(melody)) + (shift * 12) r = intempo(r, 200) m = Note(time=score.now + n, duration=r, pitch=k, amplitude=.5, instrument=chan) score.add(m) n += r yield n
def jazz_piano(score, on, tmpo, ampl): """ The jazz piano improvises jazz chords based on a pattern of root changes and a scale pattern that is transposed to each root. The piano randomly choose between playing triplet eighths or straight eights for a given measure. """ reps = odds(.65, 8, 12) scal = jumble(jazz_scale) rhys = cycle([2 / 3, 1 / 3] if reps == 8 else [1 / 3]) for _ in range(reps): r = intempo(next(rhys), tmpo) l = [] if odds(2 / 5) else [next(scal) for _ in range(between(1, 9))] for k in l: a = pick(.4, .5, .6, .7, .8) m = Note(time=score.now, duration=r, pitch=on + k, amplitude=a, instrument=0) score.add(m) yield r
def jazz_drums(score, tmpo, ampl): """ Randomly selects between playing the snare, the bass drum or resting one quarter of the time. One tenth of the time it produces a very loud tone. """ elec_snare = 40 bass_drum = 35 knums = choose(['r', elec_snare, bass_drum], [.25, 1, 1]) rhys = cycle([2 / 3, 1 / 3]) amps = choose([.7, .95], [1, .1]) for _ in range(8): k = next(knums) a = next(amps) r = intempo(next(rhys), tmpo) if k != 'r': m = Note(time=score.now, duration=r, pitch=k, amplitude=a * ampl, instrument=9) score.add(m) yield r
def spray(score, *, length=None, end=None, rhythm=.5, duration=None, pitch= 60, band=0, amplitude=.5, instrument=0): """ Generates Notes using discrete random selection. Most parameters allow lists of values to be specified, in which case elements are randomly selected from the lists every time an event is output. Parameters ---------- Parameters are the same as brush() except for these changes or additions: pitch : number | list A MIDI key number or list of key numbers to play. If a list is specified a key number is randomly selected from the list for each midi event. band : number | list A number is treated as a half-step range on either side of the current key choice from which the next key number will be chosen. If a list of intervals is specified then randomly selected intervals are added added to the current key number to determine the key number played. The list can also contain sublists of intervals, in which case each sublist is treated as a chord, i.e. the intervals in the sublist are added to the current key and performed simultaneously. """ # user must specify either length or end parameter counter = 0 if length: if end: raise TypeError("specify either leng or end, not both.") stopitr = length thisitr = (lambda: counter) else: if not end: raise TypeError("specify either length or end.") stopitr = end thisitr = (lambda: score.elapsed) # convert each param into a chooser pattern. ran = (lambda x: choose(x if type(x) is list else [x])) rhy = ran(rhythm) dur = ran(duration) key = ran(pitch) amp = ran(amplitude) chan = ran(instrument) band = choose( [i for i in range(-band, band+1)] if type(band) is int else band ) while (thisitr() < stopitr): t = score.now #print("counter=", counter, "now=", t) r = next(rhy) d = next(dur) k = next(key) a = next(amp) c = next(chan) b = next(band) if type(b) is list: k = [k+i for i in b] else: k = k + b #print("pitch=", k, end=" ") if r > 0: if not d: d = r if type(k) is list: for j in k: m = Note(time=t, duration=d, pitch=j, amplitude=a, instrument=c) score.add(m) else: m = Note(time=t, duration=d, pitch=k, amplitude=a, instrument=c) score.add(m) counter += 1 yield abs(r)
def brush(score, *, length=None, end=None, rhythm=.5, duration=None, pitch=60, amplitude=.5, instrument=0, microdivs=1): """ Outputs Notes in sequential order, automatically looping parameter list values until the algorithm stops. Parameters ---------- score : Score The Notes that are generated will be added to this score. length : number The number of MIDI events to generate. Either length or end must be specified. end : number An end time after which no more events will be generated. Either end or length must be specified. rhythm : number | list A rhythm or list of rhythms that specify the amount of time to wait between notes. Negative rhythm values are interpreted as musical rests, i.e. events are not output but time advances. The default value is 0.5. duration : number | list A duration or list of durations that specify the amount of time each MIDI event lasts. The default value is the current rhythm. pitch : number | list A MIDI key number or list of key numbers to play. The list can contain sublists of key numbers; in this case each sublist is treated as a chord (the key numbers in the sublist are performed simultaneously.) amplitude : number | list A value or list of values between 0.0 and 1.0 for determining the loudness of the MIDI events. instrument : number | list A MIDI channel number 0 to 15, or a list of channel numbers. Channel value 9 will send events to the synthesizer's drum map for triggering various percussion sounds. tuning : int A value 1 to 16 setting the divisions per semitone used for microtonal quantization of floating point keynums. See Note, Seq and the micro.py demo file for more information. """ # user must specify either length or end parameter counter = 0 if length: if end: raise TypeError("specify either length or end, not both.") stopitr = length thisitr = (lambda: counter) else: if not end: raise TypeError("specify either length or end.") stopitr = end thisitr = (lambda: score.elapsed) # convert all values into cycles cyc = (lambda x: cycle(x if type(x) is list else [x])) rhy = cyc(rhythm) dur = cyc(duration) key = cyc(pitch) amp = cyc(amplitude) chan = cyc(instrument) while (thisitr() < stopitr): t = score.now #print("counter=", counter, "now=", t) r = next(rhy) d = next(dur) k = next(key) a = next(amp) c = next(chan) if r > 0: if not d: d = r if type(k) is list: for j in k: m = Note(time=t, duration=d, pitch=j, amplitude=a, instrument=c) score.add(m) else: m = Note(time=t, duration=d, pitch=k, amplitude=a, instrument=c) score.add(m) counter += 1 yield abs(r)