Exemple #1
0
def nextBassNote(inputNote):

	if inputNote.note == "c":
		noteBelow = "b%i" % (inputNote.octave - 1)
		noteAbove = "d%i" % (inputNote.octave) 
	elif inputNote.note == "d":
		noteBelow = "c%i" % (inputNote.octave)
		noteAbove = "e%i" % (inputNote.octave) 
	elif inputNote.note == "e":
		noteBelow = "d%i" % (inputNote.octave)
		noteAbove = "f%i" % (inputNote.octave) 
	elif inputNote.note == "f":
		noteBelow = "e%i" % (inputNote.octave)
		noteAbove = "g%i" % (inputNote.octave) 
	elif inputNote.note == "g":
		noteBelow = "f%i" % (inputNote.octave)
		noteAbove = "a%i" % (inputNote.octave) 
	elif inputNote.note == "a":
		noteBelow = "g%i" % (inputNote.octave)
		noteAbove = "b%i" % (inputNote.octave) 
	else:
		noteBelow = "a%i" % (inputNote.octave)
		noteAbove = "c%i" % (inputNote.octave + 1) 

	return(random.choice([Note(noteBelow),Note(noteAbove)]))
Exemple #2
0
def getAdjacentNotes(inputNote):

	if inputNote.note == "c":
		noteBelow = "b%i" % (inputNote.octave - 1)
		noteAbove = "d%i" % (inputNote.octave) 
	elif inputNote.note == "d":
		noteBelow = "c%i" % (inputNote.octave)
		noteAbove = "e%i" % (inputNote.octave) 
	elif inputNote.note == "e":
		noteBelow = "d%i" % (inputNote.octave)
		noteAbove = "f%i" % (inputNote.octave) 
	elif inputNote.note == "f":
		noteBelow = "e%i" % (inputNote.octave)
		noteAbove = "g%i" % (inputNote.octave) 
	elif inputNote.note == "g":
		noteBelow = "f%i" % (inputNote.octave)
		noteAbove = "a%i" % (inputNote.octave) 
	elif inputNote.note == "a":
		noteBelow = "g%i" % (inputNote.octave)
		noteAbove = "b%i" % (inputNote.octave) 
	else:
		noteBelow = "a%i" % (inputNote.octave)
		noteAbove = "c%i" % (inputNote.octave + 1) 

	return [Note(noteBelow),Note(noteAbove)]
Exemple #3
0
    def build_randomly_from_scale(root,
                                  octave,
                                  scale_name="major",
                                  num_note_choices=None):
        """Create a MidiChord object based on a given scale.

        :param root: the root note of the scale
        :param octave: the octave to be used when creating the chord
        :param scale_name: the scale name to be used
        :param num_note_choices: a list of how integers representing the number of notes allowed to be chosen at random
            when constructing the chord randomly. None will default to [3, 4, 5].

        :return: a MidiChord
        """
        if num_note_choices is None:
            num_note_choices = [3, 4, 5]
        named_scale = scale.NAMED_SCALES[scale_name]
        my_scale = Scale(Note((root.upper(), octave)), named_scale)
        num_notes_in_scale = len(my_scale)
        scale_start_num = octave * num_notes_in_scale
        num_notes_in_chord = np.random.choice(num_note_choices)
        possible_notes = [
            my_scale.get(temp_note)
            for temp_note in range(scale_start_num, scale_start_num +
                                   num_notes_in_scale * 2)
        ]
        notes = np.random.choice(possible_notes,
                                 size=num_notes_in_chord,
                                 replace=False)
        chord = MidiChord([note.note + str(note.octave) for note in notes])
        chord.build_chord()
        return chord
Exemple #4
0
    def build_from_intervals(self,
                             root,
                             octave,
                             intervals,
                             scale_name="major"):
        """Given chord specs return a MidiChord object of said chord.

        usage:
            chord = ChordBuilder().build_from_intervals('c', 6, ["1", "3", "5", "b7", "#9"])

        :param root: string of the note.
        :param octave: an integer between 0 and 8 (or 9 or something)
        :param intervals: a list of note intervals relative to the root. Use 'b' for flat and '#' for sharp.
        :param scale_name: the scale from which to select notes

        :return: a Chord object
        """
        named_scale = scale.NAMED_SCALES[scale_name]
        my_scale = Scale(Note((root.upper(), octave)), named_scale)
        num_notes_in_scale = len(my_scale)
        # TODO: is this the correct way to calculate the scale_start_num?
        scale_start_num = octave * num_notes_in_scale
        intervals = [
            self._deal_with_pitch_accidentals(interval)
            for interval in intervals
        ]
        notes = [
            my_scale.get(scale_start_num + interval[0] - 1).transpose(
                interval[1]) for interval in intervals
        ]
        chord = MidiChord([note.note + str(note.octave) for note in notes])
        chord.build_chord()
        return chord
