示例#1
0
 def test_cc(self):
     properties = {
         PP.NOTE:
         Pconst(67, 5),
         PP.DUR:
         Pconst(1 / 2, 5),
         "D35":
         Pconst(1 / 4, 10),
         "V35":
         Pseq([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),
         "D34":
         Pconst(1 / 8, 20),
         "V34":
         Pseq([
             1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
             19, 20
         ], 20)
     }
     p = Phrase(properties)
     result = []
     for event in p:
         result.append(event)
     self.assertEqual(len(result), 5 + 10 + 20)
     self.assertEqual(result[-2]["V35"], 9)
     self.assertEqual(result[-2]["D35"], 4 * 1 / 4)
     self.assertEqual(result[-12]["V34"], 19)
     self.assertEqual(result[-12]["D34"], 4 * 1 / 8)
示例#2
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)
示例#3
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
示例#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)
 def lag(cls, notes, last_note_is_endnote=False):
     """
     :param last_note_is_endnote:
     :param notes: list of notes that make up the phrase
     :return: pattern that generates the desired lag
     """
     if last_note_is_endnote:
         return Pseq([Pconst(0, len(notes) - 1), Pconst(0.5, 1)], repeats=1)
     else:
         return Pconst(0, len(notes))
示例#6
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
示例#7
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)
示例#8
0
 def test_phrase(self):
     n = Note2Midi()
     properties = {
         PP.NOTE: Pseries(n.lookup("c4"), 1, 12),
         PP.VOL: Pconst(100, sys.maxsize),
         PP.DUR: Pconst(1 / 16, sys.maxsize),
         PP.PLAYEDDUR: Pconst(0.9, sys.maxsize),
         PP.LAG: Pconst(0, sys.maxsize)
     }
     p = Phrase(properties)
     result = []
     for event in p:
         result.append(event)
     self.assertEqual(len(result), 12)
     self.assertEqual(result[1][PP.NOTE], n.lookup("c#4"))
     self.assertEqual(result[5][PP.VOL], 100)
     self.assertEqual(result[9][PP.DUR], 4 * 0.0625)
示例#9
0
 def test_addPhrase(self):
     n = Note2Midi()
     properties = {
         PP.NOTE: Pconst(n.lookup("f#3"), 3),
         PP.VOL: Pconst(Dyn.mf),
         PP.DUR: Pconst(Dur.quarter),
         PP.PLAYEDDUR: Pconst(0.9),
         PP.LAG: Pconst(0)
     }
     p = Phrase(properties)
     p2m = Pat2Midi()
     duration = p2m.add_phrase(p)
     self.assertEqual(duration, 3 * 4 * Dur.quarter)
     duration2 = p2m.add_phrase(p, start_time=duration)
     # just adding a single phrase returns the duration of that phrase only
     self.assertEqual(duration, duration2)
     # adding a list of phrases returns the total duration
     total_duration = p2m.add_phrases([p], start_time=duration + duration2)
     self.assertEqual(total_duration, 3 * duration)
示例#10
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"))
示例#11
0
 def playeddur(cls, notes, kind="l2s"):
     """
     :param notes: list of notes that make up the phrase
     :param kind: one of "l2s" (legato-to-staccato) or "s2l" (staccato-to-legato)
     :return: pattern that generates the desired playeddur values
     """
     if kind == "l2s":
         anim = Pseq([
             Pconst(PDur.legato,
                    len(notes) - 1),
             Pconst(PDur.staccato, 1)
         ], 1)
     elif kind == "s2l":
         anim = Pseq([
             Pconst(PDur.staccato,
                    len(notes) - 1),
             Pconst(PDur.legato, 1)
         ], 1)
     elif kind == "s2s":
         anim = Pconst(PDur.staccato, len(notes))
     elif kind == "l2l":
         anim = Pconst(PDur.legato, len(notes))
     else:
         anim = None
         assert False
     return anim
