Esempio n. 1
0
def make_assignment_mode_example():
    # create a midi file on which to test the assignment modes in load_midi
    part_1 = score.Part('P1')
    part_2 = score.Part('P2')
    part_3 = score.Part('P3')

    part_1.set_quarter_duration(0, 1)
    part_2.set_quarter_duration(0, 2)
    part_3.set_quarter_duration(0, 3)

    part_1.add(score.TimeSignature(4, 4), 0)
    part_1.add(score.Note(step='C', octave=4, voice=1), 0, 1)
    part_1.add(score.Note(step='B', octave=4, voice=2), 0, 2)
    part_1.add(score.Note(step='B', octave=4, voice=2), 2, 4)
    part_1.add(score.Note(step='B', octave=4, voice=2), 5, 6)
    part_1.add(score.Note(step='B', octave=4, voice=3), 7, 10)

    part_2.add(score.TimeSignature(4, 4), 0)
    part_2.add(score.Tempo(80), 0)
    part_2.add(score.Note(step='D', octave=5, voice=1), 0, 1)
    part_2.add(score.Note(step='E', octave=5, voice=2), 1, 2)
    part_2.add(score.Note(step='F', octave=5, voice=2), 2, 3)
    part_2.add(score.Note(step='G', octave=5, voice=2), 3, 4)

    part_3.add(score.TimeSignature(4, 4), 0)
    part_3.add(score.Note(step='G', octave=4, voice=1), 0, 3)

    pg = score.PartGroup(group_name='P1/P2')
    pg.children = [part_1, part_2]
    for p in pg.children:
        p.parent = pg

    return [pg, part_3]
Esempio n. 2
0
def _handle_attributes(e, position, part):
    """

    """

    ts_num = get_value_from_tag(e, 'time/beats', int)
    ts_den = get_value_from_tag(e, 'time/beat-type', int)
    if ts_num and ts_den:
        part.add(score.TimeSignature(ts_num, ts_den), position)

    fifths = get_value_from_tag(e, 'key/fifths', int)
    mode = get_value_from_tag(e, 'key/mode', str)
    if fifths is not None or mode is not None:
        part.add(score.KeySignature(fifths, mode), position)

    diat = get_value_from_tag(e, 'transpose/diatonic', int)
    chrom = get_value_from_tag(e, 'transpose/chromatic', int)
    if diat is not None or chrom is not None:
        part.add(score.Transposition(diat, chrom), position)

    divs = get_value_from_tag(e, 'divisions', int)
    if divs:
        # part.add(score.Divisions(divs), position)
        part.set_quarter_duration(position, divs)

    clefs = get_clefs(e)
    for clef in clefs:
        part.add(score.Clef(**clef), position)
Esempio n. 3
0
    def test_midi_export_anacrusis(self):
        part = score.Part("id")
        # 1 div is 1 quarter
        part.set_quarter_duration(0, 1)
        # 4/4 at t=0
        part.add(score.TimeSignature(4, 4), 0)

        # ANACRUSIS
        # quarter note from t=0 to t=1
        part.add(score.Note("c", 4), 0, 1)
        # incomplete measure from t=0 to t=1
        part.add(score.Measure(), 0, 1)

        # whole note from t=1 to t=5
        part.add(score.Note("c", 4), 1, 5)
        # add missing measures
        score.add_measures(part)

        # print(part.pretty())

        mid = export_and_read(part, anacrusis_behavior="shift")
        t = 0
        for msg in mid.tracks[0]:
            t += msg.time
            if msg.type == "note_on":
                assert t == 0
                break

        mid = export_and_read(part, anacrusis_behavior="pad_bar")
        t = 0
        for msg in mid.tracks[0]:
            t += msg.time
            if msg.type == "note_on":
                assert t == 3, f"Incorrect time of first note on: {t} (should be 3)"
                break
