Example #1
0
    def test_hseq_repeats(self):
        from sebastian.core import HSeq
        from sebastian.core import MIDI_PITCH
        s1 = HSeq([
            {
                MIDI_PITCH: 50
            },
            {
                MIDI_PITCH: 51
            },
        ])

        expected = HSeq([
            {
                MIDI_PITCH: 50
            },
            {
                MIDI_PITCH: 51
            },
            {
                MIDI_PITCH: 50
            },
            {
                MIDI_PITCH: 51
            },
        ])

        self.assertEqual(expected, s1 * 2)
Example #2
0
def build_movement():
    # Define our alberti bass signature.
    alberti = arpeggio([0, 2, 1, 2])

    # Create the basic interval pattern.
    intervals = HSeq({DEGREE: x} for x in [1, 5, 1, 4, 1, 5, 1])

    # Create the rhythm
    rhythm = HSeq({DURATION_64: x} for x in [128, 64, 64, 64, 64, 64, 64])

    # Set specific chords to be used in certain measures.
    intervals[1]["chord"] = (-3, -1, 0, 2)  # second inversion 7th
    intervals[3]["chord"] = (-3, 0, 2)      # second inversion
    intervals[5]["chord"] = (-5, -3, 0)     # first inversion

    # Combine the sequences, make them chords, produce alberti on the chords,
    # fill with each being 8, expand it to a flat sequence.
    melody = intervals & rhythm | chord() | alberti | fill(8) | expand

    # Define our key
    C_major = Key("C", major_scale)

    #key(major_scale(-2))

    # Set the degree, add the midi pitch, make it an OSequence, add debugging information.
    return melody | degree_in_key_with_octave(C_major, 5) | midi_pitch() | OSequence | debug
Example #3
0
    def test_hseq_subseq(self):
        """
        Ensure that two sequences can be zipped together, unifying its points.
        """
        from sebastian.core import HSeq
        from sebastian.core import MIDI_PITCH, DURATION_64
        s1 = HSeq([{
            MIDI_PITCH: 50,
            DURATION_64: 10
        }, {
            MIDI_PITCH: 51,
            DURATION_64: 10
        }, {
            MIDI_PITCH: 52,
            DURATION_64: 10
        }, {
            MIDI_PITCH: 53,
            DURATION_64: 10
        }])

        s2 = s1.subseq(20, 40)
        self.assertEqual(
            s2,
            HSeq([
                {
                    MIDI_PITCH: 51,
                    DURATION_64: 10
                },
                {
                    MIDI_PITCH: 52,
                    DURATION_64: 10
                },
            ]))
Example #4
0
 def test_hseq_doesnt_track_duration_on_append(self):
     """
     Ensure hseq doesnt do offset modification
     """
     from sebastian.core import HSeq, Point
     s1 = HSeq()
     s1.append(Point(duration=10))
     s1.append(Point(duration=10))
     for point in s1:
         self.assertTrue('offset' not in point)
Example #5
0
 def test_hseq_doesnt_track_duration_on_append(self):
     """
     Ensure hseq doesnt do offset modification
     """
     from sebastian.core import HSeq, Point
     s1 = HSeq()
     s1.append(Point(duration=10))
     s1.append(Point(duration=10))
     for point in s1:
         self.assertTrue('offset' not in point)
Example #6
0
    def next_by_counts(self, count=None):
        self.note.reset()
        self.duration.reset()
        self.velocity.reset()
        seq = HSeq()
        if counts != None:
            counts = random.randint(1,30)
        for i in range(counts):
            next = self.note.next()
            next.update({DURATION_64: self.duration.next(), "velocity": self.velocity.next()})
            seq.append(next)

        self.last = OSequence(seq)
        return self.last
