###############################################################################
# SONG 1
# ======
#
# Our first song is a simple one. We find a room with some instruments, take a
# seat at the piano and start striking random notes with haphazard force on
# each quaver.
#
# ~~---<<<>>>---~~~<><><>~~~---<<<>>>---~~~<><><>~~~---<<<>>>---~~~<><><>~~~---

import os.path
import random

from bl.scheduler import clock
from bl.instrument.fsynth import Instrument


SF2DIR = os.path.join(os.path.dirname(__file__), 'sf2')


# First let's find an instrument to play with!
#
# What's in our sf2 directory ... hrm ... bass.sf2 ... piano.sf2 ... kit.sf2
# ...
#
# Note that in future songs we'll import some convenience functions defined in
# tutor.complib (piano_f, drums_f, bass_f) to create the instrument instances
# for us.

instrument = Instrument(os.path.join(SF2DIR, 'piano.sf2'))


def hitsomenote():


    # We have no clue what to do with this piano. Let's just
    # hit a note with some random amount of force.

    note = random.randint(36, 84)
    velocity = random.randint(40, 127)
    instrument.playnote(note, velocity)


    # And we'll take our finger off ... some time later

    release = random.choice((0.125, 0.25, 0.5, 1, 1.5))
    clock.callAfterMeasures(release, instrument.stopnote, note)


event = clock.schedule(hitsomenote)
event.startLater(1, 0.125)


# Now try this exercise from the shell.
#
# >>> event.stopLater(1) # Stop on the next measure
# >>> event.startLater(1, 0.0625) # restart, but this time every semiquaver

@@ -874,16 +874,324 @@
 f2'))%0A%0A%0A
+# Let's define some musical intervals in terms for virtual clock ticks%0A# Meter.divisionToTicks() API. Note that dtt() is a shorthand alias for%0A# divisionToTicks()%0A%0Ameter = clock.meter%0Aquaver = meter.dtt(1,8)%0Aquarter = meter.dtt(1,4)%0Ahalf = meter.dtt(1,2)%0Aone_and_half = meter.dtt(3,2)%0Ascale = range(36, 84)%0A%0A
 def hits
@@ -1338,22 +1338,20 @@
 dom.
-randint(36, 84
+choice(scale
 )%0A  
@@ -1485,17 +1485,16 @@
 e later%0A
-%0A
     rele
@@ -1518,32 +1518,43 @@
 ce((
-0.125, 0.25, 0.5, 1, 1.5
+quaver, quarter, half, one_and_half
 ))%0A 
@@ -1570,21 +1570,13 @@
 call
-Af
+La
 ter
-Measures
 (rel
@@ -1661,22 +1661,22 @@
 tart
-La
+Af
 ter(1, 
-0.125
+(1,8)
 )%0A%0A%0A
@@ -1769,16 +1769,16 @@
 measure%0A
-
 # %3E%3E%3E ev
@@ -1845,8 +1845,922 @@
 iquaver%0A
+%0A# Also try redfining scale to something less ... random.%0A# Here's another example to play with%0A%0Adef harmonize(steps):%0A    current = 0%0A    for step in steps:%0A        current += step%0A    return steps + %5B divmod(current, 12)%5B1%5D %5D%0A%0Arandom_steps = %5B%0A        random.choice(%5B2,2,3,4,4,4,4%5D), random.choice(%5B2,2,4,3,3,3,3%5D),%0A        random.choice(%5B3,4,2,2,2,2,2%5D), random.choice(%5B4,3,1,2,2,2,2%5D)%5D%0Arandom_steps = harmonize(random_steps)%0A%0Arandom_start = random.randint(36,48)%0A%0Adef use_scale(steps, start, repeat=2):%0A    global scale%0A    print 'using steps', steps%0A    print 'using start', start%0A    new_scale = %5Bstart%5D%0A    for _ in range(repeat):%0A        for step in steps:%0A            new_scale.append(new_scale%5B-1%5D + step)%0A    print 'new scale', new_scale%0A    scale = new_scale%0A%0A# Now call use_scale(random_steps, random_start)%0A#%0A# Then try playing some with your own values instead of random_steps%0A# and random_start.%0A%0A%0A

make song1 have more fun things to do - random harmonized scales