
import sys, os, re, random, math


scale = {
'C':0,
'D':2,
'E':4,
'F':5,
'G':7,
'A':9,
'B':11
}

C_major = [ ]
for i in xrange(-10,10):
    C_major.extend(i*12+j for j in [0,2,4,5,7,9,11])
F_major = [i+5 for i in C_major] 
G_major = [i+7 for i in C_major]

D_minor = F_major
D_major = [i+2 for i in C_major]

Bb_major = [ i+10 for i in C_major ]
G_minor = Bb_major

def whatis(note):
    value = scale[note[0].upper()]
    if note[0].islower(): value += 12
    for char in note[1:]:
        if char == '^':
            value += 1
        elif char == '_':
            value -= 1
        elif char == "'":
            value += 12
        elif char == ",":
            value -= 12
        else:
            assert False
    return value



def tune_equal():
    global Tuning
    print 'Equal tuning'
    Tuning = { }
    for i in xrange(12):
        Tuning[i] = 2.0**(i/12.0)

def tune_pythagorean():
    global Tuning
    print 'Pythagorean tuning'
    
    base = whatis('E_')%12
    Tuning = { }
    
    current = base
    current_fqc = 2.0**(base/12.0)
    for i in xrange(12):
        print current,
        Tuning[current] = current_fqc
        current += 7
        current_fqc *= 1.5
        if current >= 12:
            current -= 12
            current_fqc /= 2.0
    print

def tune_meantone():
    global Tuning
    print 'Meantone tuning - not sure this is right'
    
    base = whatis('E_')%12
    Tuning = { }
    
    current = base
    current_fqc = 2.0**(base/12.0)
    for i in xrange(12):
        print current,
        Tuning[current] = current_fqc
        current += 7
        current_fqc *= 5**0.25
        if current >= 12:
            current -= 12
            current_fqc /= 2.0
    print

