Beispiel #1
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)
Beispiel #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)
    properties1 = {
        # 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),
    }
    properties2 = {
        # convert from (reversed) note names to midi numbers
        PP.NOTE:
        Pseq(n.convert2(notes[::-1])),
        # 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),
    }

    p1 = Phrase(properties1)
    p2 = Phrase(properties2)
    p2m = Pat2Midi()
    p2m.set_tempo(120)
    total_dur = p2m.add_phrases([p1, p2], start_time=1)
    print(total_dur)
    p2m.write(outputfile)
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)
Beispiel #4
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)
Beispiel #5
0
    def phrase_for_section(self, section_id):
        """

        :param section_id: integer
        :return: expremigen Phrase for section
        """
        return Phrase(self.phrase_properties_for_section(section_id))
Beispiel #6
0
 def test_defaults(self):
     n = Note2Midi()
     p = Phrase()
     result = []
     for event in p:
         result.append(event)
     self.assertEqual(len(result), 1)
     self.assertEqual(result[0][PP.NOTE], n.lookup(Defaults.note))
     self.assertEqual(result[0][PP.VOL], Defaults.vol)
     self.assertEqual(result[0][PP.DUR], 4 * Defaults.dur)
     self.assertEqual(result[0][PP.PLAYEDDUR], Defaults.playeddur)
     self.assertEqual(result[0][PP.LAG], Defaults.lag)
     self.assertEqual(result[0][PP.TEMPO], Defaults.tempo)
 def __call__(self,
              kind=None,
              nanonotation=None,
              volumes=None,
              last_note_is_final=False):
     notes = self.nano.notes(nanonotation)
     durations = self.nano.dur(nanonotation)
     return Phrase({
         PP.NOTE: self.note(notes),
         PP.VOL: self.volume(notes, volumes, None, None),
         PP.PLAYEDDUR: self.playeddur(notes, kind),
         PP.DUR: self.dur(durations),
         PP.LAG: self.lag(notes, last_note_is_final)
     })
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
Beispiel #9
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)
Beispiel #10
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)
Beispiel #11
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"))
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
Beispiel #13
0
    def add_phrase(self, phrase: Phrase, track=0, channel=0, start_time=0):
        """

        :param phrase: a Phrase containing patterns and animations
        :param track: default: 0
        :param channel: default: 0
        :param start_time: time at which the phrase should be inserted default: 0
        :return: total duration of the inserted phrase
        """
        for event in phrase:
            # set tempo events only if they changed since last time
            # handle note events
            if PP.NOTE in event:
                if event[PP.TEMPO] != self.last_set_tempo[track]:
                    self.midiFile.addTempo(
                        track, start_time + phrase.generated_duration(),
                        event[PP.TEMPO])
                    self.last_set_tempo[track] = event[PP.TEMPO]
                # set notes always
                if isinstance(event[PP.NOTE], Pchord):
                    for n in event[PP.NOTE].notes:
                        try:
                            intnote = int(n)
                        except ValueError:
                            intnote = self.note2midi.lookup(n)
                            if intnote == REST:
                                continue

                        self.midiFile.addNote(
                            track=track,
                            channel=channel,
                            pitch=intnote,
                            time=start_time + phrase.generated_duration() +
                            event[PP.LAG],
                            duration=event[PP.DUR] * event[PP.PLAYEDDUR],
                            volume=int(event[PP.VOL]),
                            annotation=None)

                else:

                    try:
                        intnote = int(event[PP.NOTE])
                    except ValueError:
                        intnote = self.note2midi.lookup(event[PP.NOTE])
                        if intnote == REST:
                            continue

                    self.midiFile.addNote(
                        track=track,
                        channel=channel,
                        pitch=intnote,
                        time=start_time + phrase.generated_duration() +
                        event[PP.LAG],
                        duration=event[PP.DUR] * event[PP.PLAYEDDUR],
                        volume=int(event[PP.VOL]),
                        annotation=None)

                self.handle_control_changes(channel, event, phrase, start_time,
                                            track)

            # handle controller events (only if they changed since last time)
            else:
                self.handle_control_changes(channel, event, phrase, start_time,
                                            track)

        return phrase.generated_duration()