Example #7
0
    def gen_rand_seq(self, counts=None):
        snippet=" "
        seq = HSeq()
        note = Wandering(self.keyboard)
        duration = Wandering(range(4,8),3)
        velocity = Wandering(range(40,127),10)

        if counts == None:
            counts = random.randint(1,30)
        for i in range(counts):
            next = note.next()
            next.update({DURATION_64: duration.next(), "velocity": velocity.next()})
            seq.append(next)

        self.last_sequence = seq
        return seq
Example #8
0
 def test_write(self):
     import tempfile
     pitches = HSeq({"pitch": n} for n in [-2, 0, 2, -3])
     seq = pitches | add({"octave": 5, DURATION_64: 16}) | lilypond()
     f = tempfile.NamedTemporaryFile(suffix=".ly", delete=False)
     write(f.name, seq)
     with open(f.name) as g:
         self.assertEqual(g.read(), "{ c'4 d'4 e'4 f'4 }")
Example #9
0
    def test_sequence_map(self):
        """
        Ensure map_points applys the function
        """
        from sebastian.core import HSeq, Point

        s1 = (HSeq(Point(a=3, c=5)) + HSeq([Point(d=x) for x in range(10)]) +
              HSeq(Point(a=5)))

        def double_a(point):
            if 'a' in point:
                point['a'] *= 2
            return point

        s2 = s1.map_points(double_a)

        self.assertEqual(s2[0]['a'], 6)
        self.assertEqual(s2[-1]['a'], 10)
Example #10
0
 def test_display_skipped_on_empty(self):
     """
     If all lilypond output is empty,
     ensure we don't call lilypond
     """
     empty = HSeq({"fake": n} for n in range(2))
     seq = empty | lilypond()
     displayed = seq.display()
     self.assertTrue(isinstance(displayed, HSeq))
Example #11
0
    def test_hseq_subseq(self):
        """
        Ensure that two sequences can be zipped together, unifying its points.
        """
        from sebastian.core import HSeq
        from sebastian.core import MIDI_PITCH, DURATION_64
        s1 = HSeq([
            {MIDI_PITCH: 50, DURATION_64: 10},
            {MIDI_PITCH: 51, DURATION_64: 10},
            {MIDI_PITCH: 52, DURATION_64: 10},
            {MIDI_PITCH: 53, DURATION_64: 10}
        ])

        s2 = s1.subseq(20, 40)
        self.assertEqual(s2, HSeq([
            {MIDI_PITCH: 51, DURATION_64: 10},
            {MIDI_PITCH: 52, DURATION_64: 10},
        ]))
Example #12
0
    def test_basic_sequence_zip(self):
        """
        Ensure that two sequences can be zipped together, unifying its points.
        """
        from sebastian.core import HSeq
        from sebastian.core import MIDI_PITCH, DURATION_64
        s1 = HSeq([{
            MIDI_PITCH: 50
        }, {
            MIDI_PITCH: 51
        }, {
            MIDI_PITCH: 53
        }, {
            MIDI_PITCH: 54
        }])
        s2 = HSeq([{
            DURATION_64: 17
        }, {
            DURATION_64: 18
        }, {
            DURATION_64: 20
        }, {
            DURATION_64: 21
        }])

        s_zipped = s1 & s2
        self.assertEqual(
            s_zipped,
            HSeq([{
                MIDI_PITCH: 50,
                DURATION_64: 17
            }, {
                MIDI_PITCH: 51,
                DURATION_64: 18
            }, {
                MIDI_PITCH: 53,
                DURATION_64: 20
            }, {
                MIDI_PITCH: 54,
                DURATION_64: 21
            }]))
Example #13
0
 def test_lilypond_transform_rhythms(self):
     """
     Ensure points without pitches can render to lilypond
     """
     from sebastian.core.transforms import lilypond
     from sebastian.core import DURATION_64
     from sebastian.core import HSeq, Point
     h1 = HSeq([Point({DURATION_64: 64}), Point({DURATION_64: 0}), Point()])
     h2 = h1 | lilypond()
     self.assertEqual(h2._elements[0]['lilypond'], r"\xNote c'1")
     self.assertEqual(h2._elements[1]['lilypond'], '')
     self.assertEqual(h2._elements[2]['lilypond'], '')
