Пример #1
0
def play():

    # in example 14 we showed how to nest patterns in ways that are easier
    # to conceptualize.  For instance, these patterns play in order, and we
    # call that a movement.  However, it's often tedious to specify things
    # that replay again and again.  To do make this easy, we have a new
    # selector to introduce - Repeatedly!

    output = Performance(bpm=240, stop_seconds=100)

    scale_choices = Endlessly([scale("D minor")])
    source = ScaleSource(scales=scale_choices)

    pattern1 = Roman(symbols=Repeatedly("1 2 3 4".split(), cycles=2))
    pattern2 = Roman(symbols="4 3 2 1".split())
    movement1 = Ordered(sources=[pattern1, pattern2])

    pattern3 = Roman(symbols=Repeatedly("1 4 1 4 1 5 1 5".split(), cycles=2))
    pattern4 = Roman(symbols="I IV V I".split())
    movement2 = Ordered(sources=[pattern3, pattern4])

    suite = Ordered(sources=[movement1, movement2], channel=1)

    source.send_to(suite)

    # for this example, we won't do anything crazy with transpositions or anything.

    suite.send_to(output)

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #2
0
def play():

    # Let's show how to play a sequence of one length but omit every Nth note

    output = Performance(bpm=120, stop_seconds=15)

    source = ScaleSource(scales=scale("D minor"))

    melody = Roman(symbols=Endlessly("1 2 3 4 5 6 7".split()), channel=1)
    silence = Permit(when=Endlessly([1, 1, 0]))

    # so we're playing a pattern of 1 2 3 4 5 6 7 of scale degree notes in a giant loop
    # the first time through what really happens is:
    #    1 2 <REST> 4 5 <REST> 7
    # and the second time:
    #    1 <REST> 3 4 <REST> 6 7
    # and the third time:
    #    <REST> 2 3 <REST> 5 6 <REST>
    # all of this is because the pattern and the 'silence' pattern are of unequal lengths

    # this is not ALWAYS relevant in a composition, but if you want to do something
    # polyrhytmic and unorthodox (not just with 'Silence') patterns of  unequal length
    # can be interesting.

    # HOMEWORK: experiment with changing the melody patterns and the silence patterns

    # HOMEWORK: change endlessly to randomly, and see what happens

    source.chain([melody, silence, output])
    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #3
0
def play():

    # Let's show how to play a sequence of one length but omit every Nth note

    output = Performance(bpm=120, stop_seconds=15)

    source = ScaleSource(scales=scale("D minor"))

    melody = Roman(symbols=Endlessly("1 2 3 4 5 6 7".split()), channel=1)
    silence = Permit(when=Endlessly([1, 1, 0]))

    # so we're playing a pattern of 1 2 3 4 5 6 7 of scale degree notes in a giant loop
    # the first time through what really happens is:
    #    1 2 <REST> 4 5 <REST> 7
    # and the second time:
    #    1 <REST> 3 4 <REST> 6 7
    # and the third time:
    #    <REST> 2 3 <REST> 5 6 <REST>
    # all of this is because the pattern and the 'silence' pattern are of unequal lengths

    # this is not ALWAYS relevant in a composition, but if you want to do something
    # polyrhytmic and unorthodox (not just with 'Silence') patterns of  unequal length
    # can be interesting.

    # HOMEWORK: experiment with changing the melody patterns and the silence patterns

    # HOMEWORK: change endlessly to randomly, and see what happens

    source.chain([melody, silence, output])
    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #4
0
def play():

    # Permit, introduced in the example 18_randomness2.py allows us to
    # silence an entire chain when certain conditions are met.

    # However, sometimes, we may want to decide to apply an affect only
    # when something is true.  Because this could be useful ANYWHERE
    # the same type of "when" logic can actually be attached to ANYTHING.

    # here is a probabilistic way to use random, that combines the concepts.

    output = Performance(bpm=120, stop_seconds=15)

    source = ScaleSource(scales=scale("Ab blues"))

    melody = Roman(symbols=Endlessly("1 2 3 4 5 6 7".split()), channel=1)
    chordify = Chordify(types=Endlessly(['major','minor']), when=Randomly([0,0.45], mode='probability'))
    transpose = Transpose(octaves=Endlessly([2,-2]), when=Randomly([0,0,0.75], mode='probability'))

    # the result is every other note has a 40% chance of becoming a chord,  which is always alternating
    # major and minor when it happens

    # every THIRD note has a 75 percent chance of being transposed, which will be alternating +2/-2 octaves
    # when it happens

    # so now, we have easily inserted CONDITIONAL effects.  The use of when=Randomly wasn't required.
    # we could also have used Endlessly or Repeatedly.  Though keep in mind if using Repeatedly, when
    # the event chain is exhausted, that particular part of the performance will stop.  And when everything stops,
    # the performance is done.  Because this is likely being applied to an effect chain, Repeatedly probably
    # doesn't make the most sense with "when".  But Endlessly?  Sure!

    source.chain([melody, chordify, transpose, output])
    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #5
