Exemple #1
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()
Exemple #2
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()
Exemple #3
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()
Exemple #4
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()
Exemple #5
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()
Exemple #6
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()
Exemple #7
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()
Exemple #8
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()
Exemple #9
0
def play():

    # We are building a house of fire, baby.

    song = SongFactory(name='Foo', author='Your Name')

    song.set_defaults(bpm=120, scene_bar_count=8)

    song.set_instruments(
        strings=Instrument(channel=1),
        lead=Instrument(channel=2),
    )

    song.set_patterns(
        typ='basic',
        patterns=dict(
            some_jam_pt1=
            "4 6 1 6 | 4 4 4 4 | 6 6 4 1 | 1 4 6 4 | 6 4 4 4 | 4 6 4 6",
            some_jam_pt2=
            "1 2 3 4 | 3 2 5 1 | 1 1 7 6 | 5 4 3 2 | 1 2 3 4 | 5 6 7 1",
        ))

    song.set_patterns(
        typ='random',
        mode='probability',
        patterns=dict(
            # chordify_chance_pt = [ 0, 0.5 ]
        ))

    song.set_patterns(typ='random',
                      mode='exhaust',
                      patterns=dict(serialism="1 2 3 4 5 6 7 8 9 10 11 12"))

    song.set_patterns(
        typ='random',
        mode='choice',
        patterns=dict(
            # random_pt1 = "1 2 3 4 5 6 7",
            # implies we want a new kind of generator below...
            # velocity_pt1 = [ 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110 ]
        ))

    song.set_patterns(
        typ='random',
        mode='probability',
        patterns=dict(
            # chordify_chance_pt1 = [ 0, 0.5, 0.25, 0.125 ]
        ))

    song.set_patterns(
        typ='endless',
        patterns=dict(
            occasional_holes=[1, 0, 1, 1, 0, 0],
            chord_sequence=['major', 'minor', 'power'],
            subdivide_arp=[3],
            subdivide_lots=[2],
            transpose_pt1=[2, 0, -2],
            # duration_pt1 = [ 0.25, 0.25, 0.125, 0.125 ],
            # chordify_pt1 = [ "major", "major", "minor", "major", "pow", "aug"],
            basic_chords="I IV V I",
            boring_part="1",
            transpose_arp=[0, 4, 5],
            down_two_up_two=[-2, 2]))

    # --- FX ---
    song.set_fx_buses(
        chordify_lead=FxBus([Chordify(types=song.pattern('chord_sequence'))]),
        arpeggiate_lead=FxBus([
            Arp(semitones=song.pattern('transpose_arp'),
                splits=song.pattern('subdivide_arp'),
                octaves=song.pattern('transpose_pt1'),
                mode='locked')
        ]),
        some_silence_and_vamp_but_transpose_down=FxBus(
            [Transpose(octaves=song.pattern('down_two_up_two'))]),
        subdivide=FxBus([
            # FIXME: Permit seems to not work.  Figure out why.
            Permit(when=song.pattern('occasional_holes')),
            Subdivide(splits=song.pattern('subdivide_lots')),
        ]))

    song.set_scenes(
        # BOOKMARK: FIXME: bar count is not yet implemented as of time of writing, need a camp.band.members.stop or something to implement.  Easy though.
        overture=Scene(
            scale="C4 chromatic",
            bar_count=12,
            # pre_fx = dict(strings='random_velocity_and_duration'),
            post_fx=dict(strings='chordify_lead'),
            patterns=dict(strings='serialism')),
        llama_theme=Scene(
            scale="C5 minor",
            bar_count=12,
            # pre_fx = dict(lead='subdivide'),
            # post_fx = dict(strings = 'arpeggiate_strings', lead = 'transpose_lead'),
            post_fx=dict(strings='arpeggiate_lead',
                         lead='some_silence_and_vamp_but_transpose_down'),
            patterns=dict(strings='boring_part',
                          lead=[
                              'some_jam_pt1', 'some_jam_pt2', 'some_jam_pt1',
                              'some_jam_pt2'
                          ])))

    # -- GO! --

    # scene_names = ['overture', 'llama_theme', 'bridge', 'chorus', 'verse', 'chorus', 'verse', 'ending']
    # scene_names = ['overture', 'llama_theme' ]
    scene_names = ['llama_theme']

    song.play(scene_names)

    print(song.to_json())