Esempio n. 4
0
def make_part_tuplet():
    # create a part
    part = score.Part('My Part')

    # create contents
    divs = 12
    ts = score.TimeSignature(3, 4)
    page1 = score.Page(1)
    system1 = score.System(1)

    note1 = score.Note(id='n0', step='A', octave=4, voice=1, staff=1)
    rest1 = score.Rest(voice=1, staff=1)
    note2 = score.Note(id='n2', step='C', octave=4, voice=1, staff=1)
    rest2 = score.Rest(id='r0', voice=1, staff=1)
    
    # and add the contents to the part:
    part.set_quarter_duration(0, divs)
    part.add(ts, 0)
    part.add(page1, 0)
    part.add(system1, 0)
    part.add(note1, 0, 8)
    part.add(rest1, 8, 16)
    part.add(note2, 16, 24)
    part.add(rest2, 24, 36)

    score.add_measures(part)
    score.find_tuplets(part)
    score.set_end_times(part)

    return part
Esempio n. 5
0
    def test_notearray_1(self):
        part = score.Part("P0", "My Part")

        part.set_quarter_duration(0, 10)
        part.add(score.TimeSignature(3, 4), start=0)
        part.add(score.Note(id="n0", step="A", octave=4), start=0, end=10)

        note_array = part.note_array
        self.assertTrue(len(note_array) == 1)
Esempio n. 6
0
    def test_export_import_pprint(self):
        # create a part
        part1 = score.Part('My Part')

        # create contents
        divs = 10
        ts = score.TimeSignature(3, 4)
        page1 = score.Page(1)
        system1 = score.System(1)
        measure1 = score.Measure(number=1)
        note1 = score.Note(step='A', octave=4, voice=1, staff=1)
        rest1 = score.Rest(voice=1, staff=1)
        note2 = score.Note(step='C', octave=5, alter=-1, voice=2, staff=1)
        
        # and add the contents to the part:
        part1.set_quarter_duration(0, divs)
        part1.add(ts, 0)
        part1.add(measure1, 0, 30)
        part1.add(page1, 0)
        part1.add(system1, 0)
        part1.add(note1, 0, 15)
        part1.add(rest1, 15, 30)
        part1.add(note2, 0, 30)
        
        score.set_end_times(part1)
        
        # pretty print the part
        pstring1 = part1.pretty()

        with TemporaryFile() as f:
            # save part to musicxml
            save_musicxml(part1, f)
            f.flush()
            f.seek(0)
            # load part from musicxml
            part2 = load_musicxml(f)

        # pretty print saved/loaded part:
        pstring2 = part2.pretty()

        # test pretty printed strings for equality
        equal = pstring1 == pstring2

        if not equal:
            show_diff(pstring1, pstring2)
        msg = 'Exported and imported score does not yield identical pretty printed representations'
        self.assertTrue(equal, msg)
Esempio n. 7
0
    def test_times_2(self):
        # 6/8 anacrusis
        part = score.Part("id")
        # 2 divs is 1 quarter
        part.set_quarter_duration(0, 2)
        part.add(score.TimeSignature(6, 8), 0)

        # ANACRUSIS
        part.add(score.Note("c", 4), 0, 3)
        part.add(score.Measure(), 0, 3)

        part.add(score.Note("c", 4), 3, 9)

        score.add_measures(part)

        time_pairs = [(-3, -1.5), (0, 0), (6, 3)]
        test_time_pairs(part, time_pairs)