Example #14
0
    def test_hseq_concat(self):
        """
        Ensure hseq can concatenate
        """
        from sebastian.core import HSeq
        from sebastian.core import MIDI_PITCH
        s1 = HSeq([
            {
                MIDI_PITCH: 50
            },
            {
                MIDI_PITCH: 51
            },
        ])
        s2 = HSeq([
            {
                MIDI_PITCH: 60
            },
            {
                MIDI_PITCH: 59
            },
        ])

        expected = HSeq([
            {
                MIDI_PITCH: 50
            },
            {
                MIDI_PITCH: 51
            },
            {
                MIDI_PITCH: 60
            },
            {
                MIDI_PITCH: 59
            },
        ])

        self.assertEqual(expected, s1 + s2)
Example #15
0
def alberti(triad):
    """
    takes a VSeq of 3 notes and returns an HSeq of those notes in an
    alberti figuration.
    """
    return HSeq(triad[i] for i in [0, 2, 1, 2])
Example #16
0
 def make_horizontal_sequence(self):
     from sebastian.core import HSeq, Point
     return HSeq([Point(degree=degree) for degree in self.make_notes()])
Example #17
0
    def test_lilypond_transform(self):
        """
        Ensure that it plays in G major.
        """
        from sebastian.core.transforms import midi_pitch, add, lilypond
        from sebastian.core import DURATION_64
        from sebastian.core import HSeq, Point
        h1 = HSeq(
            [Point(pitch=pitch) for pitch in [0, 1, 2, 3, 4, 11, -4, -11]])
        positioned = h1 | add({'octave': 4, DURATION_64: 8})
        pitched = positioned | midi_pitch()
        pitched[3]['octave'] = 5
        pitched[4]['octave'] = 3
        lilyed = pitched | lilypond()

        import pprint
        pprint.pprint(list(lilyed))

        self.assertEqual(lilyed._elements, [{
            'duration_64': 8,
            'lilypond': 'd8',
            'midi_pitch': 50,
            'octave': 4,
            'pitch': 0
        }, {
            'duration_64': 8,
            'lilypond': 'a8',
            'midi_pitch': 57,
            'octave': 4,
            'pitch': 1
        }, {
            'duration_64': 8,
            'lilypond': 'e8',
            'midi_pitch': 52,
            'octave': 4,
            'pitch': 2
        }, {
            'duration_64': 8,
            'lilypond': "b'8",
            'midi_pitch': 59,
            'octave': 5,
            'pitch': 3
        }, {
            'duration_64': 8,
            'lilypond': 'fis,8',
            'midi_pitch': 54,
            'octave': 3,
            'pitch': 4
        }, {
            'duration_64': 8,
            'lilypond': 'fisis8',
            'midi_pitch': 55,
            'octave': 4,
            'pitch': 11
        }, {
            'duration_64': 8,
            'lilypond': 'bes8',
            'midi_pitch': 58,
            'octave': 4,
            'pitch': -4
        }, {
            'duration_64': 8,
            'lilypond': 'beses8',
            'midi_pitch': 57,
            'octave': 4,
            'pitch': -11
        }])
Example #18
0
def end(scale):
    return HSeq(scale[i] for i in [2, 1]) | add(quaver_point)
Example #19
0
def h2_end1(scale):
    return HSeq(scale[i] for i in [0, 4]) | add(quaver_point)
Example #20
0

def end(scale):
    return HSeq(scale[i] for i in [2, 1]) | add(quaver_point)


def h2(scale):
    return HSeq(scale[i] for i in [0, 4, 3, 4]) | add(quaver_point)


def h2_end1(scale):
    return HSeq(scale[i] for i in [0, 4]) | add(quaver_point)


