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 test_ccpropertiesgeneratorsforsection(self):
        m = Mispel()
        m.parse(r"""
        with track 0: a3\pdur[legato]\cc[15,100] b <c\cc{16,23} d4> e\cc[15,90] f a g\cc[16,40] b
        """)
        p = m.cc_properties_generators_for_section(0)

        dur15 = [d for d in Pseq(p[15][PP.ctrl_dur_key(15)], 1)]
        val15 = [v for v in Pseq(p[15][PP.ctrl_val_key(15)], 1)]

        dur16 = [d for d in Pseq(p[16][PP.ctrl_dur_key(16)], 1)]
        val16 = [v for v in Pseq(p[16][PP.ctrl_val_key(16)], 1)]

        self.assertListEqual(dur15, [0, 0.75, 1.25])
        self.assertListEqual(val15, [None, 100, 90])

        self.assertListEqual(dur16, [
            0.5, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025,
            0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025,
            0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025,
            0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, 0.025,
            0.025, 0.025, 0.025, 0.025, 0.5
        ])
        self.assertListEqual(val16, [
            None, 23.0, 23.425, 23.85, 24.275, 24.7, 25.125, 25.55, 25.975,
            26.4, 26.825, 27.25, 27.675, 28.1, 28.525, 28.95, 29.375, 29.8,
            30.225, 30.65, 31.075, 31.5, 31.925, 32.35, 32.775, 33.2, 33.625,
            34.05, 34.475, 34.9, 35.325, 35.75, 36.175, 36.6, 37.025, 37.45,
            37.875, 38.3, 38.725, 39.15, 39.575, 40
        ])
Ejemplo n.º 3
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)
Ejemplo n.º 4
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
Ejemplo n.º 5
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.º 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
Ejemplo n.º 7
0
    def duration_generator_for_section(self, section_id):
        """

        :param section_id: integer
        :return: an expremigen pattern generating all durations in this section
        """
        return Pseq(self.durations_for_section(section_id), 1)
Ejemplo n.º 8
0
    def note_generator_for_section(self, section_id):
        """

        :param section_id: integer
        :return: expremigen pattern generating all notes in this section
        """
        return Pseq(self.notes_for_section(section_id), 1)
Ejemplo n.º 9
0
def perform_cell(input_string,
                 repeats,
                 max_duration,
                 parts,
                 instrument_name,
                 key,
                 check_range=False):
    total_duration = 0
    n = NanoNotation()
    note_pattern = Pseq(n.midinumbers(input_string), repeats)
    dur_pattern = Pseq(n.dur(input_string), repeats)
    for n, d in zip(note_pattern, dur_pattern):
        if total_duration < max_duration:
            prop = {}
            if random.randint(0, 10) > 7:
                accent = 1.0
                prop["articulations"] = "accent"
            else:
                accent = 0.6

            duration = dur_to_beat(d)
            if total_duration + duration > max_duration:
                duration = max_duration - total_duration  #  cut off the rhythm to remain inside measure

            if key:
                prop["key"] = key

            if check_range and not check_range(instrument_name, n):
                print(
                    f"Warning: instrument {instrument_name} goes out of range with note {n}"
                )

            if n == REST:
                scamp.wait(duration)
            else:
                parts[instrument_name].play_note(
                    n,
                    0.7 * accent,
                    duration,
                    properties=prop if prop else None)
            total_duration += duration

        else:
            return
Ejemplo n.º 10
0
 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))
Ejemplo n.º 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"))
Ejemplo n.º 12
0
    def phrase_properties_for_section(self, section_id):
        """

        :param section_id: 0
        :return: returns a collection of phrase properties for given section
        """
        pp = {
            PP.NOTE: self.note_generator_for_section(section_id),
            PP.VOL: self.dynamics_generator_for_section(section_id),
            PP.DUR: self.duration_generator_for_section(section_id),
            PP.PLAYEDDUR: self.pdur_generator_for_section(section_id),
            PP.LAG: self.lag_generator_for_section(section_id),
            PP.TEMPO: self.tempo_generator_for_section(section_id)
        }

        ccs = self.cc_properties_generators_for_section(section_id)
        for key in ccs:
            pp[PP.ctrl_dur_key(key)] = Pseq(ccs[key][PP.ctrl_dur_key(key)], 1)
            pp[PP.ctrl_val_key(key)] = Pseq(ccs[key][PP.ctrl_val_key(key)], 1)

        return pp