Exemple #5
0
def add_tuples_to_track(track, df):
    for row in df.iterrows():
        data = row[1]
        pitch = data["pitch"] if isinstance(
            data["pitch"], int) else Note.index_from_string(data["pitch"])
        track.append(data["event_type_fun"](tick=data["tick"],
                                            velocity=data["velocity"],
                                            pitch=pitch))
    return track
Exemple #6
0
    def get_list_of_chord_notes_from_chord(chord_notes):
        """Extract the string representations of a list of Note objects.

        :param chord_notes: a list of Note objects

        :return: a list of string representations of a list of Note objects.
        """
        return [
            Note.index_from_string(chord_note.note + str(chord_note.octave))
            for chord_note in chord_notes
        ]
Exemple #7
0
 def _create_melody_note_tuple(self, start_tick):
     velocity = random.randint(50, 90)
     cur_note = random.choice(self.available_notes)
     cur_note = Note.index_from_string(cur_note.note + str(cur_note.octave))
     note_length = random.choice(self.note_len_choices)
     # ["event_type_fun", "tick", "duration", "pitch", "velocity"]
     return [
         MidiEventStager(midi.NoteOnEvent, start_tick, note_length,
                         cur_note, velocity),
         MidiEventStager(midi.NoteOffEvent, start_tick + note_length,
                         note_length, cur_note, 0)
     ]
 def __init__(self, event):
     Thread.__init__(self)
     # Define "stop" trigger
     self.stopped = event
     # Define key
     self.key = Note('C3')
     # Define scale
     self.scale = Scale(self.key, 'harmonic minor')
     self.note = self.key
     self.chunks = []
     self.chunks.append(source.sawtooth(self.note, 0.5))
     self.data = numpy.concatenate(self.chunks)
     self.data = self.data * 0.5
Exemple #9
0
    def get_real_universe_dist(cls, U, V):
        zero_hit = (Chord([Note('c0')]), 0)
        if len(U) == 0:
            U = [zero_hit]
        if len(V) == 0:
            V = [zero_hit]

        # sum(dist(u,v) for all u,v)
        total_sum = 0
        for u in U:
            for v in V:
                total_sum += cls.get_real_pairwise_dist(u, v)

        normed_sum = total_sum / (len(U) * len(V))
        return normed_sum
Exemple #10
0
def generate_song(
    notes_per_chord,
    num_repeats,
    note_time=0.25,
    prog_intervals=(7, 2, -4j, 5)
):
    # generate a random major key
    root = Note(rand.choice(Note.NOTES))
    scale_notes = Scale(root, 'major')

    octave = 3
    progression = Chord.progression(
        Scale(
            root,
            [int(p.real + p.imag) for p in prog_intervals]
        ),
        octave
    )
    for i, z in enumerate(prog_intervals):
        if z.imag != 0:
            # TODO: cannot have a repeated chord be minor
            progression[i] = major_to_minor(progression[i])

    # generates a melody for the progression
    low_octave = 4
    prev_note = rand.choice(list(scale_notes)).at_octave(low_octave)
    melody = []
    for _ in range(notes_per_chord * len(progression) * num_repeats):
        note_dist = int(round(rand.gauss(0, 2)))
        prev_note = scale_notes.transpose(prev_note, note_dist)
        melody.append(prev_note)

    # build up the HLR from the melody progression
    song = []
    t = 0
    for i in range(num_repeats):
        for chord in progression:
            song.append(
                (t*note_time, chord, note_time*notes_per_chord)
            )
            t += notes_per_chord

    for i in range(len(melody)):
        note = melody[i]
        song.append((i*note_time, Chord([note]), note_time))

    return song
