Ejemplo n.º 1
0
def create_phrase():
    n = Note2Midi()
    notes = ["c4", "e4", "g4", "c5", "b4", "g4", "f4", "d4", "c4"]
    from vectortween.NumberAnimation import NumberAnimation
    from vectortween.SequentialAnimation import SequentialAnimation
    increase = NumberAnimation(frm=Dyn.mp, to=Dyn.f)
    decrease = NumberAnimation(frm=Dyn.f, to=Dyn.ppp)
    swell_dim = SequentialAnimation([increase, decrease])
    increasing_staccato = NumberAnimation(frm=1, to=0.5)
    properties = {
        # convert from note names to midi numbers
        PP.NOTE: Pseq(n.convert2(notes)),
        # last note is longer than the rest
        PP.DUR: Pseq([Pconst(Dur.eighth, len(notes) - 1), Pconst(Dur.whole, 1)]),
        # animate staccato
        PP.PLAYEDDUR: Ptween(increasing_staccato, 0, 0, len(notes), len(notes)),
        # volume should linearly go up from mp to f, then go down from f to ppp as the phrase progresses
        PP.VOL: Ptween(swell_dim, 0, 0, len(notes), len(notes), None),
    }
    p = Phrase(properties)
    p2m = Pat2Midi()
    p2m.set_tempo(120)
    total_dur = p2m.add_phrase(p)
    print(total_dur)
    p2m.write(outputfile)
Ejemplo n.º 2
0
def create_phrase():
    p = Pat2Midi()
    n = Note2Midi()

    # vary the lag to create the rubato feeling
    lag_inc = NumberAnimation(frm=0, to=0.3, tween=['easeOutQuad'])
    lag_dec = NumberAnimation(frm=0.3, to=0, tween=['easeInOutCubic'])
    lag = SequentialAnimation([lag_inc, lag_dec], [1, 3], 2)

    # vary the volume over time to keep it interesting
    vol_inc1 = NumberAnimation(frm=Dyn.f, to=Dyn.ff, tween=['linear'])
    vol_dec1 = NumberAnimation(frm=Dyn.ff, to=Dyn.mf, tween=['linear'])

    vol_inc2 = NumberAnimation(frm=Dyn.mf, to=Dyn.f, tween=['linear'])
    vol_dec2 = NumberAnimation(frm=Dyn.f, to=Dyn.mp, tween=['linear'])

    vol_inc3 = NumberAnimation(frm=Dyn.mp, to=Dyn.mf, tween=['linear'])
    vol_dec3 = NumberAnimation(frm=Dyn.mf, to=Dyn.pp, tween=['linear'])
    vol = SequentialAnimation([vol_inc1, vol_dec1, vol_inc2, vol_dec2, vol_inc3, vol_dec3])

    # and why not bounce a bit between legato and staccato while we're having fun?
    legato_to_staccato = NumberAnimation(frm=1, to=0.25, tween=['easeOutBounce'])
    staccato_to_legato = NumberAnimation(frm=0.1, to=1, tween=['easeOutBounce'])
    dur = SequentialAnimation([legato_to_staccato, staccato_to_legato])

    # animate the tempo
    tempo_slowdown = NumberAnimation(frm=120, to=80, tween=['easeOutQuad'])

    # play some random cadenza
    notes = n.convert2(
        "a5 b5 c6 a5 e5 d5 c5 d5 e5 c5 a4 g#4 a4 b4 c5 a4 e4 d4 c4 d4 e4 c4 a3 g#3 a3 b3 c4 d4 e4 g#4 a4".split(" "))
    notes2 = n.convert2(
        "d4 e4 f4 d4 a3 g3 f3 g3 a3 b3 c4 d4 c4 d4 e4 c4 g3 f3 e3 f3 g3 a3 b3 c4 a3 b3 c4 d4 e4 g#4 a4".split(" "))
    notes.extend(notes2)

    properties_plain = {
        PP.NOTE: Pseq(notes, 1),
        PP.VOL: Pconst(100),
        PP.PLAYEDDUR: Pconst(0.95),
        PP.DUR: Pseq([Pconst(Dur.sixteenth_triplet, len(notes2) - 1), Pconst(Dur.half, 1)], 2),
        PP.LAG: Pconst(0),
        PP.TEMPO: Pconst(120)
    }
    properties_rubato = {
        PP.NOTE: Pseq(notes, 1),
        PP.VOL: Ptween(vol, 0, 0, len(notes), len(notes), None),
        PP.PLAYEDDUR: Ptween(dur, 0, 0, len(notes), len(notes), None),
        PP.DUR: Pseq([Pconst(Dur.sixteenth_triplet, len(notes2) - 1), Pconst(Dur.half, 1)], 2),
        PP.LAG: Ptween(lag, 0, 0, len(notes), len(notes), None),
        PP.TEMPO: Ptween(tempo_slowdown, 0, 0, len(notes), len(notes), None)
    }

    ph = Phrase(properties_plain)
    ph2 = Phrase(properties_rubato)
    p.add_phrases([ph, ph2], 0, 0, 0)

    p.write(outputfile)
