示例#1
0
def get_offset_from_key(key):
    tonic, mode = key.split(' ')
    tonic = tonic.replace('b', '-')
    if mode == 'major':
        k = Key(tonic)
    else:
        k = Key(tonic.lower()).relative
    return Pitch('C').midi - k.getTonic().midi
示例#2
0
def add_step_information(notes, keySignatures):
  """
  This function will populate the step information into Mupix note objects, it
  is required because music21 will not keep key signature information in
  measure other than the measure the key is defined in when reading musicXML.
  The maintainers of music21 don't believe this is an issue and won't fix it,
  so this and others must exist.

  :param [notes]: A list of Mupix NoteObjects.
  :type [notes]: List

  :param [keySignatures]: A list of Mupix KeySignatureObjects.
  :type [keySignatures]: List

  :return [List]: The original list of Mupix NoteObjects (in order) with step information included.
  :rtype: List
  """
  for key in keySignatures:
    key_name = key.step.upper() if key.mode == "major" else key.step.lower()

    for note in notes:
      if note.part == key.part and note.measure == key.measure:
        note.step = Interval(noteStart=Note(Key(key_name).asKey().tonic), noteEnd=note._music21_object).semitones % 12

  return notes
示例#3
0
文件: m21.py 项目: greenslurp/bmc
 def __init__(self, key=None, time=None, melody='', fingering=None):
     TinyNotationStream.__init__(self, melody, time)
     if key is not None:
         self.insert(0, Key(key))
     if fingering is not None:
         for (note_index, finger) in fingering:
             self.notes[note_index].fingering = finger
示例#4
0
def voiceProgression(key, chordProgression):
    """Voices a chord progression in a specified key using DP.

    Follows eighteenth-century voice leading procedures, as guided by the cost
    function defined in the `chordCost` and `progressionCost` functions.
    Returns a list of four-pitch chords, corresponding to successive Roman
    numerals in the chord progression.
    """
    key = Key(key)
    if isinstance(chordProgression, str):
        chordProgression = list(filter(None, chordProgression.split()))

    dp = [{} for _ in chordProgression]
    for i, numeral in enumerate(chordProgression):
        chord = RomanNumeral(numeral, key)
        voicings = voiceChord(key, chord)
        if i == 0:
            for v in voicings:
                dp[0][v.pitches] = (chordCost(key, v), None)
        else:
            for v in voicings:
                best = (float("inf"), None)
                for pv_pitches, (pcost, _) in dp[i - 1].items():
                    pv = Chord(pv_pitches)
                    ccost = pcost + progressionCost(key, pv, v)
                    if ccost < best[0]:
                        best = (ccost, pv_pitches)
                dp[i][v.pitches] = (best[0] + chordCost(key, v), best[1])

    cur, (totalCost, _) = min(dp[-1].items(), key=lambda p: p[1][0])
    ret = []
    for i in reversed(range(len(chordProgression))):
        ret.append(Chord(cur, lyric=chordProgression[i]))
        cur = dp[i][cur][1]
    return list(reversed(ret)), totalCost
示例#5
0
def transposeKeys(keys, newTonic):
    """Transpose a list of keys relative to a new tonic."""
    referenceKey = Key(keys[0])
    newTonicKey = Key(newTonic, mode=referenceKey.mode)
    intervalDiff = Interval(referenceKey.tonic, newTonicKey.tonic)
    transposedKeys = [newTonicKey.tonicPitchNameWithCase]
    for k in keys[1:]:
        localKey = Key(k)
        newLocalTonic = localKey.tonic.transpose(intervalDiff)
        newLocalKey = Key(newLocalTonic, mode=localKey.mode)
        if abs(newLocalKey.sharps) >= 7:
            newLocalKey = Key(newLocalTonic.getEnharmonic(),
                              mode=localKey.mode)
        transposedKeys.append(newLocalKey.tonicPitchNameWithCase)
    transposedKeys = [k.replace("-", "b") for k in transposedKeys]
    return transposedKeys