Exemple #11
0
    def __init__(self,
                 root_note=None,
                 octave=None,
                 scale_name=None,
                 melody_len=None,
                 quantization=None,
                 note_density=None,
                 note_len_choices=None):
        self.root_note = root_note
        self.octave = octave
        self.scale_name = scale_name
        self.melody_len = melody_len
        self.quantization = quantization  # this maybe should be at note level only
        self.note_density = note_density  # proportion of available ticks (determined by quantization) occupied by notes
        self.note_len_choices = note_len_choices

        self.root = Note((self.root_note, self.octave))
        self.named_scale = scale.NAMED_SCALES[self.scale_name]
        self.scale = Scale(self.root, self.named_scale)

        self.available_notes = [self.scale.get(x) for x in range(21, 30)]
        self.number_of_notes = self._compute_num_notes()
        self.start_ticks = self._get_start_ticks()
Exemple #12
0
import random

from musical.theory import Note, Scale
from musical.audio import effect, playback

from timeline import Hit, Timeline

# Define key and scale
key = Note('C3')
scale = Scale(key, 'Major')

time = 0  # Keep track of currect note placement time in seconds

timeline = Timeline()

note = key

for x in xrange(0, 11):

    if (x == 0):

        note = Note("C3")

    if (x == 1):

        note = random.choice([Note("D3"), Note("B2")])

    if (x == 2):
        if (note == Note("B2")):
            note = random.choice([Note("A2"), Note("C3")])
Exemple #13
0
import random

from musical.theory import Note, Scale
from musical.audio import effect, playback

from timeline import Hit, Timeline

timeline = Timeline()

bassProgression = [Note("C2"), Note("D2"), Note("E2"),Note("F2"),Note("G2"),Note("A2"),Note("B2"), Note("C3")]
chords = [[],
		  [Note("C3"),Note("E3"),Note("G3")],
		  [Note("D3"),Note("F3"),Note("A3")],
		  [Note("E3"),Note("G3"),Note("B3")],
		  [Note("F3"),Note("A3"),Note("C4")],
		  [Note("G3"),Note("B3"),Note("D4")],
		  [Note("A3"),Note("C4"),Note("E4")],
		  [Note("B3"),Note("D4"),Note("F4")],
		  [Note("C4"),Note("E4"),Note("G4")],
		  ]
bassNote = bassProgression


for x in range(0,8):
	
	timeline.add(x*.5,Hit(bassProgression[x],1))
	

time = 0.0

def getChord(inputNote):
Exemple #14
0
from musical.theory import Note, Scale, Chord
from musical.audio import playback

from timeline import Hit, Timeline

# Define key and scale
key = Note('D3')
scale = Scale(key, 'minor')

# Grab progression chords from scale starting at the octave of our key
progression = Chord.progression(scale, base_octave=key.octave)

time = 0.0  # Keep track of currect note placement time in seconds

timeline = Timeline()

# Add progression to timeline by arpeggiating chords from the progression
# for index in [0, 2, 3, 1,    0, 2, 3, 4,    5, 4, 0]:
#   chord = progression[index]
#   root, third, fifth = chord.notes
#   arpeggio = [root, third, fifth, third, root, third, fifth, third]
#   for i, interval in enumerate(arpeggio):
#     ts = float(i * 2) / len(arpeggio)
#     timeline.add(time + ts, Hit(interval, 1.0))
#   time += 2.0

# Strum out root chord to finish
note = Note('D3')
if note.note == "d":
    print(note)
Exemple #15
0
import numpy

from musical.theory import Note, Scale
from musical.audio import source, playback

# Define key and scale
key = Note('C4')
scale = Scale(key, 'major')

note = key
chunks = []
for i in xrange(len(scale)):
    third = scale.transpose(note, 2)
    chunks.append(source.sine(note, 0.5) + source.square(third, 0.5))
    note = scale.transpose(note, 1)
fifth = scale.transpose(key, 4)
chunks.append(source.sine(key, 1.5) + source.square(fifth, 1.5))

print "Rendering audio..."

data = numpy.concatenate(chunks)

# Reduce volume to 50%
data = data * 0.5

print "Playing audio..."

playback.play(data)

print "Done!"
Exemple #16
0
import random

from musical.theory import Note, Scale
from musical.audio import effect, playback

from timeline import Hit, Timeline

# Define key and scale
key = Note('C3')
scale = Scale(key, 'Major')

time = 0.0  # Keep track of currect note placement time in seconds

timeline = Timeline()

note = key

for x in xrange(0, 12):

    if note.index == "C3":
        note = random.choice(C3, D3)

    if note.index == "D3":
        note = random.choice(D3, E3, C3)

    if note.index == "E3":
        note = random.choice(E3, F3, D3)

    if note.index == "F3":
        note = random.choice(F3, G3, E3)
from musical.theory import Note, Scale, Chord