示例#12
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
示例#13
0
    def __init__(self, properties: dict = None):
        self.n2m = Note2Midi()
        if properties is None:
            properties = {}
        self.p = properties
        if PP.NOTE not in self.p:
            self.p[PP.NOTE] = Pconst(self.n2m.lookup(Defaults.note), 1)
        if PP.DUR not in self.p:
            self.p[PP.DUR] = Pconst(Defaults.dur)
        if PP.LAG not in self.p:
            self.p[PP.LAG] = Pconst(Defaults.lag)
        if PP.PLAYEDDUR not in self.p:
            self.p[PP.PLAYEDDUR] = Pconst(Defaults.playeddur)
        if PP.VOL not in self.p:
            self.p[PP.VOL] = Pconst(Defaults.vol)
        if PP.TEMPO not in self.p:
            self.p[PP.TEMPO] = Pconst(Defaults.tempo)

        self.note_time = 0
        self.ctrl_time = [0 for _ in range(NO_OF_CONTROLLERS)]
示例#14
0
 def test_secondempty(self):
     a = [i for i in Padd(Pconst(4, 3), Pseq([1, 2, 3, 70], 0))]
     self.assertEqual(a, [])
示例#15
0
 def test_nesting(self):
     f = [i for i in Pseq([Pseq([1, Pconst(2, 2)], 2), Pseq([3, 4], 2)], 2)]
     self.assertEqual(f, [1, 2, 2, 1, 2, 2, 3, 4, 3, 4, 1, 2, 2, 1, 2, 2, 3, 4, 3, 4])
示例#16
0
 def test_withchord(self):
     f = [i for i in Pseq([Pseq([1, Pconst(2, 2)], 2), Pseq(Pchord([3, 4]), 2)], 2)]
     self.assertEqual(f, [1, 2, 2, 1, 2, 2, Pchord([3, 4]), Pchord([3, 4]), 1, 2, 2, 1, 2, 2, Pchord([3, 4]),
                          Pchord([3, 4])])
示例#17
0
 def test_secondlonger(self):
     a = [i for i in Padd(Pconst(4, 3), Pseq([1, 2, 3, 70], 1))]
     self.assertEqual(a, [5, 6, 7])
示例#18
0
 def test_firstlonger(self):
     a = [i for i in Padd(Pconst(4, 5), Pseq([1, 2, 3], 1))]
     self.assertEqual(a, [5, 6, 7])
示例#19
0
 def test_nesting(self):
     a = [
         i for i in Padd(Padd(Pseq([1, 2], 2), Pconst(10, 3)),
                         Pseq([4, 5], 2))
     ]
     self.assertEqual(a, [15, 17, 15])
示例#20
0
 def test_normal(self):
     a = [i for i in Padd(Pconst(4, 3), Pseq([1, 2, 3], 1))]
     self.assertEqual(a, [5, 6, 7])
示例#21
0
 def test_repr(self):
     tested = "{0}".format(Padd(Pconst(4, 5), Pseq([1, 2, 3], 1)))
     expected = "Padd(Pconst(4, 5), Pseq([1, 2, 3], 1))"
     self.assertEqual(tested, expected)
示例#22
0
 def test_leftlazy(self):
     a = [i for i in Padd(Pconst(4, int(5e8)), Pseq([1, 2, 3, 70], 2))]
     self.assertEqual(a, [5, 6, 7, 74, 5, 6, 7, 74])
示例#23
0
 def test_rightlazy(self):
     a = [i for i in Padd(Pconst(4, 3), Pseq([1, 2, 3, 70], int(5e5)))]
     self.assertEqual(a, [5, 6, 7])
示例#24
0
 def test_repr(self):
     self.assertEqual("{0}".format(Pseq([1, -1, Pconst(2, 2)], 3)), "Pseq([1, -1, Pconst(2, 2)], 3)")
示例#25
0
 def test_firstempty(self):
     a = [i for i in Padd(Pconst(4, 0), Pseq([1, 2, 3, 70], 1))]
     self.assertEqual(a, [])