0
def play():

    # in example 14 we showed how to nest patterns in ways that are easier
    # to conceptualize.  For instance, these patterns play in order, and we
    # call that a movement.  However, it's often tedious to specify things
    # that replay again and again.  To do make this easy, we have a new
    # selector to introduce - Repeatedly!


    output = Performance(bpm=240, stop_seconds=100)

    scale_choices = Endlessly([scale("D minor")])
    source = ScaleSource(scales=scale_choices)

    pattern1 = Roman(symbols=Repeatedly("1 2 3 4".split(), cycles=2))
    pattern2 = Roman(symbols="4 3 2 1".split())
    movement1 = Ordered(sources=[pattern1, pattern2])

    pattern3 = Roman(symbols=Repeatedly("1 4 1 4 1 5 1 5".split(), cycles=2))
    pattern4 = Roman(symbols="I IV V I".split())
    movement2 = Ordered(sources=[pattern3, pattern4])

    suite = Ordered(sources=[movement1, movement2], channel=1)

    source.send_to(suite)

    # for this example, we won't do anything crazy with transpositions or anything.

    suite.send_to(output)

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #6
0
def play():

    # now modifying our previous example, instead of playing the same two
    # scales in a loop, let's play a given set of notes in each scale.
    # We'll use roman notation to play the 1st, 4th, and 5th note in the scale
    # followed by the 1st, 4th, and 5th major chord
    # finally, we'll play the 2nd, 3rd, and 6th minor chord.


    output = Performance(bpm=120, stop_seconds=10)

    # this is just as before, playing one scale then the other in a loop of 7
    # notes each
    scale1 = scale("c6 major")
    scale2 = scale("c6 minor")
    scale_choices = [ dict(scale=scale1, beats=7), dict(scale=scale2, beats=7) ]
    source = ScaleSource(scales=Endlessly(scale_choices))

    # the scale follower will play the first 7 notes in each scale, whatever the current
    # scale is.  Note that a scale change that doesn't quite line up with the length
    # of the roman pattern rolling over might sound a bit weird.  That's ok.
    roman = Roman(symbols=Endlessly("1 4 5 I IV V ii iii vi".split()), channel=1)
    source.chain([roman, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #7
0
def play():

    # we've focussed a lot on randomness now.  So far, we've shown how to pick random values
    # for notes and how to conditionally do something or not with "when=".

    # What's interesting though is that, due to the way some effects plugins work, we can choose
    # to intermix effects.  Here, we show that there are really two patterns going on, but only one
    # is going to win and actually get to play a note.

    # we're relying one 'musician' object stomping on another, but only sometimes.

    output = Performance(bpm=120, stop_seconds=15)

    source = ScaleSource(scales=scale("Ab blues"))

    pattern1 = Endlessly("1 2 3 4 5 6 7".split())
    pattern2 = Randomly("VII:power VI:power V:power IV:power III:power II:power I:power".split())
    cut_over = Randomly([0,0,0,1,1,1], mode='probability')

    melody1 = Roman(symbols=pattern1, channel=1)
    melody2 = Roman(symbols=pattern2, channel=2, when=cut_over)
    transpose = Transpose(octaves=Endlessly([-2,-1,0,1,2]))

    # there is no sane reason to want to do this, but what happens is that for the first three notes we are guaranteed
    # to play pattern1.  Then three notes of pattern 2.  The last note is acutally a toss up between pattern1 and pattern2.
    # since they live in the same chain, pattern1 is going to overwrite pattern2 even though they are expressed in a chain.
    # we can also even choose to overwrite the MIDI channel, which we do, all while sharing a transposition cycle.

    # again, this isn't realistic for most compositions, we'd likely just set up a bunch of patterns with RESTS, but
    # I wanted to show all the possibilities before leaving the theme of randomness for a while.  Hopefully the
    # idea of "when=" is now drummed in.

    source.chain([melody1, melody2, transpose, output])
    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #8
0
def play():

    # this really isn't endless, because we've engaged a global stop timer.
    # but if you change 10 to 100, it will play for 100 seconds.  Make note
    # of the use of Endlessly here to see that data sources are not exhausted.

    output = Performance(bpm=120, stop_seconds=10)

    # play the two scales for 7 beats each, and then keep using those scales
    scale1 = scale("c6 major")
    scale2 = scale("c6 minor")
    scale_choices = [dict(scale=scale1, beats=7), dict(scale=scale2, beats=7)]

    source = ScaleSource(scales=Endlessly(scale_choices))

    # note: the syntax is simpler to just play ONE scale repeatedly, and you'll see this
    # done more in future examples.  Because we don't need to stay in one scale for N beats
    # before moving on to another, we don't need all the extra info.
    # source = ScaleSource(scales=scale1)

    # the scale follower will play the first 7 notes in each scale, whatever the current
    # scale is.
    follower = ScaleFollower(lengths=7, channel=1)
    source.chain([follower, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #9
0
def play():

    # this really isn't endless, because we've engaged a global stop timer.
    # but if you change 10 to 100, it will play for 100 seconds.  Make note
    # of the use of Endlessly here to see that data sources are not exhausted.

    output = Performance(bpm=120, stop_seconds=10)

    # play the two scales for 7 beats each, and then keep using those scales
    scale1 = scale("c6 major")
    scale2 = scale("c6 minor")
    scale_choices = [ dict(scale=scale1, beats=7), dict(scale=scale2, beats=7) ]

    source = ScaleSource(scales=Endlessly(scale_choices))

    # note: the syntax is simpler to just play ONE scale repeatedly, and you'll see this
    # done more in future examples.  Because we don't need to stay in one scale for N beats
    # before moving on to another, we don't need all the extra info.
    # source = ScaleSource(scales=scale1)

    # the scale follower will play the first 7 notes in each scale, whatever the current
    # scale is.
    follower = ScaleFollower(lengths=7, channel=1)
    source.chain([follower, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #10
0
def play():

    # here's an example that might *START* to approximate a song.
    # here we have two instruments playing on two different tracks.

    output = Performance(bpm=60, stop_seconds=10)

    # both instruments will use the same scale at the same time, but there is a scale
    # change as we cycle between scales every 24 beats

    scale1 = scale("c5 major_pentatonic")
    scale2 = scale("e5 mixolydian")
    scale_choices = [dict(scale=scale1, beats=24), dict(scale=scale2, beats=24)]
    source = ScaleSource(scales=Endlessly(scale_choices))

    # the first instrument plays a series of chords, transposed down an octave
    # from the original scale carrier signal.

    roman1 = Roman(symbols=Endlessly("I IV V IV III:dim ii".split()), channel=1)
    transpose1 = Transpose(octaves=-1)
    source.chain([roman1, transpose1, output])

    # the second instrument plays a series of notes, but is responding to sixteenth
    # notes, not quarter notes, because of the subdivide.

    subdivide2 = Subdivide(splits=4)
    roman2 = Roman(symbols=Endlessly("1 4 3 4 4 3 2 1".split()), channel=2)
    source.chain([subdivide2, roman2, output])

    # homework assignment:
    # change subdivide2 so it's chained BEFORE roman2
    # what happens and why?

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #11
0
    def __init__(self, bpm=None, scale=None, pre_fx=None, post_fx=None, patterns=None, bar_count=None):

        self.scale = scale
        self.bpm = None
        self.pre_fx = pre_fx
        self.post_fx = post_fx
        self.patterns = patterns
        self.bar_count = bar_count
        self._factory = None # set up by scenes.py
        self._scale_source = ScaleSource(scales=core_scale(self.scale))
        self._output = None
        self._players = dict()
Пример #12
0
def play():

    # here we aren't introducing any new concepts, but we're arranging some
    # concepts a little differently.  This is somewhat of a review, as we're going
    # to start exploring some more (hopefully) musical demos in our examples now.

    # This one sounds just a bit Perrey and Kingsley with the right VST.

    output = Performance(bpm=60, stop_seconds=10)

    # let's play in the A major scale

    scale_choices = Endlessly(
        [
            dict(scale=scale("a4 major"))
        ]
    )

    source = ScaleSource(scales=scale_choices)

    # we're going to alternate between the 1st, 4th, and 5th notes
    # of the scale, but we didn't just jump to chords because of what
    # we are about to do with the arp.

    roman = Roman(symbols=Endlessly("1 4 5".split()), channel=1)

    # and now for a clever use of the arp, to machine gun 4 repititions of
    # each chord, with rests in between.  Subdivide alone couldn't do this.
    # Also notice this is running with NO tranpositions.

    arp = Arp(
        # no transpositions
        semitones=Endlessly([0,0,0,0,0,0,0,0]),
        # every beat gets sliced up 8 times, no exceptions
        splits=Endlessly([8]),
        # try uncommenting this next line:
        #octaves=Endlessly([0,0,1,0,2,0,3,0]),
        # play every other note on the arp
        # TODO: IDEA: seems like we should also allow arp velocity!
        rests=Endlessly([0,1,0,1,0,1,0,1])
    )

    # now the output here is just machine gunned notes.  Turn it into major chords.

    chordify = Chordify(types=Endlessly(['major']))

    source.chain([roman, arp, chordify, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #13
0
def play():

    output = Performance(bpm=120, stop_seconds=10)

    # specify that we are going to be playing the c6 major scale for a very long
    # time
    scale1 = scale("c6 major")
    source = ScaleSource(scales=[ dict(scale=scale1, beats=9999) ])

    # but just play the first 7 notes in the scale
    follower = ScaleFollower(lengths=[ 7 ], channel=1)
    source.chain([follower, output])

    # begin performance
    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #14
0
def play():

    # playing all the power chords in a chromatic scale.

    output = Performance(bpm=120, stop_seconds=10)

    # play the two scales for 7 beats each, and then keep using those scales
    scale1 = scale("c4 chromatic")
    scale_choices = dict(scale=scale1, beats=12)
    source = ScaleSource(scales=scale_choices)

    follower = ScaleFollower(lengths=12)
    chordify = Chordify(types="power", channel=1)
    source.chain([follower, chordify, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #15
0
def play():

    # playing all the power chords in a chromatic scale.

    output = Performance(bpm=120, stop_seconds=10)

    # play the two scales for 7 beats each, and then keep using those scales
    scale1 = scale("c4 chromatic")
    scale_choices = dict(scale=scale1, beats=12)
    source = ScaleSource(scales=scale_choices)

    follower = ScaleFollower(lengths=12)
    chordify = Chordify(types="power", channel=1)
    source.chain([follower, chordify, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #16
0
def play():

    output = Performance(bpm=120, stop_seconds=10)

    scale1 = scale("c6 major")
    scale2 = scale("c6 minor")

    # the performance will use the c6 major scale for 7 beats, then the c6 minor scale for 7 beats
    source = ScaleSource(scales=[ dict(scale=scale1, beats=7), dict(scale=scale2, beats=7) ])

    # the scale follower will play the first 7 notes in each scale
    follower = ScaleFollower(lengths=[7, 7], channel=1)

    source.chain([follower, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #17
0
def play():

    # here we aren't introducing any new concepts, but we're arranging some
    # concepts a little differently.  This is somewhat of a review, as we're going
    # to start exploring some more (hopefully) musical demos in our examples now.

    # This one sounds just a bit Perrey and Kingsley with the right VST.

    output = Performance(bpm=60, stop_seconds=10)

    # let's play in the A major scale

    scale_choices = Endlessly([dict(scale=scale("a4 major"))])

    source = ScaleSource(scales=scale_choices)

    # we're going to alternate between the 1st, 4th, and 5th notes
    # of the scale, but we didn't just jump to chords because of what
    # we are about to do with the arp.

    roman = Roman(symbols=Endlessly("1 4 5".split()), channel=1)

    # and now for a clever use of the arp, to machine gun 4 repititions of
    # each chord, with rests in between.  Subdivide alone couldn't do this.
    # Also notice this is running with NO tranpositions.

    arp = Arp(
        # no transpositions
        semitones=Endlessly([0, 0, 0, 0, 0, 0, 0, 0]),
        # every beat gets sliced up 8 times, no exceptions
        splits=Endlessly([8]),
        # try uncommenting this next line:
        #octaves=Endlessly([0,0,1,0,2,0,3,0]),
        # play every other note on the arp
        # TODO: IDEA: seems like we should also allow arp velocity!
        rests=Endlessly([0, 1, 0, 1, 0, 1, 0, 1]))

    # now the output here is just machine gunned notes.  Turn it into major chords.

    chordify = Chordify(types=Endlessly(['major']))

    source.chain([roman, arp, chordify, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #18
0
def play():

    output = Performance(bpm=120, stop_seconds=10)

    scale1 = scale("c6 major")
    scale2 = scale("c6 minor")

    # the performance will use the c6 major scale for 7 beats, then the c6 minor scale for 7 beats
    source = ScaleSource(
        scales=[dict(scale=scale1, beats=7),
                dict(scale=scale2, beats=7)])

    # the scale follower will play the first 7 notes in each scale
    follower = ScaleFollower(lengths=[7, 7], channel=1)

    source.chain([follower, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #19
0
def play():

    # Previously, in 11_randomness we introduced the default 'choice' random mode, which just endlessly
    # picks something from a list.

    # in 18_randomness2.py we introduced 'probability', which returns True or False depending on the chances
    # given.  It's used with the "when" statement, shown in both 18_randomness2.py and 19_skipover.py for doing
    # some rather fun things.

    # Some more types of randomness are "exhaust" and "human_random".

    # just to prove this performance will terminate by reaching the END of the performance, we're setting the stop
    # seconds to a crazy long amount of time.  This one won't loop endlessly, because of the way 'exhaust' mode works.
    output = Performance(bpm=120, stop_seconds=9999)

    # exhaust takes a list and feeds it in random order.  It would be the same as shuffle sorting the list, basically, and then
    # popping off the first element repeatedly.  The result is all items will be used, in a random order, and then the sequence
    # will stop.
    #
    # We normally write this in a one liner, but we'll break it up in this example to make things a bit more clear

    scale_choices = [
        scale("Ab blues"),
        scale("C major"),
        scale("Eb mixolydian")
    ]
    scale_chooser = Randomly(scale_choices, mode='exhaust')
    source = ScaleSource(scales=Randomly(scale_choices, mode='exhaust'))

    # human_random is inspired by the Apple iTunes problem.  In a party shuffle mode, people may get suprised to learn
    # that the system played three Van Halen songs in a row.  Apple changed the system to switch between artists more frequently.
    # in CAMP, human random will play each item in a list once, before going back and starting over with a new random selection.

    note_choices = "1 2 3 4 5 6 7".split()
    note_chooser = Randomly(note_choices, mode='human_random')
    melody = Roman(symbols=note_chooser, channel=1)

    # combining these two concepts together, we are going to play 3 random scales in sequence, and then FOR EACH SCALE, play
    # the scale notes in random order.

    source.chain([melody, chordify, transpose, output])
    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #20
0
def play():

    # in example 13 we showed the use of Ordered to trigger
    # one pattern after another.  As programs grow, it might be nice
    # to group them conceptually in a larger composition.

    # This is a demo that shows how Ordered can nest to not work only
    # with basic patterns, but also larger movements.

    # The idea is this: Generators stack!

    # Like before, we're setting stop seconds to 100 seconds but this composition
    # will complete due to the sources being exhausted first, which is the point.

    output = Performance(bpm=240, stop_seconds=100)

    for scale_name in ["C major", "D minor"]:

        scale_choices = Endlessly([scale(scale_name)])
        source = ScaleSource(scales=scale_choices)

        pattern1 = Roman(symbols="1 2 3 4 5 6 7".split())
        pattern2 = Roman(symbols="i ii iii iv v v vii".split())
        movement1 = Ordered(sources=[pattern1, pattern2])

        pattern3 = Roman(symbols="7 6 5 4 3 2 1".split())
        pattern4 = Roman(symbols="vii vi v iv iii ii i".split())
        movement2 = Ordered(sources=[pattern3, pattern4])
        movement2_transposer = Transpose(octaves=Endlessly([-2]))
        movement2.send_to(movement2_transposer)

        suite = Ordered(sources=[movement1, movement2], channel=1)

        source.send_to(suite)
        output.listens_to([movement1, movement2_transposer])

        # BONUS TIP: we technically don't have to have just one conductor invocation, if it
        # keeps it simple.

        conductor = Conductor(signal=[source], performance=output)
        conductor.start()
Пример #21
0
def play():

    # in example 11 we showed off some random functionality
    # in example 17 we showed how to silence notes based on that
    # knowledge of 'random'.

    # here is a probabilistic way to use random, that combines the concepts.

    output = Performance(bpm=120, stop_seconds=15)

    source = ScaleSource(scales=scale("Ab blues"))

    melody = Roman(symbols=Endlessly("1 2 3 4 5 6 7".split()), channel=1)
    silence = Permit(when=Randomly([1, 0.5], mode='probability'))

    # so we're playing a scale pattern, but every other note has a 50% chance
    # of not being played.

    source.chain([melody, silence, output])
    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #22
0
    def test_simple_band(self):

        output = Performance(bpm=120, stop_seconds=10)

        scale1 = scale("c6 major")
        scale2 = scale("c6 minor")

        source = ScaleSource(scales=[ dict(scale=scale1, beats=7), dict(scale=scale2, beats=7) ])

        subdivide = Subdivide(splits=[4])
        roman = Roman(symbols="1 2 3 4 I IV V iii".split(), channel=1)

        follower = ScaleFollower(lengths=[ 7 ])
        chordify = Chordify(types=[ 'power' ])
        shift = Transpose(octaves=[-3], channel=2)

        source.chain([subdivide, roman, output])
        source.chain([follower, chordify, shift, output])

        conductor = Conductor(signal=[source], performance=output)
        conductor.start()
Пример #23
0
def play():

    # in example 11 we showed off some random functionality
    # in example 17 we showed how to silence notes based on that
    # knowledge of 'random'.

    # here is a probabilistic way to use random, that combines the concepts.

    output = Performance(bpm=120, stop_seconds=15)

    source = ScaleSource(scales=scale("Ab blues"))

    melody = Roman(symbols=Endlessly("1 2 3 4 5 6 7".split()), channel=1)
    silence = Permit(when=Randomly([1, 0.5], mode='probability'))

    # so we're playing a scale pattern, but every other note has a 50% chance
    # of not being played.

    source.chain([melody, silence, output])
    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #24
0
def play():

    # Previously, in 11_randomness we introduced the default 'choice' random mode, which just endlessly
    # picks something from a list.

    # in 18_randomness2.py we introduced 'probability', which returns True or False depending on the chances
    # given.  It's used with the "when" statement, shown in both 18_randomness2.py and 19_skipover.py for doing
    # some rather fun things.

    # Some more types of randomness are "exhaust" and "human_random".

    # just to prove this performance will terminate by reaching the END of the performance, we're setting the stop
    # seconds to a crazy long amount of time.  This one won't loop endlessly, because of the way 'exhaust' mode works.
    output = Performance(bpm=120, stop_seconds=9999)

    # exhaust takes a list and feeds it in random order.  It would be the same as shuffle sorting the list, basically, and then
    # popping off the first element repeatedly.  The result is all items will be used, in a random order, and then the sequence
    # will stop.
    #
    # We normally write this in a one liner, but we'll break it up in this example to make things a bit more clear

    scale_choices = [scale("Ab blues"), scale("C major"), scale("Eb mixolydian")]
    scale_chooser = Randomly(scale_choices, mode='exhaust')
    source = ScaleSource(scales=Randomly(scale_choices, mode='exhaust'))

    # human_random is inspired by the Apple iTunes problem.  In a party shuffle mode, people may get suprised to learn
    # that the system played three Van Halen songs in a row.  Apple changed the system to switch between artists more frequently.
    # in CAMP, human random will play each item in a list once, before going back and starting over with a new random selection.

    note_choices = "1 2 3 4 5 6 7".split()
    note_chooser = Randomly(note_choices, mode='human_random')
    melody = Roman(symbols=note_chooser, channel=1)

    # combining these two concepts together, we are going to play 3 random scales in sequence, and then FOR EACH SCALE, play
    # the scale notes in random order.

    source.chain([melody, chordify, transpose, output])
    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #25
0
def play():

    # example 05 was "playing all the power chords in a chromatic scale".
    # let's modify the example very slightly using Subdivide.
    # normally the conductor sends down quarter notes.  Let's alternate
    # playing quarter notes and sixteenth notes.

    output = Performance(bpm=120, stop_seconds=10)

    # play the two scales for 7 beats each, and then keep using those scales
    source = ScaleSource(scales=scale("c4 chromatic"))

    follower = ScaleFollower(lengths=12)

    # pay attention to this part - nothing else has changed
    subdivide = Subdivide(splits=Endlessly([1, 4]))

    chordify = Chordify(types="power", channel=1)
    source.chain([follower, subdivide, chordify, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #26
0
def play():

    # example 05 was "playing all the power chords in a chromatic scale".
    # let's modify the example very slightly using Subdivide.
    # normally the conductor sends down quarter notes.  Let's alternate
    # playing quarter notes and sixteenth notes.

    output = Performance(bpm=120, stop_seconds=10)

    # play the two scales for 7 beats each, and then keep using those scales
    source = ScaleSource(scales=scale("c4 chromatic"))

    follower = ScaleFollower(lengths=12)

    # pay attention to this part - nothing else has changed
    subdivide = Subdivide(splits=Endlessly([1,4]))

    chordify = Chordify(types="power", channel=1)
    source.chain([follower, subdivide, chordify, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #27
0
def play():

    # examples/06_subdivide showed how to chop up the incoming quarter note signal
    # to create faster signals.  However, sometimes in a given bar we want a mix of note durations.
    # how do we do that?

    # For this example, lets play whole note chords underneath a quarter note melody.

    # implementation caveat:
    # Because the "beat" signal from the conductor comes in every quarter note, we have to take
    # care and rest in the right places of the input signal to avoid funness.  This may get easier
    # later.

    # this is pretty close to what we did in 09_harmony.py

    output = Performance(bpm=120, stop_seconds=15)

    # this performance will actually complete so stop_seconds is mostly ignorable.

    scale_choices = Endlessly([scale("D major")])
    source = ScaleSource(scales=scale_choices)

    # the underlying chords - note the rests
    chords = Roman(symbols=Endlessly(
        "I - - - I - - - IV - - - V - - - ".split()),
                   channel=1)
    # every beat is a quarter note, but on the first beat in a cycle of 4
    # play a WHOLE note
    chords_len = Duration(lengths=Endlessly([1, 0, 0, 0]))
    source.chain([chords, chords_len, output])

    # the melody
    # TODO: Roman should figure out if input is a string here and auto-split.
    pattern2 = Roman("1 2 3 1 2 2 1 3 3 1 3 2".split(), channel=2)
    pattern3 = Roman("1 3 3 1 4 4 1 3 3 1 5 -".split(), channel=2)
    pattern4 = Roman("1 5 5 1 4 4 1 3 3 1 2 2".split(), channel=2)
    pattern5 = Roman("1 2 4 6 4 2 1 6 4 2 1 -".split(), channel=2)
    melody_sequence = [pattern2, pattern3, pattern4, pattern5]
    melody = Ordered(sources=Endlessly(melody_sequence))
    # we could just do: source.chain(source, ordered) here
    # but it would mean later we would have less flexibility
    # to make the patterns feel different.
    source.chain([melody])
    for pattern in melody_sequence:
        source.chain([pattern, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #28
0
def play():

    # example 05 was "playing all the power chords in a chromatic scale".
    # example 06 used subdivide to chop up alternating measures with faster notes
    # now lets alternately transpose every 2nd measure up an octave
    # and every 3rd measure down an octave

    output = Performance(bpm=120, stop_seconds=10)

    source = ScaleSource(scales=scale("c4 chromatic"))

    follower = ScaleFollower(lengths=Endlessly([12]))

    subdivide = Subdivide(splits=Endlessly([1,4]))

    # pay attention to this part - nothing else has changed
    transpose = Transpose(octaves=Endlessly([0,1,-1]))

    chordify = Chordify(types="power", channel=1)
    source.chain([follower, subdivide, transpose, chordify, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #29
0
def play():

    # we've focussed a lot on randomness now.  So far, we've shown how to pick random values
    # for notes and how to conditionally do something or not with "when=".

    # What's interesting though is that, due to the way some effects plugins work, we can choose
    # to intermix effects.  Here, we show that there are really two patterns going on, but only one
    # is going to win and actually get to play a note.

    # we're relying one 'musician' object stomping on another, but only sometimes.

    output = Performance(bpm=120, stop_seconds=15)

    source = ScaleSource(scales=scale("Ab blues"))

    pattern1 = Endlessly("1 2 3 4 5 6 7".split())
    pattern2 = Randomly(
        "VII:power VI:power V:power IV:power III:power II:power I:power".split(
        ))
    cut_over = Randomly([0, 0, 0, 1, 1, 1], mode='probability')

    melody1 = Roman(symbols=pattern1, channel=1)
    melody2 = Roman(symbols=pattern2, channel=2, when=cut_over)
    transpose = Transpose(octaves=Endlessly([-2, -1, 0, 1, 2]))

    # there is no sane reason to want to do this, but what happens is that for the first three notes we are guaranteed
    # to play pattern1.  Then three notes of pattern 2.  The last note is acutally a toss up between pattern1 and pattern2.
    # since they live in the same chain, pattern1 is going to overwrite pattern2 even though they are expressed in a chain.
    # we can also even choose to overwrite the MIDI channel, which we do, all while sharing a transposition cycle.

    # again, this isn't realistic for most compositions, we'd likely just set up a bunch of patterns with RESTS, but
    # I wanted to show all the possibilities before leaving the theme of randomness for a while.  Hopefully the
    # idea of "when=" is now drummed in.

    source.chain([melody1, melody2, transpose, output])
    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #30
0
def play():

    # Permit, introduced in the example 18_randomness2.py allows us to
    # silence an entire chain when certain conditions are met.

    # However, sometimes, we may want to decide to apply an affect only
    # when something is true.  Because this could be useful ANYWHERE
    # the same type of "when" logic can actually be attached to ANYTHING.

    # here is a probabilistic way to use random, that combines the concepts.

    output = Performance(bpm=120, stop_seconds=15)

    source = ScaleSource(scales=scale("Ab blues"))

    melody = Roman(symbols=Endlessly("1 2 3 4 5 6 7".split()), channel=1)
    chordify = Chordify(types=Endlessly(['major', 'minor']),
                        when=Randomly([0, 0.45], mode='probability'))
    transpose = Transpose(octaves=Endlessly([2, -2]),
                          when=Randomly([0, 0, 0.75], mode='probability'))

    # the result is every other note has a 40% chance of becoming a chord,  which is always alternating
    # major and minor when it happens

    # every THIRD note has a 75 percent chance of being transposed, which will be alternating +2/-2 octaves
    # when it happens

    # so now, we have easily inserted CONDITIONAL effects.  The use of when=Randomly wasn't required.
    # we could also have used Endlessly or Repeatedly.  Though keep in mind if using Repeatedly, when
    # the event chain is exhausted, that particular part of the performance will stop.  And when everything stops,
    # the performance is done.  Because this is likely being applied to an effect chain, Repeatedly probably
    # doesn't make the most sense with "when".  But Endlessly?  Sure!

    source.chain([melody, chordify, transpose, output])
    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #31
0
def play():

    # examples/06_subdivide showed how to chop up the incoming quarter note signal
    # to create faster signals.  However, sometimes in a given bar we want a mix of note durations.
    # how do we do that?

    # For this example, lets play whole note chords underneath a quarter note melody.

    # implementation caveat:
    # Because the "beat" signal from the conductor comes in every quarter note, we have to take
    # care and rest in the right places of the input signal to avoid funness.  This may get easier
    # later.

    # this is pretty close to what we did in 09_harmony.py


    output = Performance(bpm=120, stop_seconds=15)

    # this performance will actually complete so stop_seconds is mostly ignorable.

    scale_choices = Endlessly([scale("D major")])
    source = ScaleSource(scales=scale_choices)

    # the underlying chords - note the rests
    chords     = Roman(symbols=Endlessly("I - - - I - - - IV - - - V - - - ".split()), channel=1)
    # every beat is a quarter note, but on the first beat in a cycle of 4
    # play a WHOLE note
    chords_len = Duration(lengths=Endlessly([1,0,0,0]))
    source.chain([chords, chords_len, output])

    # the melody
    # TODO: Roman should figure out if input is a string here and auto-split.
    pattern2 = Roman("1 2 3 1 2 2 1 3 3 1 3 2".split(), channel=2)
    pattern3 = Roman("1 3 3 1 4 4 1 3 3 1 5 -".split(), channel=2)
    pattern4 = Roman("1 5 5 1 4 4 1 3 3 1 2 2".split(), channel=2)
    pattern5 = Roman("1 2 4 6 4 2 1 6 4 2 1 -".split(), channel=2)
    melody_sequence = [ pattern2, pattern3, pattern4, pattern5 ]
    melody = Ordered(sources=Endlessly(melody_sequence))
    # we could just do: source.chain(source, ordered) here
    # but it would mean later we would have less flexibility
    # to make the patterns feel different.
    source.chain([melody])
    for pattern in melody_sequence:
        source.chain([ pattern, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #32
0
def play():

    # here's an example that might *START* to approximate a song.
    # here we have two instruments playing on two different tracks.

    output = Performance(bpm=60, stop_seconds=10)

    # both instruments will use the same scale at the same time, but there is a scale
    # change as we cycle between scales every 24 beats

    scale1 = scale("c5 major_pentatonic")
    scale2 = scale("e5 mixolydian")
    scale_choices = [
        dict(scale=scale1, beats=24),
        dict(scale=scale2, beats=24)
    ]
    source = ScaleSource(scales=Endlessly(scale_choices))

    # the first instrument plays a series of chords, transposed down an octave
    # from the original scale carrier signal.

    roman1 = Roman(symbols=Endlessly("I IV V IV III:dim ii".split()),
                   channel=1)
    transpose1 = Transpose(octaves=-1)
    source.chain([roman1, transpose1, output])

    # the second instrument plays a series of notes, but is responding to sixteenth
    # notes, not quarter notes, because of the subdivide.

    subdivide2 = Subdivide(splits=4)
    roman2 = Roman(symbols=Endlessly("1 4 3 4 4 3 2 1".split()), channel=2)
    source.chain([subdivide2, roman2, output])

    # homework assignment:
    # change subdivide2 so it's chained BEFORE roman2
    # what happens and why?

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #33
0
    def test_simple_band(self):

        output = Performance(bpm=120, stop_seconds=10)

        scale1 = scale("c6 major")
        scale2 = scale("c6 minor")

        source = ScaleSource(
            scales=[dict(scale=scale1, beats=7),
                    dict(scale=scale2, beats=7)])

        subdivide = Subdivide(splits=[4])
        roman = Roman(symbols="1 2 3 4 I IV V iii".split(), channel=1)

        follower = ScaleFollower(lengths=[7])
        chordify = Chordify(types=['power'])
        shift = Transpose(octaves=[-3], channel=2)

        source.chain([subdivide, roman, output])
        source.chain([follower, chordify, shift, output])

        conductor = Conductor(signal=[source], performance=output)
        conductor.start()
Пример #34
0
def play():

    # this is sort of a variation of example 08.  Except now, rather than
    # playing two different patterns that might clash, we're selecting chord
    # patterns for instrument 2 to harmonize with what instrument 1 is playing.

    output = Performance(bpm=120, stop_seconds=10)

    # both instruments will use the same scale at the same time, but there is a scale
    # change as we cycle between scales every 24 beats

    scale1 = scale("c5 major_pentatonic")
    scale2 = scale("e5 mixolydian")
    scale_choices = [ dict(scale=scale1, beats=24), dict(scale=scale2, beats=24) ]
    source = ScaleSource(scales=Endlessly(scale_choices))

    # the first instrument plays a series of notes

    roman1 = Roman(symbols=Endlessly("1 2 4 1 2 3 1 2 4 3 3".split()), channel=1)
    source.chain([roman1, output])

    # the second instrument transposes that note down two octaves and plays a power
    # chord.  We could pass in an array of chords to vary the chord type, but this is
    # probably going to sound less prone to clashing.

    chordify = Chordify(types=Endlessly(["power"]), channel=2)
    transpose = Transpose(octaves=Endlessly([-2]))
    source.chain([roman1, chordify, transpose, output])

    # note that roman 1 is part of each chain, but the channel number is overridden
    # in the second set.  This can be done because the event objects are copied as they
    # are passed between each layer.  Technically the channel can be overriden at any
    # time.  Ideas for future chaos, perhaps?

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #35
0
def play():

    # in example 15 we show how to drift between different patterns.

    # so far, we've mostly been showing patterns inside a scale, because
    # that sounds good for melodic instruments.  Not everything lives
    # inside a scale though - accidentals etc.  Transpose and the arp
    # can move by semitones to overcome that.

    # however, when dealing with drum kits, the scale is pretty much never
    # relevant

    # Usually these things trigger with something like C3 for a kick drum, D4
    # for a Tom, and so on -- but it varies by drumkit.

    # Having a transpose or scale change in there would
    # mess it all up.

    # Here's an example of switching through some drum patterns, and it also
    # fires multiple types of drum hits on a single channel.

    # when setting this example up, put any synth you want on MIDI channel 2,
    # but on MIDI channel 1 put some kind of drumkit.  You may need to change
    # the MIDI note names to make it sound right

    K = "F4"
    H = "A4"
    C = "Bb4"

    output = Performance(bpm=120, stop_seconds=15)

    melody_trigger = ScaleSource(scales=scale("D minor"))
    melody = Roman(symbols=Endlessly("1 - - - - 2 - - - -".split()), channel=1)

    drum_trigger = Subdivide(splits=4, channel=2) # gimme 16th notes for the drum tracks

    # kick drum on the quarter notes
    kicks = Literal(symbols=Endlessly([K, None, None, None,
                                       K, None, None, None,
                                       K, None, None, None,
                                       K, None, None, None]))

    # hihat on the 8th notes every other bar
    # but wait one bar before starting that up.
    hihat = Ordered(
        sources = Endlessly([
            Literal(symbols="- - - - - - - - - - - - - - - -".split()),
            Literal(symbols=Endlessly([
                H, None, H, None, H, None, H, None,
                H, None, H, None, H, None, H, None
            ]))
        ])
    )

    # cymbals on the half notes
    cymbals = Literal(symbols=Endlessly([
            C, None, None, None, None, None, None,
            C, None, None, None, None, None, None
        ]))


    melody_trigger.send_to(melody)
    drum_trigger.send_to([kicks, hihat, cymbals])
    output.listens_to([melody, kicks, hihat, cymbals])


    conductor = Conductor(signal=[melody_trigger, drum_trigger], performance=output)
    conductor.start()
Пример #36
0
def play():

    # so far what we've done has been mostly theoretical.
    # to construct larger songs, obviously, one thing has to occur
    # after another.  To do this, we could just pass in GIGANTIC
    # arrays to everything but that would suck!

    # now, everything in CAMP is built off the idea of generators.
    # this means the system can pretty well know if one thing is done
    # playing and more on to the next.

    # while we could just pass in huge note arrays, that kind of sucks.
    # What if we want a flute to play
    # it's part and then have the trombone come in?  To do that,
    # we need a facility for ordering - to say "this comes next"

    # NOTE: we're setting stop seconds to 100 seconds but this composition
    # will complete due to the sources being exhausted first, which is the point.
    # we're not writing an endlessly generative piece here, but moving towards
    # more explicit songwriting tools.  The point of this example is to show
    # we are writing a finite song in PIECES.

    output = Performance(bpm=240, stop_seconds=100)
    scale_choices = Endlessly([scale("a3 major")])

    source = ScaleSource(scales=scale_choices)

    pattern1 = Roman(symbols="1 2 3 4".split())
    pattern2 = Roman(symbols="I I I I".split())
    pattern2_transpose = Transpose(octaves=Endlessly([2]))
    pattern2.send_to(pattern2_transpose)

    # in this example, we're going to play pattern1 until it is exhausted
    # then pattern2, and when that's done, we're done.

    ordered = Ordered(sources=[pattern1, pattern2], channel=1)

    # HOMEWORK ASSIGNMENT:
    # uncomment this line to randomly pick a pattern and play it until
    # it is exhausted, but keep doing that endlessly.  Patterns might
    # repeat, see notes about advanced usages of Randomly in examples/11_randomness.py
    #
    # ordered = Ordered(sources=Randomly([pattern1,pattern2]), channel=1)

    # HOMEWORK ASSIGNMENT:
    #
    # uncomment this next line to play pattern1, pattern2 in an endless sequence
    # ordered = Ordered(Endlessly([pattern1,pattern2]))

    # TODO: IDEA: it might be nice to have a "beats" flag on ordered where it can stop
    # producing after a certain number of beats
    # ordered = Ordered(Randomly([pattern1,pattern2,pattern3]), beats=24)
    # this would allow for patterns of patterns, and better nesting.

    # TODO: IDEA: anything that can take a "beats" should really take a bars=, it's just easier
    # to think about

    # HOMEWORK: using a pattern in Ordered that uses Endlessly will cause the pattern to NOT switch.
    # Try this out and understand why pattern 2 will never play.
    # pattern1 = Roman(symbols=Endlessly("3 6 3 6 5 1 2".split()))
    # ordered = Ordered([pattern1,pattern2,pattern3])

    # TODO: IDEA, make the above homework example actually work, with something like:
    # pattern1 = Roman(symbols=Endlessly("3 6 3 6 5 1 2".split()))
    # ordered = Ordered([ dict(pattern=pattern1, beats=8), dict(pattern=pattern2, beats=8) ])

    # NOTE: in simple cases we could connect ordered to the output, but we'd miss the transposition,
    # and I wanted to show off a more complete example.  This also underscores the idea that source.chain
    # is just syntactic sugar and you don't have to use it.

    source.send_to(ordered)
    pattern1.send_to(output)
    pattern2_transpose.send_to(output)

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #37
0
def play():

    # previous examples showed a couple of instruments, lets go back to one
    # instrument to showcase just the arpeggiator.

    # WARNING - may not make sense if you haven't used any hardware or
    # software arpeggiators.

    output = Performance(bpm=120, stop_seconds=10)

    scale1 = scale("c4 major")
    scale_choices = [ dict(scale=scale1, beats=7) ]

    # refresher - CAMP is generator based, and performances stop when there is
    # nothing left to do OR stop_seconds is reached.
    # by not wrapping the scale choices in "Endlessly", we're allowing this example
    # to terminate when the scale is done.  This example will play 24 quarter note
    # beats and STOP.  But the way the arpeggiator is coded, there will really be
    # 24*4 = 96 sixteenth notes, of which 3/4s of them will be played with audible notes
    # and the rests will be, ahem, rests.

    # refresher - the MIDI channel number can be set anywhere in the graph, as well as overrided
    # anywhere in the graph.  Leaving it off here on ScaleSource and setting it on the
    # Arp would do exactly the same thing.  Leaving off the channel will cause an exception.

    source = ScaleSource(scales=(scale_choices), channel=1)

    # refresher - the scale follower will take note of the current scale and
    # play the scale for a given number of notes in order.  We could be more
    # creative by using Roman() instead to select particular notes (or chords)
    # in the scale.

    follower = ScaleFollower(lengths=Endlessly([7]))

    # refresher, the roman usage looks very similar:
    # roman = Roman(symbols="1 2 3 4 5 6 7".split())
    # really, there's little use for ScaleFollower in the real world, but it was
    # getting lonely and wanted to be featured here.  It's a bit more efficient
    # but I doubt that matters.

    # NOW FOR THE FUN PART.

    # ok, here's the arpeggiator.

    # in this example, we take the currently selected note from the scale
    # play that note, then the notes 4 and 9 semitones up - a major chord.
    # every single beat will be divided into 4 parts by the arp due to 'splits'
    # however every 4th note is also a REST.
    #
    # see this table:
    #
    # TRIGGER: | C4 ~~~~~~~~~~~~ | D4 ~~~~~~~~~ | ...
    # ---------+-----------------+--------------+
    # RESTS:   | N   N   N  Y    | N   N   N  Y |
    # SEMI:    | +0  +3  +8  -   | +0  +3  +8   |
    # OCTAVES: | +2  -2  0   0   | +2  -2  0  0 |
    # ---------+-----------------+--------------+
    # PLAY:    | C6  E2  G4  -   | D6  Gb2 A4 - |
    #
    # more creative things can be done by having the semitones
    # and rest patterns be different lengths, and so on, as well as using
    # the 'free' mode with those uneven lengths.

    arp = Arp(
        semitones=Endlessly([0,3,8,0]),
        octaves=Endlessly([2,-2,0,0]),
        splits=Endlessly([4]),
        rests=Endlessly([0,0,0,1])
    )

    # HOMEWORK: add "mode=free" to the Arp constructor above and experiment
    # with octaves, splits, rests, and semitones of different values and array
    # lengths.

    # POP QUIZ:  what happens if we remove Endlessly from some of the expressions above?
    # WHY?

    # the chain here is simple - scale source feeds note source, which in turn
    # feeds the arp.

    source.chain([follower, arp, output])

    # kick out the jams

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #38
0
def play():

    # in example 15 we show how to drift between different patterns.

    # so far, we've mostly been showing patterns inside a scale, because
    # that sounds good for melodic instruments.  Not everything lives
    # inside a scale though - accidentals etc.  Transpose and the arp
    # can move by semitones to overcome that.

    # however, when dealing with drum kits, the scale is pretty much never
    # relevant

    # Usually these things trigger with something like C3 for a kick drum, D4
    # for a Tom, and so on -- but it varies by drumkit.

    # Having a transpose or scale change in there would
    # mess it all up.

    # Here's an example of switching through some drum patterns, and it also
    # fires multiple types of drum hits on a single channel.

    # when setting this example up, put any synth you want on MIDI channel 2,
    # but on MIDI channel 1 put some kind of drumkit.  You may need to change
    # the MIDI note names to make it sound right

    K = "F4"
    H = "A4"
    C = "Bb4"

    output = Performance(bpm=120, stop_seconds=15)

    melody_trigger = ScaleSource(scales=scale("D minor"))
    melody = Roman(symbols=Endlessly("1 - - - - 2 - - - -".split()), channel=1)

    drum_trigger = Subdivide(splits=4,
                             channel=2)  # gimme 16th notes for the drum tracks

    # kick drum on the quarter notes
    kicks = Literal(symbols=Endlessly([
        K, None, None, None, K, None, None, None, K, None, None, None, K, None,
        None, None
    ]))

    # hihat on the 8th notes every other bar
    # but wait one bar before starting that up.
    hihat = Ordered(sources=Endlessly([
        Literal(symbols="- - - - - - - - - - - - - - - -".split()),
        Literal(symbols=Endlessly([
            H, None, H, None, H, None, H, None, H, None, H, None, H, None, H,
            None
        ]))
    ]))

    # cymbals on the half notes
    cymbals = Literal(symbols=Endlessly([
        C, None, None, None, None, None, None, C, None, None, None, None, None,
        None
    ]))

    melody_trigger.send_to(melody)
    drum_trigger.send_to([kicks, hihat, cymbals])
    output.listens_to([melody, kicks, hihat, cymbals])

    conductor = Conductor(signal=[melody_trigger, drum_trigger],
                          performance=output)
    conductor.start()
Пример #39
0
def play():

    # in example 10 we showed you how powerful the arpeggiator can get.
    # well, that's great for some degrees of chaos, but what if we want
    # to let the computer make MORE decisions?

    output = Performance(bpm=120, stop_seconds=10)

    # randomness is one way to do that.

    # in example 03 we showed how to use Endlessly to loop over a set of input.
    # that used SELECTORS, but Endlessly is just a LINEAR selector that loops
    # when it gets to the end of the input.

    # randomness can also be accessed, using the Randomly selector, which
    # chooses an item from a list.
    # each choice is then repeated for a given number of times.
    # here lets pick some random scales, but whatever we pick, hold that choice
    # for 7 beats, which we covered in example 01.

    random_scale_choices = Randomly([
        # each of these items are scale specifications.  You've seen these in the very first examples.
        dict(scale=scale("c6 major"), beats=7),
        dict(scale=scale("Db4 minor_pentatonic"), beats=7),
        dict(scale=scale("Eb3 mixolydian"), beats=7)
    ])

    # note that the random selector could repeat a selection as currently
    # implemented and/or specified.  See ideas below.

    # note if we want a random choice to be made EVERY beat we can simplify
    # our usage of randomly like so:

    random_note_choices = Randomly("1 2 3 4 5 6 7".split())

    # what does that do?  It randomly plays one of 7 notes in the current scale.
    # that's syntactically clean, but super basic.  Let's override that with something
    # showing more options available to Randomly.

    # we're playing CHORDS now, and if we choose the "I" chord we are going to play
    # it twice in the current scale (which might change after we play the first, so this is
    # a minor lie). All within the current scale, of course.

    random_note_choices = Randomly([
        dict(value="I", hold=2),
        dict(value="IV", hold=1),
        dict(value="V", hold=1),
        dict(value="i", hold=1),
        dict(value="ii", hold=1),
        dict(value="iv:dim7", hold=1),
    ])

    # HOMEWORK: add some more scales to the random_scale_choices above and take out some
    # notes from random_note_choices.  Mix scales with notes!

    # FUTURE IDEA: also support a notion of frequency controlling what will be drawn.
    # frequencies should add up to 1.  This would still be compatible with "hold" above.

    #random_note_choices = Randomly([
    #    dict(value="I", frequency=0.4),
    #    dict(value="IV", frequency=0.2),
    #    dict(value="V", frequency=0.2),
    #    dict(value="i", frequency=0.1),
    #    dict(value="ii", frequency=0.05),
    #    dict(value="iv:dim7", frequency=0.05),
    #])

    # for more examples, see the demos labelled randomness2.py, randomness3.py, etc.
    # we want to cover some other things first, so I'm not going to go completelyinto
    # randomness now.

    source = ScaleSource(scales=random_scale_choices)
    roman = Roman(symbols=random_note_choices, channel=1)
    source.chain([roman, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #40
0
def play():

    # in example 10 we showed you how powerful the arpeggiator can get.
    # well, that's great for some degrees of chaos, but what if we want
    # to let the computer make MORE decisions?

    output = Performance(bpm=120, stop_seconds=10)

    # randomness is one way to do that.

    # in example 03 we showed how to use Endlessly to loop over a set of input.
    # that used SELECTORS, but Endlessly is just a LINEAR selector that loops
    # when it gets to the end of the input.

    # randomness can also be accessed, using the Randomly selector, which
    # chooses an item from a list.
    # each choice is then repeated for a given number of times.
    # here lets pick some random scales, but whatever we pick, hold that choice
    # for 7 beats, which we covered in example 01.

    random_scale_choices = Randomly([
        # each of these items are scale specifications.  You've seen these in the very first examples.
        dict(scale=scale("c6 major"), beats=7),
        dict(scale=scale("Db4 minor_pentatonic"), beats=7),
        dict(scale=scale("Eb3 mixolydian"), beats=7)
    ])

    # note that the random selector could repeat a selection as currently
    # implemented and/or specified.  See ideas below.

    # note if we want a random choice to be made EVERY beat we can simplify
    # our usage of randomly like so:

    random_note_choices = Randomly("1 2 3 4 5 6 7".split())

    # what does that do?  It randomly plays one of 7 notes in the current scale.
    # that's syntactically clean, but super basic.  Let's override that with something
    # showing more options available to Randomly.

    # we're playing CHORDS now, and if we choose the "I" chord we are going to play
    # it twice in the current scale (which might change after we play the first, so this is
    # a minor lie). All within the current scale, of course.

    random_note_choices = Randomly([
        dict(value="I", hold=2),
        dict(value="IV", hold=1),
        dict(value="V", hold=1),
        dict(value="i", hold=1),
        dict(value="ii", hold=1),
        dict(value="iv:dim7", hold=1),
    ])

    # HOMEWORK: add some more scales to the random_scale_choices above and take out some
    # notes from random_note_choices.  Mix scales with notes!

    # FUTURE IDEA: also support a notion of frequency controlling what will be drawn.
    # frequencies should add up to 1.  This would still be compatible with "hold" above.

    #random_note_choices = Randomly([
    #    dict(value="I", frequency=0.4),
    #    dict(value="IV", frequency=0.2),
    #    dict(value="V", frequency=0.2),
    #    dict(value="i", frequency=0.1),
    #    dict(value="ii", frequency=0.05),
    #    dict(value="iv:dim7", frequency=0.05),
    #])

    # for more examples, see the demos labelled randomness2.py, randomness3.py, etc.
    # we want to cover some other things first, so I'm not going to go completelyinto
    # randomness now.

    source = ScaleSource(scales=random_scale_choices)
    roman = Roman(symbols=random_note_choices, channel=1)
    source.chain([roman, output])

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #41
0
def play():

    # previous examples showed a couple of instruments, lets go back to one
    # instrument to showcase just the arpeggiator.

    # WARNING - may not make sense if you haven't used any hardware or
    # software arpeggiators.

    output = Performance(bpm=120, stop_seconds=10)

    scale1 = scale("c4 major")
    scale_choices = [dict(scale=scale1, beats=7)]

    # refresher - CAMP is generator based, and performances stop when there is
    # nothing left to do OR stop_seconds is reached.
    # by not wrapping the scale choices in "Endlessly", we're allowing this example
    # to terminate when the scale is done.  This example will play 24 quarter note
    # beats and STOP.  But the way the arpeggiator is coded, there will really be
    # 24*4 = 96 sixteenth notes, of which 3/4s of them will be played with audible notes
    # and the rests will be, ahem, rests.

    # refresher - the MIDI channel number can be set anywhere in the graph, as well as overrided
    # anywhere in the graph.  Leaving it off here on ScaleSource and setting it on the
    # Arp would do exactly the same thing.  Leaving off the channel will cause an exception.

    source = ScaleSource(scales=(scale_choices), channel=1)

    # refresher - the scale follower will take note of the current scale and
    # play the scale for a given number of notes in order.  We could be more
    # creative by using Roman() instead to select particular notes (or chords)
    # in the scale.

    follower = ScaleFollower(lengths=Endlessly([7]))

    # refresher, the roman usage looks very similar:
    # roman = Roman(symbols="1 2 3 4 5 6 7".split())
    # really, there's little use for ScaleFollower in the real world, but it was
    # getting lonely and wanted to be featured here.  It's a bit more efficient
    # but I doubt that matters.

    # NOW FOR THE FUN PART.

    # ok, here's the arpeggiator.

    # in this example, we take the currently selected note from the scale
    # play that note, then the notes 4 and 9 semitones up - a major chord.
    # every single beat will be divided into 4 parts by the arp due to 'splits'
    # however every 4th note is also a REST.
    #
    # see this table:
    #
    # TRIGGER: | C4 ~~~~~~~~~~~~ | D4 ~~~~~~~~~ | ...
    # ---------+-----------------+--------------+
    # RESTS:   | N   N   N  Y    | N   N   N  Y |
    # SEMI:    | +0  +3  +8  -   | +0  +3  +8   |
    # OCTAVES: | +2  -2  0   0   | +2  -2  0  0 |
    # ---------+-----------------+--------------+
    # PLAY:    | C6  E2  G4  -   | D6  Gb2 A4 - |
    #
    # more creative things can be done by having the semitones
    # and rest patterns be different lengths, and so on, as well as using
    # the 'free' mode with those uneven lengths.

    arp = Arp(semitones=Endlessly([0, 3, 8, 0]),
              octaves=Endlessly([2, -2, 0, 0]),
              splits=Endlessly([4]),
              rests=Endlessly([0, 0, 0, 1]))

    # HOMEWORK: add "mode=free" to the Arp constructor above and experiment
    # with octaves, splits, rests, and semitones of different values and array
    # lengths.

    # POP QUIZ:  what happens if we remove Endlessly from some of the expressions above?
    # WHY?

    # the chain here is simple - scale source feeds note source, which in turn
    # feeds the arp.

    source.chain([follower, arp, output])

    # kick out the jams

    conductor = Conductor(signal=[source], performance=output)
    conductor.start()
Пример #42
0
class Scene(object):

    def __init__(self, bpm=None, scale=None, pre_fx=None, post_fx=None, patterns=None, bar_count=None):

        self.scale = scale
        self.bpm = None
        self.pre_fx = pre_fx
        self.post_fx = post_fx
        self.patterns = patterns
        self.bar_count = bar_count
        self._factory = None # set up by scenes.py
        self._scale_source = ScaleSource(scales=core_scale(self.scale))
        self._output = None
        self._players = dict()


    def to_data(self):
        result = dict(
            scale = self.scale,
            bpm = self.bpm,
            pre_fx = self.pre_fx,
            post_fx = self.post_fx,
            patterns = self.patterns,
            bar_count = self.bar_count
        )
        #if self.pre_fx:
        #    for (k,v) in self.pre_fx.items():
        #        result['pre_fx'][k] = v.to_data()
        #if self.post_fx:
        #    for (k,v) in self.post_fx.items():
        #        result['post_fx'][k] = v.to_data()
        #if self.patterns:
        #    for (k,v) in self.patterns.items():
        #        result['patterns'][k] = v.to_data()
        return result

    def build(self):

        self._build_output()
        self._build_fx_chains()
        self._build_players()
        self._build_interconnects()

    def _build_output(self):

        # FIXME: the system uses stop_seconds to cap a scene at a given number of seconds
        # but we are really more interested in beats.  We probably want to attach a new timer
        # instance to the output to make this work instead, until then stop_seconds is hard coded
        # for DEBUG only and should be removed.  This should use defaults/scene_max_bars and bars on
        # the scene object.

        if self.bpm is None:
            self.bpm = self._factory.defaults['bpm']
        self._output = Performance(bpm=self.bpm, stop_seconds = 10)

    def _build_fx_chains(self):
        for (chain_name, bus) in self._factory.fx_buses.items():
            previous = None
            nodes = bus.nodes()
            for item in nodes:
                if previous is not None:
                    previous.sends = []
                    previous.send_to(item)
                previous = item

    def _build_players(self):

        for (instrument_name, pattern_list) in self.patterns.items():

            instrument = self._factory.instruments[instrument_name]
            channel = instrument.channel
            notation = instrument.notation
            sources = []

            print("PATTERN LIST= %s" % pattern_list)
            if isinstance(pattern_list, str):
                pattern_list = [ pattern_list ]

            for pattern_name in pattern_list:

                pattern = self._factory.patterns.get(pattern_name, None)
                if pattern is None:
                    raise Exception("pattern not found: %s" % pattern_name)

                real_pattern = None

                if notation == 'roman':
                    real_pattern = Roman(symbols=pattern)
                    print("RP=%s" % pattern)
                elif notation == 'literal':
                    real_pattern = Literal(symbols=pattern)
                else:
                    raise Exception("unknown notation type for instrument: %s" % instrument_name)

                sources.append(real_pattern)

            self._players[instrument_name] = Ordered(sources=sources)

    def _stitch_fx_chain(self, assignments, instrument_name, from_node, to_node):

        # SHOULD BE REMOVABLE
        #if assignments is None or instrument_name not in assignments:
        #    return

        fx_chain_name = assignments[instrument_name]
        if fx_chain_name not in self._factory.fx_buses:
            # FIXME: typed exceptions everywhere to make it easier for higher level apps
            raise Exception("fx bus not found: %s" % fx_chain_name)

        fx_chain = self._factory.fx_buses[fx_chain_name].nodes()

        # FIXME: BOOKMARK: I think need to implement COPY methods here as reuse of the same chain may cause
        # some interestingness... maybe.  Nodes should return copies of the objects (?)

        head = fx_chain[0]
        tail = fx_chain[-1]
        print("FROM %s to %s" % (from_node, head))
        print("AND FROM %s to %s" % (tail, to_node))
        from_node.send_to(head)
        tail.send_to(to_node)

    def _build_interconnects(self):

        for (instrument_name, player) in self._players.items():
            # FIXME: all of this stuff should use python standard logging
            print("---")
            print("CONFIGURING INSTRUMENT CHAIN: %s" % instrument_name)
            print(dir(player))


            player = self._players[instrument_name]
            #import pdb; pdb.set_trace()

            # TODO: consider whether it makes sense for a FxBus to connect to another FxBus
            # ignoring for now.

            if self.pre_fx is None or instrument_name not in self.pre_fx:
                # connect directly to source
                print("PRE DIRECT CONNECT")
                self._scale_source.send_to(self._players[instrument_name])
            else:
                # ensure prefx is coupled to source and tail is coupled to output
                print("PRE CONNECT")
                self._stitch_fx_chain(self.pre_fx, instrument_name, self._scale_source, player)

            instrument = self._factory.instruments[instrument_name]
            channel_assign = Channel(channel=instrument.channel)
            player.send_to(channel_assign)

            if self.post_fx is None or instrument_name not in self.post_fx:
                # connect directly to output
                print("POST DIRECT CONNECT")
                channel_assign.send_to(self._output)
            else:
                # ensure player is coupled to head of post fx and tail is coupled to output
                print("POST CONNECT")
                self._stitch_fx_chain(self.post_fx, instrument_name, channel_assign, self._output)

    def get_signals(self):
        return [ self._scale_source ]

    def get_output(self):
        return self._output