Esempio n. 8
0
def make_part_slur():
    # create a part
    part = score.Part('My Part')
    # create contents
    divs = 12
    ts = score.TimeSignature(3, 4)
    page1 = score.Page(1)
    system1 = score.System(1)

    note0 = score.Note(id='n0', step='A', octave=4, voice=1, staff=1)
    note1 = score.Note(id='n1', step='A', octave=4, voice=1, staff=1)
    note2 = score.Note(id='n2', step='A', octave=4, voice=1, staff=1)
    note3 = score.Note(id='n3', step='A', octave=4, voice=1, staff=1)

    note4 = score.Note(id='n4', step='A', octave=3, voice=2, staff=1)
    note5 = score.Note(id='n5', step='A', octave=3, voice=2, staff=1)

    slur1 = score.Slur(start_note=note0, end_note=note5)
    slur2 = score.Slur(start_note=note4, end_note=note3)
    
    # and add the contents to the part:
    part.set_quarter_duration(0, divs)
    part.add(ts, 0)
    part.add(page1, 0)
    part.add(system1, 0)
    part.add(note0, 0, 12)
    part.add(note1, 12, 24)
    part.add(note2, 24, 36)
    part.add(note3, 36, 48)
    part.add(note4, 0, 6)
    part.add(note5, 6, 33)
    part.add(slur1, 
                      slur1.start_note.start.t,
                      slur1.end_note.end.t)
    part.add(slur2, 
                      slur2.start_note.start.t,
                      slur2.end_note.end.t)

    score.add_measures(part)
    score.tie_notes(part)
    score.set_end_times(part)
    return part
Esempio n. 9
0
    def test_times_1(self):
        # 4/4 anacrusis
        part = score.Part("id")
        # 1 div is 1 quarter
        part.set_quarter_duration(0, 1)
        # 4/4 at t=0
        part.add(score.TimeSignature(4, 4), 0)

        # ANACRUSIS
        # quarter note from t=0 to t=1
        part.add(score.Note("c", 4), 0, 1)
        # incomplete measure from t=0 to t=1
        part.add(score.Measure(), 0, 1)

        # whole note from t=1 to t=5
        part.add(score.Note("c", 4), 1, 5)
        # add missing measures
        score.add_measures(part)
        time_pairs = [(-1, -1), (0, 0), (4, 4)]
        test_time_pairs(part, time_pairs)
Esempio n. 10
0
def create_part_from_spec(spec):
    """Create a part from a specification of divisions, time signatures
    and notes.

    This is a helper function for the TestBeatMap test case.

    Parameters
    ----------
    spec : dictionary
        Part specification

    Returns
    -------
    Part
        Part instance
    
    """

    part = score.Part('beatmaptest')
    # for t, divs in spec['divs']:
    #     part.add(score.Divisions(divs), t)
    for t, divs in spec['divs']:
        part.set_quarter_duration(t, divs)

    for t, num, den in spec['ts']:
        part.add(score.TimeSignature(num, den), t)

    # divs_map = part.divisions_map

    for t, dur in spec['notes']:
        # sd = score.estimate_symbolic_duration(dur, int(divs_map(t)))
        part.add(score.Note(step='A', alter=None, octave=4), t, t + dur)

    score.add_measures(part)

    return part