Ejemplo n.º 3
0
 def volume(cls,
            notes,
            volumes=None,
            individual_tween=None,
            overall_tween=None):
     """
     :param notes: list of notes that make up the phrase
     :param volumes: a list of volumes to evolve to over the course of the phrase, e.g. [Dyn.mp, Dyn.mf, Dyn.ppp]
     :param individual_tween: per segment tween
     :param overall_tween: tween over all segments
     :return: pattern that tweens between the successive volumes
     """
     if volumes is None:
         volumes = [Dyn.mf, Dyn.mf]
     if overall_tween is None:
         overall_tween = ['linear']
     if individual_tween is None:
         individual_tween = ['linear']
     if len(volumes) == 1:
         volumes = [volumes[0], volumes[0]]
     anims = []
     for v in pairwise(volumes):
         anims.append(
             NumberAnimation(frm=v[0], to=v[1], tween=individual_tween))
     s = SequentialAnimation(anims, tween=overall_tween)
     return Ptween(s, 0, 0, len(notes), len(notes))
Ejemplo n.º 4
0
def create_phrase():
    n = Note2Midi()
    a = NumberAnimation(frm=0, to=8000, tween=['easeOutElastic', 1, 0.02])
    b = NumberAnimation(frm=8000, to=0, tween=['easeOutElastic', 1, 0.02])
    c = NumberAnimation(frm=0, to=-8000, tween=['easeOutBounce', 0.1, 0.02])
    d = NumberAnimation(frm=-8000, to=0, tween=['easeOutBounce', 0.1, 0.02])
    s = SequentialAnimation([a, b, c, d], repeats=10)
    properties = {
        PP.NOTE:
        n.convert2(Pconst("a4", 1)),
        PP.DUR:
        Pconst(Dur.whole * 16, 1),  # single note for 16 beats
        PP.PLAYEDDUR:
        Pconst(1),
        PP.ctrl_dur_key(MCC.PitchWheel):
        Pconst(0.03125, int((1 / 0.03125) * Dur.whole * 16)),
        PP.ctrl_val_key(MCC.PitchWheel):
        Ptween(s, 0, 0,
               int((1 / 0.03125) * Dur.whole * 16) - 1,
               int((1 / 0.03125) * Dur.whole * 16) - 1, None)
    }
    p = Phrase(properties)
    p2m = Pat2Midi()
    p2m.add_phrase(p, track=0, channel=0, start_time=0)
    p2m.write(outputfile)