def get_fqc(note):
    return 2.0**(note//12) * Tuning[note%12] * (261.625565/32) 


def remapper(scale, fixups = { }):
    fixup_values = { }
    for key in fixups:
        fixup_values[ whatis(key) ] = whatis(fixups[key])
    def remapper(value, steps):
        if value in fixup_values:
            value = fixup_values[value]
        if value not in scale:
            print 'blah:%d' % (value%12),
            return None
        new_value = scale[ scale.index(value) + steps ]
        diff = (value - new_value) % 12
        print diff,
        if diff in (1,6):
            print '(omit)',
            return None
        return new_value
    return remapper


def reset(tempo_mod = 1.0):
    global preamble, events, Tempo_mod
    preamble = """
    
    JCRev leftrev => dac.left;
    leftrev.mix(0.03);
    JCRev rightrev => dac.right;
    rightrev.mix(0.03);
    
    """
    events = [ ]
    Tempo_mod = tempo_mod

    #tune_equal()
    tune_pythagorean()
    #tune_meantone()

#(.5/180)::minute => dur T;

#Tempo = 60.0/2/170

def set_tempo(bpm):
    global Tempo
    Tempo = 60.0 / bpm / Tempo_mod


N = 0
def get_uid():
    global N
    N += 1
    return 'i%d' % N

def amble(string):
    global preamble
    preamble += string + '\n'

def linkin(name, pan):
    amble("""
        %(name)s => Pan2 %(name)s_pan;
        %(name)s_pan.pan(%(pan)f);
        %(name)s_pan.left => leftrev;
        %(name)s_pan.right => rightrev;
    """ % dict(name=name,pan=pan))

class Instrument:
    def __init__(self):
        pass
    
    def play_line(self, song, master_volume, transpose=0, expression=0, limit=None, limit_chars='{[()]}', remapper=lambda x,y:x):
        regex = r"([A-GZa-gz])(\^|_|)([',]*)([0-9]*)(/([0-9]*))?$"
        
        intensity = 0
        limit_intensity = 0
        volume = master_volume
        remap_parm = None
        t = 0.0
        line = [ ]
        for item in song.split():
            if item.startswith('shift:'):
                remap_parm = int(item[6:])
                continue
                
            if item.startswith('v*'):
                volume *= float(item[2:])
                continue

            if item.startswith('v/'):
                volume /= float(item[2:])
                continue
        
            if item in ('(','[','{'):
                intensity += 1
                if item in limit_chars: limit_intensity += 1
                continue
            if item in (')',']','}'):
                intensity -= 1
                if item in limit_chars: limit_intensity -= 1
                continue
        
            match = re.match(regex,item)
            assert match, 'Did not understand ' + item
            note = match.group(1)
            modifier = match.group(2)
            octave_modifier = match.group(3)
            t1 = match.group(4)
            has_t2 = match.group(5)
            t2 = match.group(6)
            if t1:
                t1 = int(t1)
            else:
                t1 = 1
            if not has_t2:
                t2 = 1
            elif not t2:
                t2 = 2
            else:
                t2 = int(t2)
            #print note,
            
            shift = 0 #48 + transpose #36
            if note.islower():
                shift += 12
                note = note.upper()
            
            for char in octave_modifier:
                if char == "'":
                    shift += 12
                else:
                    shift -= 12
            
            if modifier == '^': shift += 1
            if modifier == '_': shift -= 1
            
            #if intensity < 2:
            #if note != 'Z':
            #    self.play(Tempo*(t+expression*(0.5**intensity)),
            #              float(t1)/t2*Tempo, 
            #              scale[note]+shift, 0.5 ** intensity * master_volume)
            rexpression = expression * (random.random()+0.5)
            when = Tempo*(t+rexpression*(0.5**intensity))
            
            if limit is None or limit_intensity < limit:
                if note != 'Z':
                    remapped = remapper(scale[note]+shift, remap_parm)
                    if remapped is not None: remapped += transpose+48
                    line.append((when, remapped, 0.5 ** intensity * volume))
                else:
                    line.append((when, None))
            t += float(t1)/t2
        line.append((Tempo*t, None))
        for i in xrange(len(line)-1):
            if line[i][1] is not None:
                self.play(line[i][0],line[i+1][0]-line[i][0],line[i][1],line[i][2])
            

class Twanger(Instrument):
    def __init__(self, pan=0.0):
        self.uid = get_uid()
        #amble('StifKarp %(uid)s => JCRev %(uid)sr => Pan2 %(uid)sp => dac;' % dict(uid=self.uid))
        #amble('Mandolin %(uid)s => JCRev %(uid)sr => Pan2 %(uid)sp => dac;' % dict(uid=self.uid))
        amble('Mandolin %(uid)s;' % dict(uid=self.uid))
        linkin(self.uid, pan)
        #amble('%(pan)f => %(uid)sp.pan;' % dict(pan=pan,uid=self.uid))
        #amble('0.05 => %(uid)sr.mix;' % dict(uid=self.uid))
        #amble('0.975 => %s.baseLoopGain;' % self.uid)
        #amble('0.5 => %s.pickupPosition;' % self.uid)
        #amble('1.0 => %s.stretch;' % self.uid)
        #amble('0.5 => %s.stringDamping;' % self.uid)
        amble('0.6 => %s.stringDamping;' % self.uid)
        amble('0.8 => %s.pluckPos;' % self.uid)
        amble('0.5 => %s.bodySize;' % self.uid)
        
        amble('0.0 => %s.pluck;' % self.uid) #Mandolin plucks on startup :-(
        Instrument.__init__(self)
    
    def play(self, t, length, note, intensity):
        events.append((t,
            '%f => %s.freq;'
            '%f => %s.pluck;' % 
            (get_fqc(note), self.uid, intensity, self.uid)))


class Blown_base(Instrument):
    def __init__(self, power, power_bend=0.75, intensity_bend=0.5):
        self.power = power
        #amble("""
        #fun void blow_%(uid)s(float note, float intensity, dur length) {
        #    Std.mtof(note) => %(uid)s.freq;
        #    1.0 => %(uid)s.noteOn;
        #    for(0 => int i; i <= %(n)d; i++) {
        #        intensity*Math.pow(1.0-i*1.0/%(n)d,%(power)f) => %(uid)s.pressure;
        #        length/%(n)d => now;
        #    }
        #}
        #""" % dict(power=power,uid=self.uid,n=50))
        
        self.power = power
        self.power_bend = power_bend
        self.intensity_bend = intensity_bend

        self.attack = 0.04
        amble("""
        0.0 => float %(uid)stot;
        0.0 => float %(uid)sfqctot;
        
        fun void blow_%(uid)s(float fqc, float intensity, dur length, float power) {
            //fqc => %(uid)s.freq;
            1.0 => %(uid)s.noteOn;
            
            %(attack)f::second/length => float attack_proportion;
            for(0 => int i; i < %(n)d; i++) {
                //intensity *
                //Math.min(1.0,(length/%(attack)f::second)*i*1.0/%(n)d) *
                //Math.pow(1.0-i*1.0/%(n)d,power) => float extra;
                
                (i+0.5)*1.0/%(n)d => float pos;
                Math.min(pos / attack_proportion,
                         Math.pow((1.0-pos) / (1.0-attack_proportion),power)) *
                intensity => float extra;
                
                extra*extra => extra;
                
                %(uid)stot + extra => %(uid)stot;
                %(uid)sfqctot + extra*fqc => %(uid)sfqctot;
                %(uid)sfqctot / %(uid)stot => %(uid)s.freq;
                Math.pow(Math.max(0.0,Math.min(1.0, %(uid)stot)),0.5) => %(uid)s.pressure;
                
                length/%(n)d => now;
                
                %(uid)stot - extra => %(uid)stot;
                %(uid)sfqctot - extra*fqc => %(uid)sfqctot;
                Math.pow(Math.max(0.0,Math.min(1.0, %(uid)stot)),0.5) => %(uid)s.pressure;
            }
        }
        """ % dict(uid=self.uid,n=200,attack=self.attack))
    
    def play(self, t, length, note, intensity):
        if length < self.attack:
            print length, '->', self.attack
            length = self.attack
    
        this_power = self.power ** (intensity ** self.power_bend)
        
        intensity **= self.intensity_bend
        
        intensity = self.MIN_PRESSURE + intensity*(self.MAX_PRESSURE-self.MIN_PRESSURE)
        events.append((t-self.attack/2,
            'spork ~ blow_%(uid)s(%(fqc)f, %(intensity)f, %(length)f::second, %(power)f);'
            % dict(fqc=get_fqc(note), uid=self.uid,length=length+self.attack*0.25,intensity=intensity,power=this_power)))
#            % dict(fqc=get_fqc(note), uid=self.uid,length=length+self.attack/2*0,intensity=intensity,power=this_power)))
        #d = dict(uid=self.uid,note=note,length=length,intensity=intensity)
        #events.append((t, 
        #   'Std.mtof(%(note)d) => %(uid)s.freq;'
        #   #'%(uid)se.value(1.0);'
        #   #'%(uid)s.pressure(%(intensity)f);' 
        #   '%(uid)s.noteOn(1.0);' 
        #   #'%(length)f::second => %(uid)se.duration;'
        #   #'%(uid)se.target(0.5);'
        #   '%(uid)s.clear(1.0);'
        #   % d))
        ##events.append((t+0.01, '%(uid)se.keyOff(1);' % d))
        #n = 10
        #for i in xrange(n+1):
        #   f = float(n-i)/n
        #   d['p'] = intensity*(f**self.power)
        #   events.append((t+length*0.999*(1.0-f), '%(uid)s.pressure(%(p)f);' % d))

class Blower(Blown_base):
    MIN_PRESSURE = 0.51
    MAX_PRESSURE = 1.0

    def __init__(self, pan=0.0, gain=1.0, power=1.0/5):
        self.uid = get_uid()
        amble('Clarinet %(uid)s;' % dict(uid=self.uid))
        linkin(self.uid, pan)
        amble('%(gain)f => %(uid)s.gain;' % dict(gain=gain, uid=self.uid))
        #self.power = power
        Blown_base.__init__(self, power)

class Flute(Blown_base):
    MIN_PRESSURE = 0.51
    MAX_PRESSURE = 0.82
    
    def __init__(self, pan=0.0, gain=1.0, power=1.0/5):
        self.uid = get_uid()
        amble('Flute %(uid)s;' % dict(uid=self.uid))
        linkin(self.uid, pan)
        amble('%(gain)f => %(uid)s.gain;' % dict(gain=gain, uid=self.uid))
        #amble('%(uid)s.noteOn(1.0);' % dict(uid=self.uid))
        amble('%(uid)s.noiseGain(0.3);' % dict(uid=self.uid))
        #self.power = power
        Blown_base.__init__(self, power)

    #def play(self, t, length, note, intensity):        
    #    Blown_base.play(self, t-0.1,length,note,1.0)


class Poly_twanger(Instrument):
    def __init__(self, pos):
        self.twangers = { }
        self.pos = pos
        Instrument.__init__(self)

    def play(self, t, length, note, intensity):
        which = (note%12)//2 #Hmm
        if which not in self.twangers:
            self.twangers[which] = Twanger( self.pos+(which-3)/18.0 ) #(note-48.0) / 24.0 )
        self.twangers[which].play(t, length, note, intensity)
    
class Sample(Instrument):
    def __init__(self, samp_name, anticipation=0.0, pan=0.0, volume_adjust=1.0):
        self.uid = get_uid()
        self.anticipation = anticipation
        self.volume_adjust = volume_adjust
        amble('SndBuf %(uid)s;' % dict(uid=self.uid))
        linkin(self.uid, pan)
        
        amble('"%(name)s" => %(uid)s.read;' % dict(name=samp_name, uid=self.uid))
        amble('0.0 => %(uid)s.gain;' % dict(name=samp_name, uid=self.uid)) # Plays on load

    def play(self, t, length, note, intensity):
        events.append((t - self.anticipation,
            '%(intensity)f => %(uid)s.gain;'
            '0 => %(uid)s.pos;'
            % dict(intensity=intensity*self.volume_adjust,uid=self.uid)))

#class Snare(Sample):
#    def __init__(self, pan=0.0):
#        #Sample.__init__(self, 'snare-hop.wav', 0.005)
#        Sample.__init__(self, '/usr/share/hydrogen/data/drumkits/Millo_MultiLayered3/sd_04.wav', 0.005, pan, 4.0)

class Snare(Instrument):
    def __init__(self, pan=0.0):
        self.layers = [
            Sample('/usr/share/hydrogen/data/drumkits/Millo_MultiLayered3/sd_%02d.wav'%i, 0.005, pan, 1.5) for i in (1,2,3,4,5,6,8) ]

    def play(self, t, length, note, intensity):
        i = int( math.log(intensity)/math.log(2.0)*2 ) + 9
        #print i
        assert 0 <= i < len(self.layers), ' %d out of range ' % i
        self.layers[i].play(t,length,note,1.0)


def render():
    f = open('result.ck','wb')
    f.write(preamble)
    
    #print >> f, '2::second => now;'
    #return
    
    events.sort()
    now = 0.0
    for t, what in events:
        if t > now:
            print >> f, '%f::second => now;' % (t-now)
        now = t
        print >> f, what
    print >> f, '4::second => now;'
    f.close()

def save_it(filename):
    amble("""
        dac.left => WvOut waveleft => blackhole;
        dac.left.gain(0.5);
        "result-left.wav" => waveleft.wavFilename;
        dac.right => WvOut waveright => blackhole;
        dac.right.gain(0.5);
        "result-right.wav" => waveright.wavFilename;
    """)
    render()
    assert os.system('chuck.alsa -s result.ck') == 0
    assert os.system('sox -M result-left.wav result-right.wav result.wav') == 0
    assert os.system('lame --preset extreme result.wav %s.mp3' % filename) == 0
    assert os.system('cp result.wav %s.wav' % filename) == 0

def play_it():
    render()
    try:
        os.system('chuck.alsa result.ck') == 0
    except KeyboardInterrupt:
        sys.exit(0)

#song = (
#   '( ( G ( ( F ) E2 ) ( E F ) ) G2 ) ( G2 ) ( G2 ) '
#   '( c ( ( B ) A2 ) ( G A ) ) B2 ( ( c2 ) ( c2 ) ) '
#
#   '( ( G ( ( F ) E2 ) ( E F ) ) G2 ) ( G2 ) ( G2 ) '
#   '( c ( ( B ) A2 ) ( G A ) ) B2 ( ( c2 ) ) '
#)
#
#song = (
#   '( G ( F E2 ) E ( F G2 ) G2 ( G2 ) ) '
#   'c ( B A2 ) G ( A B2 ) c2 ( ( c2 ) ) '
#   '( G ( F E2 ) E ( F G2 ) G2 ( G2 ) ) '
#   'c ( B A2 ) G ( A B2 ) c2 '
#)

def galliard():
    set_tempo(170*2)

    intro = ' Z24 '
    A = """
        shift:4
        B_2 ( A2 G2 ) c3 ( ( B_ ) A2 ) 
        G2 ( F2 E2 ) F3 ( ( E ) D2 ) 
        B_2 ( A2 G2 ) c3 ( ( B_ ) A G ) 
        G4 ( F2 ) G5 z 
        """
    
    B = """
        shift:4
        G2 ( G2 G2 ) F ( ( G ) A ( B_ ) c2 ) 
        B_3 ( ( A ) A G/ A/ ) B_6 
        B_2 ( B_2 B_2 ) A ( ( B_ ) c ( B_ ) A G ) 
        G4 ( F2 ) G5 z 
        """
    
    null = ' Z48 '
    
    song = intro + null*2 + B*2 + A*2 + B*2 + A*2 + B*2 + A*2
    
    #song = intro + A*2 + B*2 + A*2 + B*2 + A*2 + B*2 + A*2
    inst = Blower(0.0, 0.25)
    inst.play_line(song, 1.0, 12, -0.1, 2)

    #song = intro + null*4 + A*2 + B*2 + A*2 + B*2 + A*2
    #song = intro + A*2 + B*2 + A*2 + B*2 + A*2 + B*2 + A*2
    #inst = Blower(-0.5, 0.0625, power=1.0/5)
    #inst.play_line(song, 0.5, 24, -0.1, limit=1)
    #inst = Blower(-0.25, 0.0625, power=1.0/5)
    #inst.play_line(song, 0.5, 24, -0.1, limit=1, remapper=remapper(F_major))
    #print

    song = intro + A*2 + B*2 + A*2 + B*2 + A*2 + B*2 + A*2
    inst = Poly_twanger(0.5)
    inst.play_line(song, 0.75, 0, -0.1)
    
    #inst = Sample('percussion/AMB_FTM2.wav', 0.006) #0.04)
    #inst = Sample('snare-hop.wav', 0.005)
    inst = Snare()
    inst.play_line(
                   'C2 ( C2 C2 ) C4 ( C2 ) ' * (1+8*7) +
                   'C2 ( C2 C2 ) C6 ',

                   1.0/10, 0, 0.0)


def milan():
    set_tempo(160*2)
    
    # last note is totally out of band
    A = """
                       ( F G ) 
        A2 ( ( G F ) G2 ( A B_ ) A2 G F ) 
        G2 ( ( A B_ ) A2 ( z2 ) G4 ) 
        F4 ( z2 G3 z )
    """
    B = """
                       ( G A ) 
        B_2 ( ( A G ) A2 ( B_ c ) B_2 A G ) 
        A2 ( ( B_ c ) B_2 ( z2 ) A4 ) 
        G4 ( z2 F3 z ) 
    """
    
    song = ' z32 z2 '+ A+B+A+B+A+B

    inst = Poly_twanger(0.5)
    inst.play_line(song, 0.75, 0, 0.0)

    inst = Blower(-0.25,0.2, power=1.0/4)
    inst.play_line(song, 1.0, 12, 0.0, limit=2)

    inst = Blower(-0.5,0.6, power=1.0/4)
    inst.play_line(song, 1.0, 24, 0.0)
    
    drum = ' C4 ( C4 C4 ) C4 ( C4 C4 ) C4 ( z2 ( C2 ) C2 C C ) ' # C12 C12 '
    drum_end = ' C4 ( C4 C4 ) C4 ( C4 C4 ) C4 '
#    inst = Sample('snare-hop.wav', 0.005)
    inst = Snare()
    inst.play_line(drum * (1+6-1) + drum_end,
                   1.0/7, 0, 0.0)


def turkelone():
    set_tempo(130)

    A = """
        F^3/4 [ ( ( F^/4 ) F^/ ) F^3/4 ] ( ( G/4 ) F^/ )
        G [ ( F^/ ) G ] ( A/ )
        B_ [ ( B_/ ) A3/4 ] ( ( B_/4 ) A/ )
        B_3/4 [ ( ( B_/4 ) B_/ ) B_/4 ] ( ( B_/4 ) A )
        G3/4 [ ( ( G/4 ) G/ ) F^3/4 ] ( ( G/4 ) F^/ )
        G3/4 [ ( ( G/4 ) G/ ) G/ ] ( G/ G/ ) 
    """

    B = """
        G3/4 [ ( ( G/4 ) G/ ) F^3/4 ] ( ( G/4 ) F^/ )
        G3/4 [ ( ( G/4 ) G/ ) F^ ] ( F^/ )
    """
    
    C = """
        G3/4 [ ( ( G/4 ) G/ ) A3/4 ] ( ( B_/4 ) A/ )
        B_3/4 [ ( ( B_/4 ) B_/ ) B_/ ] ( B_/ A/ )
        G3/4 [ ( ( G/4 ) G/ ) F3/4 ] ( ( E/4 ) F/ )
        G3/4 [ ( ( G/4 ) G/ ) G/ ] ( G/ G/ )
    """
    
    Dbody = """
        E3/4 [ ( ( E/4 ) E/ ) E/ ] ( E/ E/ )
        E3/4 [ ( ( E/4 ) E/ ) E ] ( E/ )
        F3/4 [ ( ( E/4 ) F/ ) E3/4 ] ( ( D/4 ) E/ )
    """
    
    Dend1 = """
        F^3/4 [ ( ( E/4 ) F^/4 G/4 ) F^/ ] ( F^/ F^/ )
    """
    Dend2 = """
        F^3/4 [ ( ( E/4 ) F^/4 G/4 ) F^/ ] ( F^/ F^/ )
        F^3
    """
    
    # x3/4 ( ( x/4 ) x/ )
    
    song = ' Z6 ' + A*2+B*2+C*2+Dbody+Dend1+A*2+B*2+C*2+Dbody+Dend2

    song = song.replace('[','(').replace(']',')')

    inst = Poly_twanger(0.5)
    inst.play_line(song, 0.75, 12, -0.05)
    
    #inst = Blower(-0.5, 0.25)
    #inst.play_line(song, 1.0, -12, 0.0, limit=1)

    #song = A*2+B*2+C*2+Dbody+Dend1+A*2+B*2+C*2+Dbody+Dend2
    #song = ' Z6 ' + A*2+B*2+C*2+Dbody+Dend1+A*2+B*2+C*2+Dbody+Dend2

    #song = song.replace('[','(').replace(']',')')

    inst = Blower(-0.25, 0.15, power=1.0/4)
    inst.play_line(song, 1.0, 12+5, -0.05)
    
    inst = Blower(-0.5, 0.2, power=1.0/4)
    inst.play_line(song, 1.0, 24, -0.05)

#    inst = Sample('snare-hop.wav', 0.005)
    inst = Snare()
    inst.play_line('C3/ ( C/ C/ C/ ) ' * (2+56) +
                   'C3',
                   1.0/5, 0, 0.0)

def earl():
#    set_tempo(200)
    set_tempo(220)
    
    A = """
        shift:4
        [ ( G )
        G3/ ] ( ( A/ ) B_ ) c3
        [ c3/ ] ( ( d/ ) e ) d2 ( c )
        [ B_3 ] B_2 [ ( G )
        
        G3/ ] ( ( A/ ) B_ ) c3/ [ ( ( d/ ) B_ )
        A2 ] ( G ) F3/ ( ( E/ ) F )
        [ G3 ] G2  
    """
    
    Bbody = """
        shift:3
        [ ( D )
        E3/ ] ( ( F/ ) G ) F3/ [ ( ( E/ ) F )
        G2 ] ( D ) E3/ [ ( ( F/ ) G )
        E3/ ] ( ( F/ ) E ) G2 [ ( D )
        
        E3/ ] ( ( F/ ) G ) F3/ [ ( ( E/ ) F )
        shift:4
        G ] ( d c ) B_3/ [ ( ( A/ ) G )
    """
    
    Bend1 = """
        F3/ ] ( ( E/ ) F ) G2    
    """

    Bend2 = """
        F3/ ] ( ( E/ ) F ) G6    
    """
    
    # x3/ ( ( x/ ) x )
    
    intro = ' Z6 Z5 '
    #intro = ' Z9 Z8 '
    song  = intro + (A*2 + Bbody + Bend1)*2 + A*2 + Bbody + Bend2
#    song2 = intro + (' Z36 ' + A + Bbody + Bend1)*2 + \
#                         A*2 + Bbody + Bend2
    #song = ' Z6 Z5 ' + Bbody + Bend2

    song = song.replace('[','(').replace(']',')')
#    song2 = song2.replace('[','(').replace(']',')')
#    song = song.replace('[','').replace(']','')

    inst = Poly_twanger(0.5)
    inst.play_line(song, 1.0, 0, -0.05, limit=2+2)

    inst = Blower(-0.25, 0.1, power=1.0/4)
    inst.play_line(song, 1.0, 12, -0.05, limit=2)

    #inst = Poly_twanger()
    inst = Blower(0.0, 0.1, power=1.0/4)
    #inst.play_line(song, 1.0, 12, -0.05, limit=1)
    inst.play_line(song, 1.0, 12, -0.05, limit=1+1,
        remapper=remapper(F_major))
    print
    
    inst = Flute(-0.5, 0.3, power=1.0/4)
    inst.play_line(song, 1.0, 24, -0.05)
    inst = Flute(-0.35, 0.3, power=1.0/4)
    inst.play_line(song, 1.0, 36, -0.05)

    drum = ' ( C2 ) ( C ) C3 '
    drumend = ' ( C3 ) C3 '    
#    inst = Sample('snare-hop.wav', 0.005)
    inst = Snare()
    inst.play_line(drum*(2+18+18+18-1)+drumend,
                   1.0/5, 0, 0.0)

#    drum = ' ( C ( C C ) C3 ) C3 '
#    inst = Sample('snare-hop.wav', 0.005)
#    inst.play_line(drum*(2+12+12+12),
#                   1.0/5, 0, 0.0)

def old():
    set_tempo(160)
    
    A = """
        [ G ] ( A ) B_ [ ( G )
        A3/ ] ( G/ ) F/ [ ( ( E/ ) F/ D/ )
        E_/ ] ( ( F/ ) G ) G [ ( F^ )
        G2 ] G2
    """
    
    Bbody = """
        [ d ] ( c ) B_ [ ( A )
        B_ ] ( A/ G/ ) F [ ( G/ A/ )
        B_ ] ( c ) d2
        [ c2 ] A2 
        [ B_2 ] G2
        [ A2 ] F2
        [ E_ ] ( G ) G [ ( F^ ) ]
    """

    Bend1 = " [ G2 ] G2 "
    #Bend2 = " G4 "
    
    song = ' Z8 ' + (A*2+Bbody+Bend1)*2+A*2+Bbody+Bend1

    inst = Poly_twanger(0.5)
    inst.play_line(song, 1.0, 0, -0.05)

    #inst = Poly_twanger()
    #inst.play_line(song, 0.5, 0, -0.05)

    song2 = ' Z8 ' + ' Z32 ' + ' Z32 ' +A*2+Bbody+Bend1+ A*2+Bbody+Bend1

    inst = Blower(-0.5, 0.2, power=1.0/4)
    inst.play_line(song2, 1.0, 24, -0.05, limit=2, limit_chars='[()]')

    inst = Blower(-0.25, 0.3, power=1.0/3)
    inst.play_line(song, 1.0, 12, -0.05)

    drum = " [ C ] ( C ) C2 "
    #drumend = "C4"

#    inst = Sample('snare-hop.wav', 0.005)
    inst = Snare()
    inst.play_line(drum*(2+16*3), #-1) + drumend,
                   1.0/10, 0, 0.0)


def new():
    set_tempo(180)

    song = """
        c2 [ c ] ( B )
        c5/ z/ ( B )
        A [ ( G ) G ] ( F^ )
        G5/ z/ ( G )
        c/ [ ( ( B/ ) A/ G/ ) A/ ] ( ( B/ ) c/ A/ )
        B [ ( A/ B/ ) c/ ] ( ( B/ ) A/ G/ )
        A/ [ ( ( G/ ) F^/ E/ ) F^/ ] ( ( E/ ) F^ )
        G2 z ( A/ B/ )
        
        c [ ( A ) G ] ( E/ F/ )
        G5/ z/ ( G )
        F/ [ ( ( E/ ) F/ G/ ) A ] ( E/ F/ )
        G5/ z/ ( A/ B/ )
        c [ ( A ) G ] ( E/ F/ )
        G5/ z/ ( F )
        E/ [ ( ( D/ ) C ) C ] ( B, )
        C5/ z/ { ( A/ B/ )
        
        c } [ ( A ) G ] ( E/ F/ )
        G5/ z/ ( G )
        F/ [ ( ( E/ ) F/ G/ ) A ] ( E/ F/ )
        G5/ z/ ( A/ B/ )
        c [ ( A ) G ] ( E/ F/ )
        G5/ z/ ( F )
        e/ [ ( ( d/ ) c ) B/ ] ( ( c/ ) d/ B/ )
        c4
         
    """
    
    song = ' z8 ' + song*3

    inst = Poly_twanger(0.5) 
    #inst = Twanger(0.5)
    inst.play_line(song, 0.75, 0, -0.05, limit=2, limit_chars='[()]')

    inst = Blower(-0.25, 0.1, power=1.0/3)
    inst.play_line(song, 1.0, 12, -0.05, limit=1, limit_chars='[()]')

    #inst = Blower(-0.35, 0.15, power=1.0/3)
    #inst.play_line('shift:2 '+song, 1.0, 12, -0.05, limit=1, 
    #     remapper=remapper(C_major, {'F^':'A', 'B':'e'}))
    #print
    inst = Blower(-0.35, 0.1, power=1.0/3)
    inst.play_line('shift:4 '+song, 1.0, 12, -0.05, limit=1, 
         remapper=remapper(C_major, {'F^':'A', 'B':'e'}))
    print

    inst = Blower(-0.5, 0.5, power=1.0/4)
    inst.play_line(song, 1.0, 24, 0.05)

    drum = " C2 ( C C ) "
    drumend = "C4"

#    inst = Sample('snare-hop.wav', 0.005)
    inst = Snare()
    inst.play_line(drum*(2+24*3-1) + drumend,
                   1.0/10, 0, 0.0)


def sosilia():
    set_tempo(180)

    A = """
        B { [ ( d ) c ] ( B ) 
        A2 } [ A ] ( G/ A/ )
        B { [ ( d ) c3/ ] ( B/ )
        A } [ ( B ) A ] ( G )
        G { ( F^ ) G2 }
    """

    A_wrong = """
        [ B ] ( d ) c { [ ( B ) 
        A2 ] A } [ ( G/ A/ )
        B ] ( d ) c3/ { [ ( B/ )
        A ] ( B ) A } [ ( G )
        G ] ( F^ ) G2
    """
    
    B = """
        { [ B ] ( A ) G } [ ( A/ B/ )
        c ] ( B ) A { [ ( A )
        e ] ( d ) c } [ ( d )
        d ] ( c^ ) d2
    """
    
    C = """
        { [ d3/ ] ( c/ ) B } [ ( d )
        c/ ] ( ( B/ ) c/ d/ ) c { [ ( B )
        A ] ( G ) G } [ ( F^ )
        G2 ] G2
    """
    
    song = ' Z8 ' + (2*A+2*B+C+2*B+C)*3

    inst = Poly_twanger(0.5)
    inst.play_line(song, 0.75, 0, 0.0)

    stripped = song
    for char in '{}': stripped = stripped.replace(char,'')

    #inst = Blower(0.5, 0.05, power=1.0/3)
    #inst.play_line(stripped, 1.0, 0, -0.0, limit=1, limit_chars='()')

    inst = Blower(0.25, 0.1, power=1.0/5)
    inst.play_line(stripped, 1.0, 12, -0.0, limit=2, limit_chars='{[()]}')

    inst = Blower(-0.25, 0.1, power=1.0/5)
    inst.play_line(song, 1.0, 24, -0.0, limit=2, limit_chars='[()]')
    
    inst = Flute(-0.5, 0.2, power=1.0/5)
    inst.play_line(song, 1.0, 36, -0.05)

#    inst = Flute(0.25, 0.4, power=1.0/4)
#    inst.play_line(song, 1.0, 36, -0.05)

    drumA = ' C2 ( C C ) '
    drum = ' ( C C ) C2 '
    #drumend = ' C4 '

#    inst = Sample('snare-hop.wav', 0.005)
    inst = Snare()
    inst.play_line(drumA*2+(drumA*9+drum+drum*24)*3,
                   1.0/10, 0, 0.0)



def quadran():
    A1_wrong = """
        ( G/ A/ ) 
        B3/ { [ ( A/ ) G ] ( e )
        d } [ ( c ) B ] ( A ) 
        B3/ { [ ( A/ ) G3/ ] ( G/ )
        A/ } [ ( ( B/ ) c ) c ] ( B )
        c2 { [ G ] ( c )
        c } [ ( B/ A/ ) c ] ( B )
        c3/ { [ ( d/ ) c ] ( B )
        A/ } [ ( ( G/ ) A/ B/ ) c/ ] ( ( A/ ) d/ c/ )
        
        B3/ { [ ( A/ ) G ] ( d )
        d } [ ( B/ c/ ) d/ ] ( ( c/ ) B/ A/ )
        B3/ { [ ( A/ ) G ] ( A/ B/ )
        c } [ ( B ) A ] ( G )
        F^3/ { [ ( E/ ) D ] ( A )
        A } [ ( G ) F^ ] ( E )
        F^2 { [ F^2 ]
        E } [ ( D ) G ] ( A )
    """

    
    A2_wrong = """
        B3/ { [ ( A/ ) G ] ( e )
        d } [ ( c ) B ] ( A )
        B3/ { [ ( A/ ) G3/ ] ( G/ )
        A/ } [ ( ( B/ ) c ) c ] ( B )
        c2 { [ G ] ( c )
        c } [ ( B/ A/ ) c ] ( B )
        c3/ { [ ( d/ ) c ] ( B )
        A/ } [ ( ( G/ ) A/ B/ ) c/ ] ( ( A/ ) d/ c/ )
        
        B { [ ( A/ B/ ) c ] ( B )
        A } [ ( G ) F^ ] ( E )
        F^ { [ E ] ( G2 )
        G  } [ ( F^/ E/ ) F^/ ] ( ( G/ ) E/ F^/ )
        G2 { [ d2 ]
        c3/ } [ ( B/ ) A/ ] ( ( B/ ) c/ d/ )
        B2 { [ B ] ( B ) 
        B2 } [ A ] ( G )
    """
    
    B_wrong = """
        F^3/ { [ ( E/ ) D ] ( A )
        A } [ ( G ) F^ ] ( E )
        F^2 { [ F^ ] ( G/ F^/ )
        E } [ ( D ) E ] ( E )
        F^3/ { [ ( E/ ) D ] ( B )
        A } [ ( G ) F^ ] ( E )
        F^ { [ ( D ) G ] ( A )
        B } [ ( G ) A ] ( B )
        
        c3/ { [ ( d/ ) c ] ( A )
        G } [ ( F^ ) E ] ( F^/ D/ )
        G2 { [ G ] ( F^/ E/ )
        F^/ } [ ( ( G/ ) E/  F^/ ) G2 ]
        d2 { [ c3/ ] ( B/ )
        A/ } [ ( ( B/ ) c/ d/ ) B2 ]
    """
    
    # Repair: mimic end of A somewhat
    Bend1_wrong = """
        B2 { [ B ] ( B )
        B2 } [ A ] ( G )
    """
    
    Bend2_wrong = """
        B2 { [ B ] ( B )
        B2 } [ B ]
    """

    Bend3_wrong = """
        B8
    """



    A1 = """
        [ ( G/ A/ ) 
        B3/ ] ( A/ ) G { [ ( e )
        d ] ( c ) B } [ ( A ) 
        B3/ ] ( A/ ) G3/ { [ ( G/ )
        A/ ] ( ( B/ ) c ) c } [ ( B )
        c2 ] G { [ ( c )
        c ] ( B/ A/ ) c } [ ( B )
        c3/ ] ( d/ ) c { [ ( B )
        A/ ] ( ( G/ ) A/ B/ ) c/ } [ ( ( A/ ) d/ c/ )
        
        B3/ ] ( A/ ) G { [ ( d )
        d ] ( B/ c/ ) d/ } [ ( ( c/ ) B/ A/ )
        B3/ ] ( A/ ) G { [ ( A/ B/ )
        c ] ( B ) A } [ ( G )
        F^3/ ] ( E/ ) D { [ ( A )
        A ] ( G ) F^ } [ ( E )
        F^2 ] F^2
        { [ E ] ( D ) G } [ ( A ) ]
    """

    A2 = """
        [ B3/ ] ( A/ ) G { [ ( e )
        d ] ( c ) B } [ ( A )
        B3/ ] ( A/ ) G3/ { [ ( G/ )
        A/ ] ( ( B/ ) c ) c } [ ( B )
        c2 ] G { [ ( c )
        c ] ( B/ A/ ) c } [ ( B )
        c3/ ] ( d/ ) c { [ ( B )
        A/ ] ( ( G/ ) A/ B/ ) c/ } [ ( ( A/ ) d/ c/ )
        
        B ] ( A/ B/ ) c { [ ( B )
        A ] ( G ) F^ } [ ( E )
        F^ ] ( E ) G2
        { [ G ] ( F^/ E/ ) F^/ } [ ( ( G/ ) E/ F^/ )
        G2 ] d2 
        { [ c3/ ] ( B/ ) A/ } [ ( ( B/ ) c/ d/ )
        B2 ] B { [ ( B ) 
        B2 ] A } [ ( G ) ]
    """

    B = """
        [ F^3/ ] ( E/ ) D { [ ( A )
        A ] ( G ) F^ } [ ( E )
        F^2 ] F^ { [ ( G/ F^/ )
        E ] ( D ) E } [ ( E )
        F^3/ ] ( E/ ) D { [ ( B )
        A ] ( G ) F^ } [ ( E )
        F^ ] ( D ) G { [ ( A )
        B ] ( G ) A } [ ( B )
        
        c3/ ] ( d/ ) c { [ ( A )
        G ] ( F^ ) E } [ ( F^/ D/ )
        G2 ] G { [ ( F^/ E/ )
        F^/ ] ( ( G/ ) E/  F^/ ) G2 }
        [ d2 ] c3/ { [ ( B/ )
        A/ ] ( ( B/ ) c/ d/ ) B2 }
    """
    
    B_bridge = """
        [ B ] ( B ) B2
        { B2 A } [ ( G ) ]
    """
    
    B_end = """
        [ B ] ( B ) B8
    """
    
    #Alt repair: B2 [ B ] ( B )
    
    #song = ' Z7 ' + (A1+A2+B+Bend1+B+Bend2)+(A1+A2+B+Bend1+B+Bend3)
   # song = ' Z7 ' + (A1+A2+B+Bend1+B+Bend3)

    song = ' Z7 ' + (A1+A2+B+B_bridge+B+B_end)

    #meh missing bar somewhere?
    #song2 = ' Z8 ' + (' Z65 '+A2+B+Bend2 + ' Z64 ') + \
    #                 (A1+' Z64 '+' Z64 '+B+Bend2) 

    set_tempo(210)

    inst = Poly_twanger(0.5)
    inst.play_line(song, 0.75, 0, -0.05) #, limit=3)

    inst = Blower(-0.0, 0.15, power=1.0/3)
    inst.play_line(song, 1.0, 12, -0.05, limit=2, limit_chars='{[()]}')

    inst = Blower(-0.25, 0.15, power=1.0/3)
    inst.play_line(song, 1.0, 24, -0.05, limit=2, limit_chars='[()]')

    inst = Flute(-0.5, 0.3, power=1.0/6)
    inst.play_line(song, 1.0, 36, -0.05)
    
    #drumintro = ' C2 [ C2 ] C [ ( C ) C2 ] ' 
    #drum = ' C2 [ C2 ] C2 [ C ] ( C ) '
    #drumend = ' C8 '
    #inst = Snare()
    #inst.play_line(drum * (1+32-1) + drumend,
    #               1.0/7, 0, 0.0)
    drum = ' ( C2 ) C2 '
    inst = Snare()
    inst.play_line(drum * (1+32)*2,
                   1.0/7, 0, 0.0)


def garden():
    set_tempo(165)

    A = """
        shift:4
        c2 c ( c )
        A3/ ( B_/ ) c ( c )
        d ( c ) B_ ( A )
        G3 ( A )
        B_3/ ( c/ ) d/ ( ( e/ ) f )
        F3/ ( G/ ) A/ ( ( B_/ ) c )
        B_ ( A ) G/ ( ( F/ ) G/ A/ )
        F4
    """

    B = """
        shift:4
        c ( c/ c/ ) c ( c )
        d ( e ) f2
        A ( A/ A/ ) A ( F )
        G ( A ) B_2
        A3/ ( G/ ) F/ ( ( G/ ) A )
        B_3/ ( A/ ) G/ ( ( A/ ) B_ )
        c3/ ( B_/ ) A/ ( ( B_/ ) c )
        d3/ ( c/ ) B_/ ( ( c/ ) A/ B_/ )
        G ( F ) F ( E )
        F4
    """

    song = ' Z8 ' + (A*2+B*2)*3

    song2 = ' Z8 ' + (' Z32 ' + A + ' Z40 ' + B)*2 + A*2 + B*2

    inst = Poly_twanger(0.5)
    inst.play_line(song, 1.0, 0, -0.03, limit=3)

    inst = Blower(-0.25, 0.1, power=1.0/4)
    inst.play_line(song2, 1.0, 12, -0.03, limit=1)

    inst = Blower(-0.5, 0.1, power=1.0/4)
    inst.play_line(song2, 1.0, 24, -0.03, limit=1,
        remapper=remapper(F_major))
    print

    inst = Flute(0.0, 0.15, power=1.0/4)
    inst.play_line(song, 1.0, 24, -0.03)

    inst = Flute(0.25, 0.15, power=1.0/4)
    inst.play_line(song2, 1.0, 36, -0.03)

    drum = " C2 ( C C ) C2 ( C C ) "
    drumend = " C2 ( C C ) C4 "

#    inst = Sample('snare-hop.wav', 0.005)
    inst = Snare()
    inst.play_line(drum*(1+18*3-1)+drumend,
                   1.0/10, 0, 0.0)



def spanish():
    set_tempo(150 * 2)
    
    song = """
        shift:4
        d4 c3 shift:3 ( A ) 
        shift:3
        B2 ( c2 ) d3 shift:4 ( e )
        shift:4
        d ( ( B ) c d ) e4
        shift:3
        e2 ( e2 ) e3 shift:4 ( g )
        shift:4
        f2 ( e2 ) d3 shift:3 ( c )
        shift:3
        d ( ( f ) e d ) c2 ( d2 )
        shift:3
        B2 ( c2 ) d3 shift:3 ( c )
        shift:3
        B ( ( c ) d e ) d4
    """
    
    song1 = ' Z16 ' + ( song + ' Z64 ' + song*2 )*2 + ' d8 '
    song2 = ' Z16 ' + ( ' Z64 ' + song + song*2 )*2 + ' d8 '
    song12 = ' Z16 ' + ( song*4 )*2 + ' d8 '

    inst = Poly_twanger(0.5)
    inst.play_line(song12, 0.5, 0, -0.1)

    inst = Blower(-0.1, 0.2, power=1.0/3)
    inst.play_line(song2, 1.0, 0, -0.1, limit=2,
        remapper=remapper(C_major))
    print

    inst = Blower(-0.2, 0.2, power=1.0/3)
    inst.play_line(song1, 1.0, 12, -0.1, limit=2)

    inst = Blower(-0.3, 0.2, power=1.0/3)
    inst.play_line(song2, 1.0, 12, -0.1, limit=2,
        remapper=remapper(C_major))
    print

    inst = Blower(-0.4, 0.2, power=1.0/3)
    inst.play_line(song1, 1.0, 24, -0.1, limit=2)

    drum = " C ( ( C ) C2 ) C4 "
    drumend = " C8 "

#    inst = Sample('snare-hop.wav', 0.005)
    inst = Snare()
    inst.play_line(drum*(2+8*8)+drumend,
                   1.0/7, 0, 0.0)


def black():
    A = """
        shift:4
        [ ( D ) ]
        [ D3/ ] ( ( E/ ) F ) G3/ [ ( ( A/ ) G ) ]
        [ F3/ ] ( ( E/ ) F ) G2 [ ( A ) ]
        [ B_3/ ] ( ( A/ ) G ) B_3/ [ ( ( c/ ) d ) ]
        [ A3 ] A2
    """
    
    B = """
        [ ( d ) ]
        [ c3/ ] ( ( B_/ ) A ) B_3/ [ ( ( c/ ) d ) ]
        [ A ] ( A A ) A2 [ ( d ) ]
        [ c3/ ] ( ( B_/ ) A ) B_3/ [ ( ( c/ ) d ) ]
    """
    Bend1 = """
        [ A3 ] A2
    """
    Bend2 = """
        [ A3 ] A3
    """
    
    C = """
        [ d2 ] ( e ) f3/ [ ( ( e/ ) d ) ]
        [ c3/ ] ( ( B_/ ) c ) d2 [ ( A ) ]
        [ d ] ( a g ) f^3/ [ ( ( e/ ) d ) ]
        [ c^3/ ] ( ( B_/ ) c^ ) d3
    """
    
    D = """
        [ d2 ] ( e ) f3/ [ ( ( e/ ) d ) ]
        [ c ] ( d B_ ) A2 [ ( G ) ]
        [ B_ ] ( A G ) B_ [ ( A G ) ]
    """
    Dend1 = """
        [ c ] ( A2 ) G3
    """
    Dend2 = """
        [ c ] ( A2 ) G2
    """
    
    E = """
        [ ( A ) ]
        [ B_ ] ( A G ) B_ [ ( A G ) ]
    """
    Eend1 = """
        [ c ] ( A2 ) G2 
    """
    Eend2 = """
        [ c ] ( A2 ) G3 
    """
    
    song = ' Z11 ' + \
           ( A*2 + B+Bend1+B+Bend2 + C*2 + D+Dend1+D+Dend2 + E+Eend1+E+Eend1 )*2 + \
             A*2 + B+Bend1+B+Bend2 + C*2 + D+Dend1+D+Dend2 + E+Eend1+E+Eend2

    song = song.replace('[','(').replace(']',')')

    #song = '( '+song.replace('[',')').replace(']','(')+' )'

    #song = ' shift:4 ' + C

    set_tempo(240)
    #tune_equal()
    
    exp = -0.05

    inst = Poly_twanger(0.5)
    inst.play_line(song, 1.0, 0, exp, limit=2+1)

    inst = Blower(-0.5, 0.2, power=1.0/3)
    inst.play_line(song, 1.0, 12, exp, limit=1+1)

    inst = Blower(0.0, 0.3, power=1.0/4)
    inst.play_line(song, 1.0, 24, exp)


    drum = " ( C2 ) ( C ) C3 "
    #drum = " C3 ( C ) ( C C ) "

#    inst = Sample('snare-hop.wav', 0.005)
    inst = Snare()
    inst.play_line(drum*(2+36*3),
                   1.0/7, 0, 0.0)

    
    # blackalmanify gresley music!


def tinternell():
    # Odd bars emphasized
    
    A_wrong = """
        { ( E_ )
        D3/ } [ ( F/ )
        E_/ ] ( ( D/ ) E_ )
        F3/ { [ ( E_/ )
        D ] ( C )
        B, } [ ( C )
        C/ ] ( ( B,/4 A,/4 ) C/ B,/ )
        C2 { [
        C ] }
    """
    
    B_wrong = """
        { ( B_,/ C/ )
        D } [ ( D )
        C/ ] ( ( D/ ) E_/ F/ )
        G2 { [
        G ] }
    """
    
    C_wrong = """
        { ( E_ )
        D3/ } [ ( C/ )
        D ] ( E_ )
        F3/ { [ ( E_/ )
        D ] ( C )
        D } [ ( C )
        D ] ( D )
    """
    
    Cend1_wrong = """
        C2
        { [ C ] }
    """

    Cend2_wrong = """
        C4
    """
    
    vdown = ' v*0.75 '
    vup = ' v/0.75 '

    A = """
        { [ ( E_ )
        D3/ ] ( F/ )
        E_/ } [ ( ( D/ ) E_ )
        F3/ ] ( E_/ )
        D { [ ( C )
        B, ] ( C )
        C/ } [ ( ( B,/4 A,/4 ) C/ B,/ )
        C2 ]
        C
    """

    B = """
        { [ ( B_,/ C/ )
        D ] ( D )
        C/ } [ ( ( D/ ) E_/ F/ )
        G2 ]
        G 
    """
    
    C = """
        { [ ( E_ )
        D3/ ] ( C/ )
        D } [ ( E_ )
        F3/ ] ( E_/ )
        D { [ ( C )
        D ] ( C )
        D } [ ( D ) ]
    """
    
    Cend1 = """
        [ C2 ]
        C
    """

    Cend2 = """
        [ C2 ]
        C2
    """
 
    song = ' Z7 ' + A+B*2+C+Cend1+A+vdown+A+vup+A+B*2+C+Cend1+A+B*2+C+Cend2
    #song2 = ' Z7 ' + ' Z16 '+B*2+C+Cend+A*3+B*2+C+Cend+A+B*2+C

    set_tempo(150)

    #inst = Poly_twanger(0.5)
    #inst.play_line(song, 0.75, 12, -0.05, limit=2)

    inst = Blower(-0.25, 0.5, power=1.0/4)
    inst.play_line(song, 1.0, 24, -0.1, limit_chars='{[()]}')

    #drum = ' C2 ( C C ) '
    #drumend = ' C4 '
    #inst = Snare()
    #inst.play_line(drum * (2+ 4+4+4 +12+4+4 +4+4+4 -1) + drumend,
    #               1.0/7, 0, 0.0)

    drum = ' ( C2 ) C ( ( C ) ) '
    drumend = ' ( C2 ) C2 '
    inst = Snare()
    inst.play_line(drum * (2+ 4+4+4 +12+4+4 +4+4+4 -1) + drumend,
                   1.0/7, 0, 0.0)
    
def lorayne():
    A = """
        { ( G3/ A/ ) B/ } [ ( ( A/ ) B/ c/ )
        d2 ] d { [ ( c/ B/ )
        A ] ( B ) c } [ ( d )
        B2 ] G2
    """
    
    B = """
        { ( G3/ A/ ) B } [ ( A/ G/ )
        A2 ] A2
        { ( G3/ A/ ) B } [ ( A/ G/ )
        A2 ] A2
        { ( G3/ A/ ) B/ } [ ( ( A/ ) B/ c/ )
        d2 ] d3/ { [ ( c/ )
        B ] ( A/ G/ ) F^/ } [ ( ( E/ ) G/ F^/ )
        G2 ] G2
    """

    song = ' Z8 ' + (A*2+B*2)*3

    set_tempo(170)

    inst = Poly_twanger(0.5)
    inst.play_line(song, 0.75, 0, -0.05)

    inst = Blower(-0.25, 0.15, power=1.0/3)
    inst.play_line(song, 1.0, 12, -0.05, limit=1, limit_chars='()')

    inst = Blower(-0.5, 0.5, power=1.0/4)
    inst.play_line(song, 1.0, 24, -0.05)

    drum = " ( C2 ) C ( ( C ) C2 ) C2 "

    inst = Snare()
    inst.play_line(drum*(1+12*3),
                   1.0/7, 0, 0.0)

def queens():
    A = """ shift:4
        { ( G A ) B_ } [ ( G )
        A/ ] ( ( G/ ) F^/  E/ ) F^2
        { [ G2 ] A2 }
        [ D2 ] D2
    """
    
    B = """
        { ( d3/ c/ ) B_ } [ ( A )
        B_ ] ( A/ G/ ) F { [ ( F )
        B_ ] ( c ) d } [ ( B_ )
        c/ ] ( ( B_/ ) A/ G/ ) F^ { [ ( G/ A/ )
        B_/ ] ( ( A/ ) G/ F/ ) E } [ ( F/ G/ )
        A/ ] ( ( G/ ) F/ E/ ) D/ { [ ( ( E/ ) F/ D/ )
        E/ ] ( ( F/ ) G ) G } [ ( F^ )
        G2 ] G2
    """
    #2nd last bar altered

    song = ' Z8 ' + (A*2+B*2)*3

    #song = song.replace('{','').replace('}','')

    set_tempo(170)

    inst = Poly_twanger(0.5)
    inst.play_line(song, 0.75, 0, -0.05, limit=2, limit_chars='[()]')

    inst = Blower(-0.25, 0.1, power=1.0/4)
    inst.play_line(song, 1.0, 12, -0.05, limit=1, limit_chars='()')

    inst = Blower(-0.5, 0.3, power=1.0/5)
    inst.play_line(song, 1.0, 24, -0.05, limit_chars='[()]')

    drum = " ( C C ) C2 "

    inst = Snare()
    inst.play_line(drum*(2+24*3),
                   1.0/10, 0, 0.0)

def brounswyke():
    A = """
        { [ G ] ( F^ ) G } [ ( A ) G2 ] G2
        { F^3 } [ ( E ) D ] ( E ) F^ { [ ( G )
        A ] ( B ) c } [ ( B ) A ] ( G ) F^ { [ ( E )
        F^/ ] ( ( E/ ) F^/ G/ ) F^ } ( E ) [ D2 ] D2
    """
    
    B = """
        { [ A ] ( G ) A } [ ( B )  
        A ] ( F^ ) G { [ ( A )
        B ] ( A ) G } [ ( F^ ) 
        G ] ( E ) F^/ { [ ( ( E/ ) F^/ G/ )
        A2 ] G } [ ( F^/ E/ ) 
        F^/ ] ( ( E/ ) F^/ G/ ) A { [ ( F^ )
        G2 ] E } [ ( F^ ) 
    """
    
    Bend1 = ' G2 ] G2 '
    Bend2 = ' G2 ] G4 '
    
    song = ' Z8 ' + \
           A*2+(B+Bend1)*2 + \
           A*2+(B+Bend1)*2 + \
           A*2+B+Bend1+B+Bend2

    set_tempo(240)

    inst = Poly_twanger(0.5)
    inst.play_line(song, 1.0, 0, -0.05, limit_chars='[()]')

    inst = Blower(-0.25, 0.2, power=1.0/3.5)
    inst.play_line(song, 1.0, 12, -0.05, limit=2, limit_chars='{[()]}')

    inst = Blower(-0.5, 0.4, power=1.0/3.5)
    inst.play_line(song, 1.0, 24, -0.05, limit=2, limit_chars='[()]')

    drum = " ( C C ) C2 "

    inst = Snare()
    inst.play_line(drum*(2+32*3),
                   1.0/10, 0, 0.0)


if __name__ == '__main__':
    music = [
        (milan, 'output/pfh_arbeau_girl_from_milan'),
        (galliard, 'output/pfh_arbeau_galliard'),
        (spanish, 'output/pfh_arbeau_spanish_pavane'),
 
        (earl, 'output/pfh_innsofcourt_earl_of_essex_measure'),
        (old, 'output/pfh_innsofcourt_old_alman'),
        (new, 'output/pfh_innsofcourt_new_alman'),
        (turkelone, 'output/pfh_innsofcourt_turkelone'),
        (sosilia, 'output/pfh_innsofcourt_madame_sosilia_alman'),
        (black, 'output/pfh_innsofcourt_black_alman'),
        (quadran, 'output/pfh_innsofcourt_quadran_pavan'),
        (tinternell, 'output/pfh_innsofcourt_tinternell'),
        (lorayne, 'output/pfh_innsofcourt_lorayne_alman'),
        (queens, 'output/pfh_innsofcourt_queens_alman'),
        (brounswyke, 'output/pfh_innsofcourt_brounswyke_alman'),

        (garden, 'output/pfh_playford_all_in_a_garden_green'),
    ]

    if sys.argv[1] == 'build':
        for func, name in music:
            if len(sys.argv) > 2 and func.__name__ not in sys.argv[2:]: continue
            reset()
            func()
            save_it(name)

    else:
        if len(sys.argv) > 2:
            reset( float(sys.argv[2]) )
        else:
            reset( 1.0 )

        for func, name in music:
            if func.__name__ == sys.argv[1]:
                break
        else:
            raise 'Not found'
        
        func()
        play_it()
        

