示例#1
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)
示例#2
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
示例#3
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