# there's two important quarter notes used at the ends of sections
e1 = HSeq(scale[3]) | add(quarter_point)
e2 = HSeq(scale[0]) | add(quarter_point)

partA = h1(scale) + h1_end1(scale) + e1 + h1(scale) + end(scale) + e2
partB = h2(scale) + h2_end1(scale) + e1 + h2(scale) + end(scale) + e2

# here we see the basic structure of the song
oseq = OSequence((partA * 2) + (partB * 2))

C_major = Key("C", major_scale)

# note values filled-out for C major in octave 5 then MIDI pitches calculated
seq = oseq | degree_in_key_with_octave(C_major, 5) | midi_pitch()

# write to file:
write_midi.write("shortning_bread_1.mid", [seq])
Example #21
0
def h1(scale):
    return HSeq(scale[i] for i in [5, 4, 3, 4]) | add(quaver_point)
Example #22
0
def make_hseq(notes):
    return HSeq(Point(degree=n, duration_64=d) for n, d in notes)
Example #23
0
 def test_output(self):
     pitches = HSeq({"pitch": n} for n in [-2, 0, 2, -3])
     seq = pitches | add({"octave": 5, DURATION_64: 16}) | lilypond()
     self.assertEqual(output(seq), "{ c'4 d'4 e'4 f'4 }")
Example #24
0
def arpeggio(pattern, point):
    """
    turns each subsequence into an arpeggio matching the given ``pattern``.
    """
    point['sequence'] = HSeq(point['sequence'][i] for i in pattern)
    return point
Example #25
0
"""
The main title theme to HBO's Game of Thrones by Ramin Djawadi
"""

from sebastian.core import Point, HSeq, OSequence
from sebastian.core.transforms import midi_pitch, degree_in_key, add
from sebastian.core.notes import Key, major_scale, minor_scale
from sebastian.midi import write_midi

C_Major = Key("C", major_scale)
C_minor = Key("C", minor_scale)

motive_degrees = HSeq(Point(degree=n) for n in [5, 1, 3, 4])

motive_rhythm_1 = HSeq(Point(duration_64=n) for n in [16, 16, 8, 8])
motive_rhythm_2 = HSeq(
    Point(duration_64=n) for n in [48, 48, 8, 8, 32, 32, 8, 8])

motive_1 = motive_degrees & motive_rhythm_1
motive_2 = (motive_degrees * 2) & motive_rhythm_2

# add key and octave
seq1 = (motive_1 * 4) | add({"octave": 5}) | degree_in_key(C_minor)
seq2 = (motive_1 * 4) | add({"octave": 5}) | degree_in_key(C_Major)
seq3 = motive_2 | add({"octave": 4}) | degree_in_key(C_minor)

seq = (seq1 + seq2 + seq3) | midi_pitch() | OSequence

write_midi.write("game_of_thrones.mid", [seq], instruments=[49], tempo=350000)
Example #26
0
seq3 = seq1 + seq2

# transpose and reverse
seq4 = seq3 | transpose(12) | reverse()

# merge
seq5 = seq3 // seq4

# play MIDI
player.play([seq5])

# write to MIDI
write_midi.write("seq5.mid", [seq5])

# contruct a horizontal sequence of scale degrees
seq6 = HSeq(Point(degree=degree) for degree in [1, 2, 3, 2, 1])

# put that sequence into C major, octave 4 quavers
C_MAJOR = Key("C", major_scale)
seq7 = seq6 | add({"octave": 4, DURATION_64: 8}) | degree_in_key(C_MAJOR)

# convert to MIDI pitch and play
player.play([OSequence(seq7 | midi_pitch())])

# sequence of first four degree of a scale
seq8 = HSeq(Point(degree=n) for n in [1, 2, 3, 4])

# add duration and octave
seq8 = seq8 | add({DURATION_64: 16, "octave": 5})

# put into C major