def mixed_sequences(data_path, output_path):
    for (number, filename) in enumerate(os.listdir(data_path), start=1):
        try:
            full_path = os.path.join(data_path, filename)
            LOG.debug("Finding mixed sequences in piece {number}: {filename}.".format(**locals()))
            piece = parse(full_path)
            temp_abspath = os.path.join(output_path, TEMP_MIDI_NAME)
            piece.write('midi', temp_abspath)
            chord_per_measure = temperley.chord_per_measure(piece, temp_abspath)
            keys = temperley.key_sequence(temp_abspath)
            if len(set(keys)) > 1:
                continue  # more than one key in piece is complicated...
            else:
                key_string = convertKeyStringToMusic21KeyString(keys[0].replace('b','-'))
                key = Key()
                key_pitch = key.getPitches()[0]
            instrument = lambda x: x.getInstrument().instrumentName.lower()
            guitar_parts = (e for e in piece if isinstance (e, Part) and \
                                             ('guitar' in instrument(e) or \
                                             'gtr' in instrument(e)) and not \
                                             'bass' in instrument(e))
            for part in guitar_parts:
                current_sequence = None
                last_note = None
                measures = [elem for elem in part if isinstance(elem, Measure)]
                if len(chord_per_measure) != len(measures):
                    continue
                for chord, measure in zip(chord_per_measure, measures):
                    chord_pitch = music21.pitch.Pitch(convertKeyStringToMusic21KeyString(chord))
                    for element in measure:
                        if isinstance(element, Note):
                            if not last_note:
                                current_sequence = [(0, 0, notesToChromatic(key_pitch, element).semitones, key.mode, notesToChromatic(key_pitch, chord_pitch).semitones)]
                            else:
                                interval = notesToChromatic(last_note, element)
                                entry = (current_sequence[-1][1], interval.semitones, notesToChromatic(key_pitch, element).semitones, key.mode, notesToChromatic(key_pitch, chord_pitch).semitones)
                                current_sequence.append(entry)
                            last_note = element
                        elif isinstance(element, Rest) and element.quarterLength < 4:
                            pass
                        elif current_sequence:
                            yield current_sequence
                            current_sequence = None
                            last_note = None
        except Exception:
            LOG.warning('Encountered exception in {filename}'.format(**locals()))
示例#7
0
def to_music21_key(key_signature: KeySignature) -> Key:
    """Return a KeySignature object as a music21 Key object."""
    if key_signature.root_str is not None:
        tonic = key_signature.root_str
    elif key_signature.root is not None:
        tonic = PITCH_NAMES[key_signature.root]
    elif key_signature.fifths is not None:
        if key_signature.mode is not None:
            offset = MODE_CENTERS[key_signature.mode]
            tonic = CIRCLE_OF_FIFTHS[key_signature.fifths + offset][1]
        else:
            tonic = CIRCLE_OF_FIFTHS[key_signature.fifths][1]
    else:
        raise ValueError(
            "One of `root`, `root_str` or `fifths` must be specified.")
    key = Key(tonic=tonic, mode=key_signature.mode)
    key.offset = key_signature.time
    return key
示例#8
0
def getKeyFromString(key):
    """Cached method. Calls music21.key.Key()."""
    cachedGetKeyFromString.append(key)
    return Key(key)
示例#9
0
def to_music21_key(key_signature: KeySignature) -> Key:
    """Return a KeySignature object as a music21 Key object."""
    key = Key(tonic=PITCH_NAMES[key_signature.root], mode=key_signature.mode)
    key.offset = key_signature.time
    return key
示例#10
0
def get_key(file):
    with open(file["path"], "r") as f:
        for line in f:
            m = key_signature_pattern.match(line)
            if m:
                return Key(sharpsToPitch(int(m.group(4))), m.group(5))
示例#11
0
def mixed_sequences(data_path, output_path):
    for (number, filename) in enumerate(os.listdir(data_path), start=1):
        try:
            full_path = os.path.join(data_path, filename)
            LOG.debug("Finding mixed sequences in piece {number}: {filename}.".
                      format(**locals()))
            piece = parse(full_path)
            temp_abspath = os.path.join(output_path, TEMP_MIDI_NAME)
            piece.write('midi', temp_abspath)
            chord_per_measure = temperley.chord_per_measure(
                piece, temp_abspath)
            keys = temperley.key_sequence(temp_abspath)
            if len(set(keys)) > 1:
                continue  # more than one key in piece is complicated...
            else:
                key_string = convertKeyStringToMusic21KeyString(
                    keys[0].replace('b', '-'))
                key = Key()
                key_pitch = key.getPitches()[0]
            instrument = lambda x: x.getInstrument().instrumentName.lower()
            guitar_parts = (e for e in piece if isinstance (e, Part) and \
                                             ('guitar' in instrument(e) or \
                                             'gtr' in instrument(e)) and not \
                                             'bass' in instrument(e))
            for part in guitar_parts:
                current_sequence = None
                last_note = None
                measures = [elem for elem in part if isinstance(elem, Measure)]
                if len(chord_per_measure) != len(measures):
                    continue
                for chord, measure in zip(chord_per_measure, measures):
                    chord_pitch = music21.pitch.Pitch(
                        convertKeyStringToMusic21KeyString(chord))
                    for element in measure:
                        if isinstance(element, Note):
                            if not last_note:
                                current_sequence = [
                                    (0, 0, notesToChromatic(
                                        key_pitch,
                                        element).semitones, key.mode,
                                     notesToChromatic(key_pitch,
                                                      chord_pitch).semitones)
                                ]
                            else:
                                interval = notesToChromatic(last_note, element)
                                entry = (current_sequence[-1][1],
                                         interval.semitones,
                                         notesToChromatic(key_pitch,
                                                          element).semitones,
                                         key.mode,
                                         notesToChromatic(
                                             key_pitch, chord_pitch).semitones)
                                current_sequence.append(entry)
                            last_note = element
                        elif isinstance(element,
                                        Rest) and element.quarterLength < 4:
                            pass
                        elif current_sequence:
                            yield current_sequence
                            current_sequence = None
                            last_note = None
        except Exception:
            LOG.warning(
                'Encountered exception in {filename}'.format(**locals()))