# generate a random major key
root = Note('c')
scale = Scale(root, 'major')

# generate a I-V-vi-IV progression
progression = Chord.progression(Scale(root, (7, 2, -4, -5)), 3)
for chord in progression:
    print chord
Exemple #18
0
'''
verseBase = Notes('A4')*5 + Notes('G4','F#4','G4')
verseMod = verseBase.replace('B4',3)\
                    .replace('E4',7)\
                    + [('F#4',1.0), ('-', 2.0)]
verseStart = verseBase.without(0) + verseBase.replace('B4',3) + verseBase + verseMod

verse2 = Notes('G4','G4','G4','F#4','E4','D4','E4',('F#4',1.0), ('-', 1.0))
verse3 = Notes('F#4','F#4','D4',('E4',1.0),('-',1.75))
verse = verseStart + verse2 + verse3
verses = (verse*2)%0.5

'''
    Verse Background
'''
base = Note('B3')
afterIntro1 = Notes(base, [base.third('minor'), base.fifth('minor')])
afterIntro2 = Notes([('A4',0.5),('A3',0.5)],'-')
base = Note('G3')
afterIntro3 = Notes(base, [base.third(), base.fifth()])
base = Note('A3')
afterIntro4 = Notes(base, [base.third(), base.fifth()])
afterIntro = afterIntro1*3 + afterIntro2 + afterIntro3*2 + afterIntro4*2\
                           + afterIntro1*4 + afterIntro3*2 + afterIntro4*2

verseBackground = intro + afterIntro + intro + afterIntro
verseBackground = verseBackground % 0.25

'''
    Chorus