Esempio n. 11
0
def create_part(ticks, notes, spellings, voices, note_ids, time_sigs, key_sigs, part_id=None, part_name=None):
    LOGGER.debug('create_part')

    part = score.Part(part_id, part_name=part_name)
    part.set_quarter_duration(0, ticks)

    clef = score.Clef(number=1, **estimate_clef_properties([pitch for _, pitch, _ in notes]))
    part.add(clef, 0)
    for t, name in key_sigs:
        fifths, mode = key_name_to_fifths_mode(name)
        part.add(score.KeySignature(fifths, mode), t)

    LOGGER.debug('add notes')

    for (onset, pitch, duration), (step, alter, octave), voice, note_id in zip(notes, spellings, voices, note_ids):
        if duration > 0:
            note = score.Note(step, octave, alter, voice=int(voice or 0), id=note_id,
                              symbolic_duration=estimate_symbolic_duration(duration, ticks))
        else:
            note = score.GraceNote('appoggiatura', step, octave, alter, voice=int(voice or 0), id=note_id,
                                   symbolic_duration=dict(type='quarter'))

        part.add(note, onset, onset+duration)

    if not time_sigs:
        warnings.warn('No time signatures found, assuming 4/4')
        time_sigs = [(0, 4, 4)]

    time_sigs = np.array(time_sigs, dtype=np.int)

    # for convenience we add the end times for each time signature
    ts_end_times = np.r_[time_sigs[1:, 0], np.iinfo(np.int).max]
    time_sigs = np.column_stack((time_sigs, ts_end_times))

    LOGGER.debug('add time sigs and measures')

    for ts_start, num, den, ts_end in time_sigs:
        time_sig = score.TimeSignature(num.item(), den.item())
        part.add(time_sig, ts_start.item())

    score.add_measures(part)

    # this is the old way to add measures. Since part comes from MIDI we
    # only have a single global divs value, which makes add it easier to compute
    # measure durations:
    
    # measure_counter = 1
    # # we call item() on numpy numbers to get the value in the equivalent python type
    # for ts_start, num, den, ts_end in time_sigs:
    #     time_sig = score.TimeSignature(num.item(), den.item())
    #     part.add(time_sig, ts_start.item())
    #     measure_duration = (num.item() * ticks * 4) // den.item()
    #     measure_start_limit = min(ts_end.item(), part.last_point.t)
    #     for m_start in range(ts_start, measure_start_limit, measure_duration):
    #         measure = score.Measure(number=measure_counter)
    #         m_end = min(m_start+measure_duration, ts_end)
    #         part.add(measure, m_start, m_end)
    #         measure_counter += 1
    #     if np.isinf(ts_end):
    #         ts_end = m_end

    LOGGER.debug('tie notes')
    # tie notes where necessary (across measure boundaries, and within measures
    # notes with compound duration)
    score.tie_notes(part)

    LOGGER.debug('find tuplets')
    # apply simplistic tuplet finding heuristic
    score.find_tuplets(part)

    LOGGER.debug('done create_part')
    return part