Ejemplo n.º 13
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.º 14
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.º 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])
Ejemplo n.º 16
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])
Ejemplo n.º 17
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])
Ejemplo n.º 18
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)
Ejemplo n.º 19
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])
Ejemplo n.º 20
0
 def test_normal(self):
     a = [i for i in Pseq([4, 5, 6], 2)]
     self.assertEqual(a, [4, 5, 6] * 2)
Ejemplo n.º 21
0
 def test_secondempty(self):
     a = [i for i in Padd(Pconst(4, 3), Pseq([1, 2, 3, 70], 0))]
     self.assertEqual(a, [])
Ejemplo n.º 22
0
 def dur(cls, durations):
     return Pseq(durations, repeats=1)
Ejemplo n.º 23
0
 def test_defaultvalue(self):
     e = [i for i in Pseq(repeats=2)]
     self.assertEqual(e, [])
Ejemplo n.º 24
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])])
Ejemplo n.º 25
0
def perform_cell_spicy(input_string,
                       repeats,
                       max_duration,
                       parts,
                       instrument_name,
                       key,
                       check_range=False):
    total_duration = 0
    n = NanoNotation()
    note_pattern = Pseq(n.midinumbers(input_string), repeats)
    dur_pattern = Pseq(n.dur(input_string), repeats)
    if len(n.midinumbers(input_string)) == 1 and repeats <= 1:
        perform_cell(input_string, repeats, max_duration, parts,
                     instrument_name, key, check_range)
    else:
        last_encountered_nd2 = None
        for nd1, nd2 in pairwise(zip(note_pattern, dur_pattern)):
            last_encountered_nd2 = nd2
            if total_duration < max_duration:
                prop = {}
                if random.randint(0, 10) > 7:
                    accent = 1.0
                    prop["articulations"] = "accent"
                else:
                    accent = 0.6

                n1 = nd1[0]
                n2 = nd2[0]
                d = nd1[1]
                duration = dur_to_beat(d)

                if total_duration + duration > max_duration:
                    duration = max_duration - total_duration  #  cut off the rhythm to remain inside measure

                if key:
                    prop["key"] = key

                if check_range and not check_range(instrument_name, n):
                    print(
                        f"Warning: instrument {instrument_name} goes out of range with note {n}"
                    )

                all_notes, all_durs = transform_note_duration(duration, n1, n2)

                for n, d in zip(all_notes, all_durs):
                    if n == REST:
                        scamp.wait(d)
                    else:
                        parts[instrument_name].play_note(
                            n,
                            0.7 * accent,
                            d,
                            properties=prop if prop else None)
                    total_duration += d
            else:
                return

        if last_encountered_nd2 is not None:
            n = last_encountered_nd2[0]
            d = last_encountered_nd2[1]
            if n == REST:
                scamp.wait(d)
            else:
                parts[instrument_name].play_note(
                    n,
                    0.7 * accent,
                    duration,
                    properties=prop if prop else None)
            total_duration += d
Ejemplo n.º 26
0
 def note(self, notes):
     """
     :param notes: list of notes that make up the phrase
     :return: pattern that generates the notes one by one
     """
     return Pseq(self.note2midi.convert2(notes))
Ejemplo n.º 27
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])
Ejemplo n.º 28
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])
Ejemplo n.º 29
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])
Ejemplo n.º 30
0
 def test_firstempty(self):
     a = [i for i in Padd(Pconst(4, 0), Pseq([1, 2, 3, 70], 1))]
     self.assertEqual(a, [])