'''
Exemple #19
0
textInput = input('please input some text: ')
print('textInput:', textInput)

# encode in a bytearray
textBytes = textInput.encode()
print('textBytes', textBytes)

# hash the text
textHash = hashlib.md5()
textHash.update(textBytes)
digest = textHash.digest()
print('digest:', digest)

# convert bytes to integers
integers = [n for n in digest]
print(integers)
for char in digest:
    print(char)

# play the notes
time = 0.0
timeline = Timeline()

for pitch in integers:
    print(pitch)
    timeline.add(time, Hit(Note(pitch % 32 + 24), 0.6))
    time += 0.6

data = timeline.render()

playback.play(data)
Exemple #20
0
 def get_note(self, root):
     note = Note.NOTES[root % len(Note.NOTES)]
     octave = root / len(Note.NOTES)
     return Note('%s%d' % (note, octave))
Exemple #21
0
from notes import Notes
from musical.theory import Note


base = Note('B3')
afterIntro1 = base.triad()
afterIntro1.play()
Exemple #22
0
from musical.theory import Note, Scale, Chord
from musical.audio import playback

from timeline import Hit, Timeline

# Define key and scale
key = Note('D3')
scale = Scale(key, 'minor')

# Grab progression chords from scale starting at the octave of our key
progression = Chord.progression(scale, base_octave=key.octave)

time = 0.0 # Keep track of currect note placement time in seconds

timeline = Timeline()

# Add progression to timeline by arpeggiating chords from the progression
for index in [0, 2, 3, 1,    0, 2, 3, 4,    5, 4, 0]:
    chord = progression[index]
    root, third, fifth = chord.notes
    arpeggio = [root, third, fifth, third, root, third, fifth, third]
    for i, interval in enumerate(arpeggio):
        ts = float(i * 2) / len(arpeggio)
        timeline.add(time + ts, Hit(interval, 1.0))
    time += 2.0

# Strum out root chord to finish
chord = progression[0]
timeline.add(time + 0.0, Hit(chord.notes[0], 4.0))
timeline.add(time + 0.1, Hit(chord.notes[1], 4.0))
timeline.add(time + 0.2, Hit(chord.notes[2], 4.0))
Exemple #23
0
from random_rhythm import *
from random_melody import *

# Set random seed + filepath from command line
random_seed = "0"
if len(argv) >= 2:
    random_seed = argv[1]
seed(random_seed)

filepath = "public/generated_songs/song_" + random_seed + ".wav"
if len(argv) > 2:
    filepath = argv[2]

# Define key and scale
random_note = choice(Note.NOTES)
key = Note(random_note + '3')
# scale = Scale(key, choice([l for l in list(NAMED_SCALES.values()) if len(l) == 7]))
scale = Scale(key, uniform(0, 1) > 0.3 and 'major' or 'minor')

# Grab key_chords chords from scale starting at the octave of our key
key_chords = Chord.progression(scale, base_octave=key.octave)

time = 0.0  # Keep track of currect note placement time in seconds
rhythm_mod = uniform(0.5, 1.5)  # lower number = faster tempo
print("rhythm_mod = " + str(rhythm_mod))

timeline = Timeline()


def render_melody(rhythm, melody):
    global time
Exemple #24
0
timeline = Timeline()
debug = False

bassArray = []

chordLetters = {
	"c" : ["c","e","g"],
	"d" : ["d","f","a"],
	"e" : ["e","g","b"],
	"f" : ["f","a","c"],
	"g" : ["g","b","d"],
	"a" : ["a","c","e"],
	"b" : ["b","d","f"]
}

key = Note("C3")
scale = Scale(key, 'major')


def returnChord(note):
	return([scale.transpose(note,2),scale.transpose(note,0)])

def nextNote(prevNote, bassNote):
	#if 'c' chordNotes is set to [Note("C3"),Note("E3"),Note("G3")]
	chordNotes = chordLetters[bassNote.note]
	print(chordNotes
		)
	possibleNext = []

	possibleNext.append(scale.transpose(prevNote,1))
	possibleNext.append(scale.transpose(prevNote,-1))
import random

from musical.theory import Note, Scale
from musical.audio import effect, playback

from timeline import Hit, Timeline

# Define key and scale
key = Note('E3')
scale = Scale(key, 'harmonic minor')

time = 0.0  # Keep track of currect note placement time in seconds

timeline = Timeline()

note = key

# Semi-randomly queue notes from the scale
for i in range(64):
    if note.index > 50 or note.index < 24:
        # If note goes out of comfort zone, randomly place back at base octave
        note = scale.get(random.randrange(4) * 2)
        note = note.at_octave(key.octave)
    else:
        # Transpose the note by some small random interval
        note = scale.transpose(note, random.choice((-2, -1, 1, 2)))
    length = random.choice((0.125, 0.125, 0.25))
    timeline.add(time, Hit(note, length + 0.125))
    time += length

# Resolve
Exemple #26
0
def main(argv):
  try:
    opts, args = getopt.getopt(argv, "hdsm", ['help', 'debug', 'startup', 'morning'])
  except getopt.GetoptError:
    usage()
    sys.exit(2)

  global _debug
  _debug = 0

  morning = False 

  for opt, arg in opts:
    if opt in ("-h", "--help"):
      usage()
      sys.exit()

    if opt in ("-m", "--morning"):
      morning = True
      _debug = 1

    if opt == '-d':
      _debug = 1

    if opt in ("-s", "--startup"):
      import time
      time.sleep(90)
      #os.system("/usr/bin/tvservice -o")


  # Increase chance of singing at sunrise/sunset
  import ephem

  birdcage = ephem.Observer()
  birdcage.lat = '51.497517'
  birdcage.lon = '0.080380'
  birdcage.date = str(datetime.datetime.now())
  birdcage.elevation = 5

  sun = ephem.Sun()

  next_sunrise = birdcage.next_rising(sun)
  early_next_sunrise = ephem.Date(next_sunrise - 15 * ephem.minute) 
  late_next_sunrise = ephem.Date(next_sunrise + 15 * ephem.minute) 

  next_sunset = birdcage.next_setting(sun)
  early_next_sunset = ephem.Date(next_sunset - 15 * ephem.minute) 
  late_next_sunset = ephem.Date(next_sunset + 15 * ephem.minute) 

  sunrise = False;
  sunset = False;
  if (birdcage.date > early_next_sunrise and birdcage.date < late_next_sunrise):
    #print 'Sunrise roll'
    sunrise = true;
    dice_roll = random.choice([1,2,3,4,5,6,7,8])
  elif (birdcage.date > early_next_sunset and birdcage.date < late_next_sunset):
    #print 'Sunset roll'
    sunset = true;
    dice_roll = random.choice([1,2,3,4,5,6,7,8])
  else:
    dice_roll = random.choice([1,2,3,4,5,6])

  if (dice_roll < 5 and _debug <> 1):
    #print "Going back to sleep"
    sys.exit()

  # We're alive, import what else we need now
  sys.path.append(os.path.join(os.path.dirname(__file__), 'python-musical'))

  from musical.theory import Note, Scale, Chord
  from musical.audio import effect, playback

  from timeline import Hit, Timeline

  # Define key and scale
  key = Note((random.choice(Note.NOTES), random.choice([2,3,3])))

  scales = ['major', 'minor', 'melodicminor', 'harmonicminor', 'pentatonicmajor', 'bluesmajor', 'pentatonicminor', 'bluesminor', 'augmented', 'diminished', 'wholehalf', 'halfwhole', 'augmentedfifth', 'japanese', 'oriental', 'ionian', 'phrygian', 'lydian', 'mixolydian', 'aeolian', 'locrian']
  random.shuffle(scales)
  scale = Scale(key, random.choice(scales))

  #print key
  #print scale

  # Grab progression chords from scale starting at the octave of our key
  progression = Chord.progression(scale, base_octave=key.octave)

  time = 0.0 # Keep track of correct note placement time in seconds

  timeline = Timeline()

  # Pick a notes from a chord randomly chosen from a list of notes in this progression
  chord = progression[ random.choice(range(len(progression)-1)) ]
  notes = chord.notes

  melodies = [ 
    [0.8, 0.2],
    [0.4, 0.2],
    [0.2, 0.8],
    [0.2, 0.4],
    [0.6, 0.2],
    [0.4, 0.4, 0.2],
    [0.6, 0.1, 0.1],
    [0.8, 0.1, 0.2],
    [0.2, 0.2, 0.2],
    [0.2, 0.4, 0.2],
    [1.0, 0.1, 0.2, 0.1, 0.2, 0.10, 0.1],
    [0.8, 0.4, 0.1, 0.2, 0.4, 0.1, 0.2],
    [0.8, 0.4, 0.4, 0.2, 0.2, 0.1, 0.1],
    [0.4, 0.0, 0.1, 0.1, 0.2, 0, 0.1, 0.4],
    [0.1, 0.1, 0.1, 0.0, 0.2, 0.0, 0.1, 0.2, 0.4],
    [0.8, 0.4, 0.1, 0.4, 0.2, 0.2, 0.1, 0.2, 0.8, 0.1, 0.4, 0.1],
    [0.2, 0.2, 0.4, 0.2, 0.1, 0.1, 0.0, 0.2],
    [1.0, 0.1, 0.2, 0.1, 0.2, 0.2],
    [0.2, 0.1, 0.2, 0.4, 0.1, 0.2, 0.4],
    [0.4, 0.1, 0.4, 0.2, 0.4, 0.1, 0.4, 0.2],
    [0.1, 0.1, 0.1, 0.2, 0.1, 0.1, 0.2],
    [0.1, 0.1, 0.1, 0.2, 0.1, 0.1, 0.1, 0.2, 0.0],
    [0.1, 0.0, 0.1, 0.0, 0.1, 0.0, 0.2, 0.0, 0.2, 0.0, 0.1, 0.1, 0.3],
  ]

  if sunrise or sunset:
    random_melody = random.choice(melodies[0:12])
  else:
    random_melody = random.choice(melodies)

  # Testing a new melody-generation idea - duncan 11/4/20
  # - needs more work, disabling for now - 12/4/20
  #random_melody = []
  #melody_length = random.randrange(1, 12)
  #
  #for i in range(0, melody_length):
  #  random_melody.append( round(random.uniform(0.1, 0.6), 1) )
  # test end

  if morning:
    random_melody = melodies[-1]

  print random_melody

  last_interval = 0.0
  last_transpose = 0

  for i, interval in enumerate(random_melody):
    random_note = random.choice(notes)

    # the first note should be high
    # identical intervals should often hold the same pitch
    # otherwise, pick a random pitch
    if i == 0:
      random_transpose = random.choice([8, 12])
    elif (last_interval == interval):
      if random.choice([0,1,2]) == 2:
        random_transpose = last_transpose
      else:
        random_transpose = 0
    else:
      random_transpose = random.choice([0,2,4,6,8,10,12])

    last_interval = interval
    last_transpose = random_transpose

    note = random_note.transpose(random_transpose)
    #print note

    # favour queued notes, but occasionally overlap them too
    if (random.choice([1,2,3,4,5,6]) > 2):
      time = time + interval
      timeline.add(time, Hit(note, interval))
    else:
      timeline.add(time, Hit(note, interval))
      time = time + interval

  #print "Rendering audio..."
  data = timeline.render()

  # Reduce volume to 50%
  data = data * 0.5

  print "Playing audio..."
  if morning:
    for i in range(2):
      playback.play(data)
  else:
    for i in range(random.choice([1,2])):
      playback.play(data)