Ejemplo n.º 5
0
    def cc_properties_generators_for_section(self, section_id):
        """

        :param section_id: integer
        :return: a python dictionary: for every control change id encountered, returns a generator generating all
                 control changes in this section
        """
        cc_properties = self.cc_properties_for_section(section_id)
        patterns = defaultdict(lambda: defaultdict(list))
        for cc in cc_properties:
            note_durations = self.duration_generator_for_section(section_id)
            for segment in cc_properties[cc]:
                frm = segment[0]
                to = segment[1]
                durkey = PP.ctrl_dur_key(cc)
                valkey = PP.ctrl_val_key(cc)
                if segment[0] is None:
                    no_of_notes = int(segment[2])
                    dur = sum(take(no_of_notes, note_durations))
                    patterns[cc][durkey].append(Pconst(dur, 1))
                    patterns[cc][valkey].append(Pconst(None, 1))
                else:
                    no_of_notes = int(segment[2])
                    dur = sum(take(no_of_notes, note_durations))
                    if frm[1] == "anim":
                        n = NumberAnimation(frm=int(frm[2]), to=int(to[2]))
                        patterns[cc][durkey].append(Pconst(0.1 * dur / no_of_notes, int(no_of_notes / 0.1)))
                        patterns[cc][valkey].append(Ptween(n, 0, 0, int(no_of_notes / 0.1), int(no_of_notes / 0.1)))
                    elif frm[1] == "static":
                        patterns[cc][durkey].append(Pconst(dur, 1))
                        patterns[cc][valkey].append(Pconst(int(frm[2]), 1))
                    else:
                        raise ValidationException(f"Fatal Error. Unknown animation type {frm}")
        return patterns
Ejemplo n.º 6
0
    def property_generator_for_section(self, section_id, symvalue_from_string_fn, property_from_notespec_fn,
                                       default_value):
        """

        :param section_id: integer
        :param symvalue_from_string_fn: function that maps a symbolic specification into a number (e.g. ff => 100)
        :param property_from_notespec_fn: function that extracts a given property from a parsed notespec
        :param default_value: value that tracks the default value (may update dynamically, e.g. to track last used
                              octave)
        :return: returns a python generator generating all values for the given property
        """
        dynamics = self.property_for_section(section_id, property_from_notespec_fn, default_value)
        patterns = []
        for d in dynamics:
            frm_dyn = d[0]
            to_dyn = d[1]
            distance = d[2]
            try:
                tweenoptions = d[0][3]
            except IndexError:
                tweenoptions = ['linear']
            if distance:
                from_value_type = frm_dyn[0]
                if from_value_type == 'sym':
                    from_value = symvalue_from_string_fn(frm_dyn[2])
                else:
                    from_value = frm_dyn[2]
                to_value_type = to_dyn[0]
                if to_value_type == 'sym':
                    to_value = symvalue_from_string_fn(to_dyn[2])
                else:
                    to_value = to_dyn[2]
                animation_type = frm_dyn[1]
                if animation_type == 'anim':
                    n = Ptween(NumberAnimation(frm=from_value, to=to_value, tween=tweenoptions), 0, 0, distance,
                               distance,
                               None)
                elif animation_type == 'static':
                    n = Ptween(NumberAnimation(frm=from_value, to=from_value, tween=['linear']), 0, 0, distance,
                               distance, None)
                else:
                    print(animation_type)
                    assert False
                patterns.append(n)
        return Pseq(patterns, 1)