Esempio n. 12
0
def part_from_matchfile(mf):
    part = score.Part('P1', mf.info('piece'))
    # snotes = sorted(mf.snotes, key=attrgetter('OnsetInBeats'))
    snotes = sort_snotes(mf.snotes)
    divs = np.lcm.reduce(np.unique([note.Offset.denominator * (note.Offset.tuple_div or 1)
                                    for note in snotes]))
    part.set_quarter_duration(0, divs)
    min_time = snotes[0].OnsetInBeats  # sorted by OnsetInBeats
    max_time = max(n.OffsetInBeats for n in snotes)

    ts = mf.time_signatures

    beats_map, beat_type_map, min_time_q, max_time_q = make_timesig_maps(ts, max_time)

    bars = np.unique([n.Bar for n in snotes])
    t = min_time
    t = t * 4 / beat_type_map(min_time_q)
    offset = t
    # bar map: bar_number-> start in quarters
    bar_times = {}
    for b0, b1 in iter_current_next(bars, start=0):

        bar_times.setdefault(b1, t)
        if t < 0:
            t = 0
        else:
            # multiply by diff between consecutive bar numbers
            n_bars = b1 - b0
            if t <= max_time_q:
                t += (n_bars * 4 * beats_map(t)) / beat_type_map(t)

    for note in snotes:
        # start of bar in quarter units
        bar_start = bar_times[note.Bar]

        # offset within bar in quarter units
        bar_offset = (note.Beat - 1) * 4 / beat_type_map(bar_start)
        # offset within beat in quarter units
        beat_offset = (4 * note.Offset.numerator
                       / (note.Offset.denominator * (note.Offset.tuple_div or 1)))

        # # anacrusis
        if bar_start < 0:
            # in case of anacrusis we set the bar_start to -bar_duration (in
            # quarters) so that the below calculation is correct
            bar_start = - beats_map(bar_start) * 4 / beat_type_map(bar_start)

        # note onset in divs
        onset_divs = int(divs * (bar_start + bar_offset + beat_offset - offset))
        # print(note.Anchor, onset_divs, bar_start, bar_offset, beat_offset, offset)

        articulations = set()
        if 'staccato' in note.ScoreAttributesList:
            articulations.add('staccato')
        if 'accent' in note.ScoreAttributesList:
            articulations.add('accent')

        # dictionary with keyword args with which the Note (or GraceNote) will be instantiated
        note_attributes = dict(step=note.NoteName,
                               octave=note.Octave,
                               alter=note.Modifier,
                               id=note.Anchor,
                               articulations=articulations)

        staff_nr = next((a[-1] for a in note.ScoreAttributesList if a.startswith('staff')), None)
        try:
            note_attributes['staff'] = int(staff_nr)
        except (TypeError, ValueError):
            # no staff attribute, or staff attribute does not end with a number
            note_attributes['staff'] = None

        note_attributes['voice'] = next((int(a) for a in note.ScoreAttributesList
                                         if NUMBER_PAT.match(a)), None)

        # get rid of this if as soon as we have a way to iterate over the
        # duration components. For now we have to treat the cases simple
        # and compound durations separately.

        if note.Duration.add_components:
            prev_part_note = None

            for i, (num, den, tuple_div) in enumerate(note.Duration.add_components):

                # when we add multiple notes that are tied, the first note will
                # get the original note id, and subsequent notes will get a
                # derived note id (by appending, 'a', 'b', 'c',...)
                if i > 0:
                    # tnote_id = 'n{}_{}'.format(note.Anchor, i)
                    note_attributes['id'] = score.make_tied_note_id(note_attributes['id'])

                part_note = score.Note(**note_attributes)

                duration_divs = int(divs * 4 * num / (den * (tuple_div or 1)))

                assert duration_divs > 0

                offset_divs = onset_divs + duration_divs

                part.add(part_note, onset_divs, offset_divs)

                if prev_part_note:
                    prev_part_note.tie_next = part_note
                    part_note.tie_prev = prev_part_note
                prev_part_note = part_note
                onset_divs = offset_divs

        else:

            num = note.Duration.numerator
            den = note.Duration.denominator
            tuple_div = note.Duration.tuple_div
            duration_divs = int(divs * 4 * num / (den * (tuple_div or 1)))

            offset_divs = onset_divs + duration_divs

            # notes with duration 0, are also treated as grace notes, even if
            # they do not have a 'grace' score attribute
            if ('grace' in note.ScoreAttributesList or
                    note.Duration.numerator == 0):

                part_note = score.GraceNote('appoggiatura', **note_attributes)

            else:

                part_note = score.Note(**note_attributes)

            part.add(part_note, onset_divs, offset_divs)

    # add time signatures
    for (ts_beat_time, ts_bar, (ts_beats, ts_beat_type)) in ts:

        bar_start_divs = int(divs * (bar_times[ts_bar] - offset))  # in quarters
        part.add(score.TimeSignature(ts_beats, ts_beat_type), bar_start_divs)

    # add key signatures
    for (ks_beat_time, ks_bar, keys) in mf.key_signatures:

        if len(keys) > 1:
            # there are multple equivalent keys, so we check which one is most
            # likely according to the key estimator
            est_keys = estimate_key(notes_to_notearray(part.notes_tied), return_sorted_keys=True)
            idx = [est_keys.index(key) if key in est_keys else np.inf
                   for key in keys]
            key_name = keys[np.argmin(idx)]

        else:

            key_name = keys[0]

        fifths, mode = key_name_to_fifths_mode(key_name)
        part.add(score.KeySignature(fifths, mode), 0)

    add_staffs(part)
    # add_clefs(part)

    # add incomplete measure if necessary

    if offset < 0:

        part.add(score.Measure(number=1), 0, int(-offset * divs))

    # add the rest of the measures automatically
    score.add_measures(part)
    # print(part.pretty())
    score.tie_notes(part)
    score.find_tuplets(part)

    if not all([n.voice for n in part.notes_tied]):
        # print('notes without voice detected')
        add_voices(part)

    return part