Ejemplo n.º 7
0
 def test_phrase2(self):
     n = Note2Midi()
     notes = ["c4", "e4", "g4", "c5", "b4", "g4", "f4", "d4", "c4"]
     from vectortween.NumberAnimation import NumberAnimation
     from vectortween.SequentialAnimation import SequentialAnimation
     increase = NumberAnimation(frm=Dyn.mp, to=Dyn.f)
     decrease = NumberAnimation(frm=Dyn.f, to=Dyn.ppp)
     swell_dim = SequentialAnimation([increase, decrease])
     increasing_staccato = NumberAnimation(frm=1, to=0.8)
     properties = {
         # convert from note names to midi numbers
         PP.NOTE:
         Pseq(n.convert2(notes)),
         # last note is longer than the rest
         PP.DUR:
         Pseq([Pconst(Dur.quarter,
                      len(notes) - 1),
               Pconst(Dur.whole, 1)]),
         # animate staccato
         PP.PLAYEDDUR:
         Ptween(increasing_staccato, 0, 0, len(notes), len(notes)),
         # volume should linearly go up from mp to f, then go down from f to ppp as the phrase progresses
         PP.VOL:
         Ptween(swell_dim, 0, 0, len(notes), len(notes), None),
     }
     p = Phrase(properties)
     result = []
     for event in p:
         result.append(event)
     self.assertEqual(len(result), 9)
     # check that last note longer
     self.assertEqual(result[7][PP.DUR], 4 * 1 / 4)
     self.assertEqual(result[8][PP.DUR], 4 * 1)
     # check that volume increases then decreases
     self.assertLess(result[0][PP.VOL], result[4][PP.VOL])
     self.assertLess(result[8][PP.VOL], result[4][PP.VOL])
     self.assertLess(result[8][PP.VOL], result[0][PP.VOL])
     # check that staccato increases
     for i in range(8):
         self.assertTrue(
             result[i][PP.PLAYEDDUR] > result[i + 1][PP.PLAYEDDUR])
     self.assertEqual(result[8][PP.NOTE], n.lookup("c4"))
Ejemplo n.º 8
0
def add_chords(pat2mid, track, channel):
    n = Note2Midi()
    notes = [C(["c3", "e3", "g3"]), C(["b2", "d3", "g3"]), C(["c3", "e3", "g3", "c4"])]
    from vectortween.NumberAnimation import NumberAnimation
    decrease = NumberAnimation(frm=Dyn.f, to=Dyn.p)
    properties = {
        PP.NOTE: Pseq(n.convert2(notes)),
        PP.DUR: Pseq([Pconst(Dur.whole, 2), Pconst(Dur.doublewhole, 1)]),
        PP.PLAYEDDUR: Pconst(1),
        PP.VOL: Ptween(decrease, 0, 0, len(notes), len(notes), None)
    }
    p = Phrase(properties)
    pat2mid.add_phrase(p, track=track, channel=channel, start_time=0)
    return pat2mid
Ejemplo n.º 9
0
def add_melody(pat2mid, track, channel):
    n = Note2Midi()
    notes = ["c4", "e4", "g4", "c5", "b4", "g4", "f4", "d4", "c4"]
    from vectortween.NumberAnimation import NumberAnimation
    from vectortween.SequentialAnimation import SequentialAnimation
    increase = NumberAnimation(frm=Dyn.mp, to=Dyn.f)
    decrease = NumberAnimation(frm=Dyn.f, to=Dyn.ppp)
    swell_dim = SequentialAnimation([increase, decrease])
    increasing_staccato = NumberAnimation(frm=1, to=0.5)
    properties = {
        # convert from note names to midi numbers
        PP.NOTE: Pseq(n.convert2(notes)),
        # last note is longer than the rest
        PP.DUR: Pseq([Pconst(Dur.quarter, len(notes) - 1), Pconst(Dur.whole, 1)]),
        # animate staccato
        PP.PLAYEDDUR: Ptween(increasing_staccato, 0, 0, len(notes), len(notes)),
        # volume should linearly go up from mp to f, then go down from f to ppp as the phrase progresses
        PP.VOL: Ptween(swell_dim, 0, 0, len(notes), len(notes), None),
    }
    p = Phrase(properties)
    pat2mid.set_tempo(60)
    pat2mid.add_phrase(p, track=track, channel=channel, start_time=0)
    return pat2mid
Ejemplo n.º 10
0
 def test_normal(self):
     n = NumberAnimation(frm=60, to=90, tween=['linear'])
     a = [i for i in Ptween(n, 0, 0, 10, 10, None)]
     self.assertEqual(a, [60, 63, 66, 69, 72, 75, 78, 81, 84, 87])
Ejemplo n.º 11
0
 def test_repr(self):
     n = NumberAnimation(frm=60, to=90, tween=['linear'])
     self.assertEqual("{0}".format(Ptween(n, 0, 0, 10, 10)),
                      "Ptween(<anim>, 0, 0, 10, 10, None)")