Esempio n. 1
0
    def m21(self):

        score = Score()
        part = Part()
        bars = len(self) // self.bar_size

        measure = Measure()
        measure.insert(0.0, self.meter.m21)

        for bar in range(bars):

            start = bar * self.bar_size
            end = (bar + 1) * self.bar_size
            positions = [position % self.bar_size 
                for position in self.iter_onset_positions(start=start, end=end)
            ]
            # Append an extra position to make sure that the last ioi is
            # between the last note and the end of the bar
            positions.append(self.bar_size)
            offsets = [self.get_offset(p) for p in positions]
            iois = [b - a for a, b in zip(offsets[:-1], offsets[1:])]

            for offset, ioi in zip(offsets[:-1], iois):

                note = Note('a5')
                note.duration.quarterLength = ioi * 4.0
                measure.insert(offset * 4.0, note)

            part.append(measure)
            measure = Measure()

        score.append(part)
        return score.makeMeasures()
Esempio n. 2
0
def generateScore(chords, lengths=None, ts="4/4"):
    """Generates a four-part score from a sequence of chords.

    Soprano and alto parts are displayed on the top (treble) clef, while tenor
    and bass parts are displayed on the bottom (bass) clef, with correct stem
    directions.
    """
    if lengths is None:
        lengths = [1 for _ in chords]
    voices = [Voice([Piano()]) for _ in range(4)]
    for chord, length in zip(chords, lengths):
        bass, tenor, alto, soprano = [
            Note(p, quarterLength=length) for p in chord.pitches
        ]
        bass.addLyric(chord.lyric)
        bass.stemDirection = alto.stemDirection = "down"
        tenor.stemDirection = soprano.stemDirection = "up"
        voices[0].append(soprano)
        voices[1].append(alto)
        voices[2].append(tenor)
        voices[3].append(bass)

    female = Part([TrebleClef(), TimeSignature(ts), voices[0], voices[1]])
    male = Part([BassClef(), TimeSignature(ts), voices[2], voices[3]])
    score = Score([female, male])
    return score
Esempio n. 3
0
    def _matrix_to_part(self, submatrix):
        '''
        Takes a submatrix of size (T, D) and turn it into a music21.stream.Part
        object, where T is the number of time slices, and dim is the note
        vector.
        '''
        part = Part()
        pitches = submatrix[:, 0]
        articulations = submatrix[:, 1]

        current_note = None
        for current_tick in range(len(submatrix)):
            if articulations[current_tick]:  # if articulate
                # append the old note
                if current_note is not None:  # for the first note
                    part.append(current_note)

                # create a new note
                if pitches[current_tick] < self.rest:
                    current_note = Note()
                    # assign pitch, inverse of self._midi_to_input()
                    current_note.pitch.midi = pitches[current_tick]
                else:
                    current_note = Rest()
                # resets the duration to the smallest amount
                current_note.duration.quarterLength = self.unit_length
            else:
                current_note.duration.quarterLength += self.unit_length

        return part
Esempio n. 4
0
def make_music21_score(
    part_names=('violin', 'flute', 'oboe', 'clarinet', 'alto_saxophone',
                'trumpet', 'bass', 'percussion'),
    title='Title',
    composer='Jonathan Marmor',
    time_signature=None,
    starting_tempo_bpm=60,
    starting_tempo_quarter_duration=1.0,
    timestamp=None,
):
    if not timestamp:
        timestamp = datetime.datetime.utcnow()
    metadata = Metadata()
    metadata.title = title
    metadata.composer = composer
    metadata.date = timestamp.strftime('%Y/%m/%d')

    score = Score()
    score.insert(0, metadata)

    for part_name in part_names:

        instrument_name, instrument_number = parse_part_name(part_name)

        instrument = instrument_data[instrument_name]

        part = Part()

        metronome_mark = MetronomeMark(
            number=starting_tempo_bpm,
            referent=Duration(starting_tempo_quarter_duration))
        part.append(metronome_mark)

        if time_signature:
            # Should be a string like '12/8'
            music21_time_signature = TimeSignature(time_signature)
            part.append(music21_time_signature)

        m21_instrument = instrument['class']()
        m21_instrument.partName = instrument['name']
        m21_instrument.partAbbreviation = instrument['abbreviation']

        if instrument_number > 1:
            m21_instrument.partName = '{} {}'.format(instrument['name'],
                                                     instrument_number)
            m21_instrument.partAbbreviation = '{} {}'.format(
                instrument['abbreviation'], instrument_number)

        part.insert(0, m21_instrument)

        clef = instrument.get('clef')
        if clef:
            part.append(clef())

        score.insert(0, part)

    return score
Esempio n. 5
0
 def __init__(self, instruments):
     self.names = ['vln', 'gtr']
     self.vln = vln = Part()
     self.gtr = gtr = Part()
     self.l = [vln, gtr]
     self.d = {}
     for name, part, inst in zip(self.names, self.l, instruments.l):
         part.id = name
         self.d[name] = part
         part.insert(0, inst)
Esempio n. 6
0
def removeDuplicateTimeSigs(partToAdjust: stream.Part):
    currentTS = 'FAKE'
    timeSignatures = partToAdjust.recurse().getElementsByClass('TimeSignature')
    for ts in timeSignatures:
        if ts.ratioString == currentTS:
            partToAdjust.remove(ts, recurse=True)
        else:
            currentTS = ts.ratioString

    return partToAdjust
Esempio n. 7
0
def matchParts(referencePart: stream.Part, partToAdjust: stream.Part):
    """
    Resolve differences between two parts (here a score template and analysis part) with
    one defined as the reference part (score) and the other to be adjusted (analysis).
    Changes made:

    1. Number of measures.
    Often analyses have fewer measures than scores as the last chord is reached
    before the last measure, and those 'empty' measures are not explicitly encoded.
    This function adds empty measures to the analysis, padding it out so that they match up.

    2. Last measure duration.
    In the case of a part with an anacrusis, the first measures and last measure are incomplete:
    their combined value is equal to one full measure.
    Romantext supports the encoding of an anacrustic initial measure (e.g. m0 b3) but there
    is no equivalent way of setting the final measure's duration.
    This function shortens the final measure's duration to match that of the score
    in the case of a part with anacrusis (no action otherwise).

    3. Remove duplicated (redundant) time signatures.
    Where analyses have repeat measures, and where those measures have a time signature,
    the time signature is repeated leading to duplicates that are redundant.
    This is especially common when repeating the first measure.
    This function removes those redundant time signatures.
    TODO: promote this up to Roman text itself.

    :param referencePart: the 'model' part, defining the 'correct' values.
    :param partToAdjust: the part to alter according to values in the referencePart.
    :return: partToAdjust, altered.
    """

    # First and last measure duration
    referenceMeasures = referencePart.getElementsByClass('Measure')
    adjustMeasures = partToAdjust.getElementsByClass('Measure')
    measureDiff = len(referenceMeasures) - len(adjustMeasures)
    if measureDiff > 0:
        for x in range(measureDiff):
            partToAdjust.append(stream.Measure())

    # Anacrusis: incomplete first and last measures
    refFirst = referenceMeasures[0]
    if refFirst.duration != refFirst.barDuration:  # i.e. anacrusis
        refLast = referenceMeasures[-1]
        if refLast.duration != refLast.barDuration:
            adjustLast = adjustMeasures.getElementsByClass('Measure')[-1]
            adjustLast.splitAtQuarterLength(refLast.duration.quarterLength)

    removeDuplicateTimeSigs(partToAdjust)
    return partToAdjust
Esempio n. 8
0
def ParseMIDI(FilePath=str()):  #this function parse midi creating a list
    Majors =\
    {
        'C': 0, 'C#': -1, 'D-': -1, 'D': -2, 'D#': -3, 'E-': -3, 'E': -4, 'F': -5,
        'F#': 6, 'G-': 6, 'G': 5, 'G#': 4,'A-': 4, 'A': 3, 'A#': 2, 'B-': 2, 'B': 1
    } #major conversion
    Minors =\
    {
        'C': -3, 'C#': -4, 'D-': -4,'D': -5, 'D#': 6, 'E-': 6, 'E': 5, 'F': 4,
        'F#': 3, 'G-': 3, 'G': 2, 'G#': 1,'A-': 1, 'A': 0, 'A#': -1, 'B-': -1, 'B': -2
    } #minor conversion
    SemitoneShift = 0  #integer shifting for every note

    File = Converter.parse(FilePath)  #file reading
    Key = File.analyze('key')  #stream key extraction

    if Key.mode == 'major':  #checking if the key is in major
        SemitoneShift = Majors[Key.tonic.name]  #getting the shift
    elif Key.mode == 'minor':  #checking if the key is in minor
        SemitoneShift = Minors[Key.tonic.name]  #getting the shift

    FileTransposed = File.transpose(SemitoneShift)

    Stream = [Element
              for Element in FileTransposed.recurse()]  #stream list creation
    Parts = [
        Stream.index(Element) for Element in Stream
        if type(Element) == type(Part())
    ]  #getting indexes where to split
    Parts.append(
        len(Stream) - 1
    )  #adding the lenght of the stream to indexes (to get the end index of last part)

    return [Stream[Start:End] for Start, End in zip(Parts[:-1], Parts[1:])
            ]  #splitting stream in parts(instruments)
def notate_score(musician_names, instrument_names, music):
    score = Score()

    for musician_name, instrument_name in zip(musician_names,
                                              instrument_names):
        instrument = get_instrument(instrument_name)
        instrument.partName = instrument.instrumentName
        instrument.partAbbreviation = instrument.instrumentAbbreviation

        parts = []
        part = Part()
        parts.append(part)
        part.insert(0, instrument)

        score.insert(0, part)
        score.insert(0, StaffGroup(parts))

        notes = music[musician_name]

        for pitches in notes:
            if not pitches or pitches == 'stop':
                note = Rest()
            elif len(pitches) == 1:
                pitch = Pitch(pitches[0] + 60)
                note = Note(pitch)
            else:
                note = Chord(notes=[Pitch(p + 60) for p in pitches])

            duration = Duration()
            duration.fill([4.0])
            note.duration = duration

            part.append(note)

    score.show('musicxml', '/Applications/Sibelius 7.5.app')
Esempio n. 10
0
    def __init__(self, part_obj: StreamPart):

        self.instrument = part_obj.partName
        self.notes = part_obj.notes
        # self.notes_and_rests = part_obj.notesAndRests
        self.pitch_differences = []
        self.harmony = None
        self.roman_numerals = None
        self.pitch_vector = None
        self.duration_progression = None
        self.get_pitch_differences()
        self.chord_progression = part_obj.chordify()
        self.get_harmonic_reduction()
        self.convert_harmonic_to_roman_numerals()
        self.get_duration_progression()
Esempio n. 11
0
def generate_song(chord_length=15,show_symbols=False):
   '''Generate a random chord progression with a piano/bass comp and
      return as a Music21 score. Default length of 15 chord changes
      (plus the fixed ones at start/end) makes a score about one A4 page.'''
   # Start with a blank score
   score = Score()
   # TODO: Add swing rhythm indicator without having to do it manually
   # in musescore (how to with music21?)

   # Add tracks/intstruments - names etc will be set automatically
   piano = Part()
   piano.insert(0, Piano())
   score.insert(0,piano)

   bass = Part()
   bass.insert(0, AcousticBass())
   score.insert(0,bass)

   #hihat = Part()   TODO drum kit

   # Get a random progression
   prog = ProgressionGenerator()
   prog.generate(chord_length)

   # Go through the progression, adding a comp for each chord
   for chord_choice in prog.chords:
      roman = RomanNumeral(chord_choice)   # Convert string into a generic Roman I/IV/etc chord

      # Duration = eights until the next chord change.
      # at least 1 bar on "important" chords (I,IV,V)
      if chord_choice in ('Imaj7', 'IVmaj7', 'V7'):
         duration = random.choice((8,8,8,8,10,10,12,12,14,16))
      else: # 1 bar or less on "minor" (pun intended) chords
         duration = random.choice((2,4,4,4,6,6,8,8,8,8))

      add_piano_riff(roman, duration, piano, show_symbols)
      add_bass_walk(roman, duration, bass)
      # TODO drum part

   # ending riff on last bar or two
   duration = random.choice((8,8,16))
   add_piano_closing(RomanNumeral('Imaj7'), duration, piano, show_symbols)
   add_bass_closing(RomanNumeral('Imaj7'), duration, bass)
   return score
def write_notation_cell(music, path, event_index):
    score = Score()

    metadata = Metadata()
    metadata.title = ''
    metadata.composer = ''
    score.insert(0, metadata)

    layout = ScoreLayout()
    layout.scalingMillimeters = 1.25
    layout.scalingTenths = 40
    score.insert(0, layout)

    for musician in music:
        instrument_name = musician['instrument']
        instrument = get_instrument(instrument_name)
        instrument.partName = instrument.instrumentName
        if instrument.instrumentName is 'Violoncello':
            instrument.partName = 'Cello'
        instrument.partAbbreviation = instrument.instrumentAbbreviation

        parts = []
        part = Part()
        parts.append(part)
        part.insert(0, instrument)

        score.insert(0, part)
        # score.insert(0, StaffGroup(parts))

        for event in musician['music']:
            pitches = event['pitches']
            dur = event['duration']
            # if not pitches or pitches == 'stop':
            #     note = Rest()
            if len(pitches) == 1:
                pitch = Pitch(pitches[0] + 60)
                note = Note(pitch)
            else:
                note = Chord(notes=[Pitch(p + 60) for p in pitches])

            duration = Duration()
            duration.fill([dur])
            note.duration = duration

            part.append(note)

    file_path = os.path.join(path, str(event_index).zfill(2))
    musicxml_file_path = file_path + '.xml'
    png_output_file_path = file_path + '.png'

    score.write('musicxml', musicxml_file_path)

    write_png_with_musescore(musicxml_file_path, png_output_file_path, dpi=600)
Esempio n. 13
0
def setup_parts(instruments, score):
    parts = []
    for instrument in instruments:
        part = Part()
        m21_instrument = get_instrument(instrument['name'])

        part.insert(0, m21_instrument)
        if instrument.get('clef') is 'bass':
            part.insert(0, BassClef())

        parts.append(part)
        score.insert(0, part)

    score.insert(0, StaffGroup(parts))

    return parts
Esempio n. 14
0
def parse_track(part: Part, resolution=DEFAULT_RESOLUTION) -> Track:
    """Return track parsed from a music21 Part object.

    Parameters
    ----------
    part : `music21.stream.Part`
        Part object to parse.
    resolution : int, optional
        Time steps per quarter note. Defaults to
        `muspy.DEFAULT_RESOLUTION`.

    Returns
    -------
    :class:`muspy.Track`
        Parsed track.

    """
    notes, chords = parse_notes_and_chords(part, resolution)

    instrument = part.getInstrument()

    if instrument.midiProgram is not None:
        program = instrument.midiProgram
    else:
        program = 0

    if instrument.midiChannel is not None:
        is_drum = instrument.midiChannel == 10
    else:
        is_drum = False

    return Track(
        program=program,
        is_drum=is_drum,
        name=part.partName,
        notes=notes,
        chords=chords,
    )
Esempio n. 15
0
def get_part(length, list_value):
    part = Part()
    instrument_index = list_value.get({
        'min': 0,
        'max': len(INSTRUMENTS_CLASSES) - 1
    })
    instrument_class = INSTRUMENTS_CLASSES[instrument_index]
    set_instrument(part, instrument_class())
    for _ in range(length):
        note_pred = list_value.get({'min': 0, 'max': 1}, is_int=False)
        duration = list_value.get(DURATION, is_int=False)
        is_chord = note_pred > 0.2
        if is_chord:
            num_of_notes = list_value.get(NUM_OF_NOTES)
            velocity = list_value.get(VELOCITY)
            notes = []
            for _ in range(num_of_notes):
                note = list_value.get(PITCH)
                notes.append(note)
            append_chord(part, notes, duration, velocity)
        else:
            append_rest(part, duration)
    return part
Esempio n. 16
0
    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


if __name__ == "__main__":
  """
  How to create Mupix Objects.
  """
  from music21.stream import Score, Part, Measure
  from music21.key import KeySignature
  from music21.note import Note  # noqa

  s = Score()
  p1 = Part(id="part1")
  m1 = Measure(number=1)
  m1.append(KeySignature(3))
  m1.append(Note("C4", type="eighth"))
  m2 = Measure(number=2)
  m2.append(KeySignature(0))
  m2.append(Note("G4", type="eighth"))
  p1.append([m1, m2])
  s.append([p1])

  notes = [NoteObject(item, 1) for item in s.recurse().notes if not item.isChord]
  print(notes)
Esempio n. 17
0
def part(sequence):
    part = Part()
    for elem in sequence:
        part.append(elem)
    return part
Esempio n. 18
0
def to_music21(music: "Music") -> Score:
    """Return a Music object as a music21 Score object.

    Parameters
    ----------
    music : :class:`muspy.Music`
        Music object to convert.

    Returns
    -------
    `music21.stream.Score`
        Converted music21 Score object.

    """
    # Create a new score
    score = Score()

    # Metadata
    if music.metadata:
        score.append(to_music21_metadata(music.metadata))

    # Tracks
    for track in music.tracks:
        # Create a new part
        part = Part()
        part.partName = track.name

        # Add tempos
        for tempo in music.tempos:
            part.append(to_music21_metronome(tempo))

        # Add time signatures
        for time_signature in music.time_signatures:
            part.append(to_music21_time_signature(time_signature))

        # Add key signatures
        for key_signature in music.key_signatures:
            part.append(to_music21_key(key_signature))

        # Add notes to part
        for note in track.notes:
            m21_note = M21Note(_get_pitch_name(note.pitch))
            m21_note.offset = note.time / music.resolution
            m21_note.quarterLength = note.duration / music.resolution
            part.append(m21_note)

        # Append the part to score
        score.append(part)

    return score
Esempio n. 19
0
def tensors_to_stream(outputs, config, metadata=None):
    cur_measure_number = 0
    parts = {}
    for part_name in outputs.keys():
        if part_name == 'extra':
            continue
        part = Part(id=part_name)
        parts[part_name] = part

    last_time_signature = None
    cur_time_signature = '4/4'
    for step in range(outputs['soprano'].shape[0]):
        extra = outputs['extra'][step]
        if extra[indices_extra['has_time_signature_3/4']].item() == 1:
            cur_time_signature = '3/4'
        elif extra[indices_extra['has_time_signature_4/4']].item() == 1:
            cur_time_signature = '4/4'
        elif extra[indices_extra['has_time_signature_3/2']].item() == 1:
            cur_time_signature = '3/2'
        cur_time_pos = extra[indices_extra['time_pos']].item()
        has_fermata = extra[indices_extra['has_fermata']].item() == 1

        if cur_time_pos == 1.0 or cur_measure_number == 0:
            for part_name, part in parts.items():
                part.append(Measure(number=cur_measure_number))
                if cur_measure_number == 0:
                    if part_name in ['soprano', 'alto']:
                        part[-1].append(clef.TrebleClef())
                    else:
                        part[-1].append(clef.BassClef())
                    key = int(
                        torch.argmax(
                            outputs['extra'][0, indices_extra['has_sharps_0']:
                                             indices_extra['has_sharps_11'] +
                                             1],
                            dim=0).item())
                    if key >= 6:
                        key -= 12
                    part[-1].append(KeySignature(key))
                    part[-1].append(MetronomeMark(number=90))
            cur_measure_number += 1

        if last_time_signature is None or cur_time_signature != last_time_signature:
            for part in parts.values():
                part[-1].append(TimeSignature(cur_time_signature))
            last_time_signature = cur_time_signature

        for part_name, part in parts.items():
            idx = torch.argmax(outputs[part_name][step]).item()
            if idx == indices_parts['is_continued']:
                try:
                    last_element = part[-1].flat.notesAndRests[-1]
                    cur_element = deepcopy(last_element)
                    if last_element.tie is not None and last_element.tie.type == 'stop':
                        last_element.tie = Tie('continue')
                    else:
                        last_element.tie = Tie('start')
                    cur_element.tie = Tie('stop')
                except IndexError:
                    logging.debug(
                        'Warning: "is_continued" on first beat. Replaced by rest.'
                    )
                    cur_element = Rest(quarterLength=config.time_grid)
                part[-1].append(cur_element)
            elif idx == indices_parts['is_rest']:
                part[-1].append(Rest(quarterLength=config.time_grid))
            else:
                pitch = Pitch()
                part[-1].append(Note(pitch, quarterLength=config.time_grid))
                # Set pitch value AFTER appending to measure in order to avoid unnecessary accidentals
                pitch.midi = idx + min_pitches[part_name] - len(indices_parts)

        if has_fermata:
            for part in parts.values():
                fermata = Fermata()
                fermata.type = 'upright'
                part[-1][-1].expressions.append(fermata)

    score = Score()
    if metadata is not None:
        score.append(Metadata())
        score.metadata.title = f"{metadata.title} ({metadata.number})"
        score.metadata.composer = f"Melody: {metadata.composer}\nArrangement: BachNet ({datetime.now().year})"
    for part in parts.values():
        part[-1].rightBarline = 'light-heavy'

    score.append(parts['soprano'])
    if 'alto' in parts:
        score.append(parts['alto'])
        score.append(parts['tenor'])
    score.append(parts['bass'])

    score.stripTies(inPlace=True, retainContainers=True)

    return score
Esempio n. 20
0
def CompileSong(ClassifiedStream=None,
                FileName=str(),
                ClosestApprox=True,
                UpperApprox=False,
                Split=False):
    if ClosestApprox and UpperApprox:  #closest approximation is preferred if both are active
        UpperApprox = False  #turning off upper semiton approximation

    if not ClosestApprox and not UpperApprox:  #ensuring there is an approximation method
        ClosestApprox = True  #default approximation method

    UpperSemitone =\
    {
        'C-': 'C', 'C': 'C', 'C#': 'D', 'D-': 'D', 'D': 'D', 'D#': 'E', 'E-': 'E',
        'E': 'E', 'E#': 'F', 'F-': 'F', 'F' : 'F', 'F#': 'G', 'G-': 'G', 'G': 'G',
        'G#': 'A', 'A-': 'A', 'A': 'A', 'A#': 'B', 'B-': 'B', 'B': 'B', 'B#': 'C',
    } #upper approximation map
    ClosestSemitone =\
    {
        'C-': 'C', 'C': 'C', 'C#': 'C', 'D-': 'D', 'D': 'D', 'D#': 'D', 'E-': 'E',
        'E': 'E', 'E#': 'E', 'F-': 'F', 'F' : 'F', 'F#': 'F', 'G-': 'G', 'G': 'G',
        'G#': 'G', 'A-': 'A', 'A': 'A', 'A#': 'A', 'B-': 'B', 'B': 'B', 'B#': 'B',
    } #clostest approximation map

    for Part in ClassifiedStream:  #for loop for every part
        for Element in Part[:]:  #for loop for every element
            if Element[
                    'Type'] == 'Part':  #checking if the element is a stream part
                Part.remove(Element)
            elif Element['Type'] == 'Key':  #checking if the element is key
                Element['Extra'] = str(
                    Element['Extra'].tonic.name + ' ' +
                    Element['Extra'].mode)  #turning key to string
            elif Element['Type'] == 'Note':  #checking if the element is a note
                if ClosestApprox:  #checking the approximation method
                    Element['Sound'] = ClosestSemitone[
                        Element['Sound']]  #remapping the sound
                elif UpperApprox:  #checking the approximation method
                    Element['Sound'] = UpperSemitone[
                        Element['Sound']]  #remapping the sound
            elif Element['Type'] == 'Chord':  #checkinf the element is a chord
                if ClosestApprox:  #checking the approximation method
                    Element['Sound'] = [
                        ClosestSemitone[Note] for Note in Element['Sound']
                    ]  #remapping the sound
                elif UpperApprox:  #checking the approximation method
                    Element['Sound'] = [
                        UpperSemitone[Note] for Note in Element['Sound']
                    ]  #remapping the sound

    if Split:  #check if the user wants to split tracks
        Tracks = [i for i in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ']  #name for subtracks
        if len(Tracks) > len(
                ClassifiedStream):  #check what element has more tracks
            for i in range(len(ClassifiedStream)
                           ):  #for loop for every track in the MIDI file
                FilePart = f'MappedSongs/{FileName}[{Tracks[i]}].cmid'  #new name of the file
                Part = [ClassifiedStream[i]]  #list of single part of MIDI file

                with open(FilePart,
                          'wb') as OutputFile:  #creating a compiled file
                    Data = Dumps(Part,
                                 protocol=HighestProtocol)  #serializing data
                    OutputFile.write(Data)  #writing data to the file
        else:
            for i in range(
                    len(Tracks)
            ):  #for loop for every track in the MIDI file (will cut all the tracks next to 26)
                FilePart = f'MappedSongs/{FileName}[{Tracks[i]}].cmid'  #new name of the file
                Part = [ClassifiedStream[i]]  #list of single part of MIDI file

                with open(FilePArt,
                          'wb') as OutputFile:  #creating a compiled file
                    Data = Dumps(Part,
                                 protocol=HighestProtocol)  #serializing data
                    OutputFile.write(Data)  #writing data to the file

    else:
        FileName = f'MappedSongs/{FileName}.cmid'  #completed file name + path
        with open(FileName, 'wb') as OutputFile:  #creating a compiled file
            Data = Dumps(ClassifiedStream,
                         protocol=HighestProtocol)  #serializing data
            OutputFile.write(Data)  #writing data to the file
def read_vmf_string(vmf_string):
    """
    Reads VMF data from a string to a Score Stream.

    :param vmf_string: The contents of the VMF file as a string.
    :return: A music21 score instance containing the music in the VMF file.
    """

    parts_converted = {}

    vmf = json.loads(vmf_string)

    # create a score
    score = Score()

    # Get the initial data
    number_of_parts = vmf['header']['number_of_parts']
    number_of_voices = vmf['header']['number_of_voices']
    smallest_note = float(Fraction(vmf['header']['tick_value']))

    # create the parts and first measure.
    for voice_number in range(number_of_parts):
        part = Part()
        voice = Voice()

        part.append(voice)

        score.append(part)

    # get the body of the vmf
    body = vmf['body']

    part_number = 0

    # We do this because we want to do each part at a time.
    for voice_number in range(number_of_voices):
        # Get all ticks for a given part.
        part = [tick[voice_number] for tick in body]

        current_element = None
        current_voice = None

        # iterate over each tick
        for tick in part:

            if current_voice is None:
                # Get the parent part if it exists.
                try:
                    current_part = parts_converted[tick[-1]]

                    # add a new voice and write to it.
                    voice = Voice()

                    initial_key_signature = KeySignature(vmf['header']['key_signature']['0.0'])
                    initial_time_signature = TimeSignature(vmf['header']['time_signature']['0.0'])

                    voice.append(initial_key_signature)
                    voice.append(initial_time_signature)

                    current_part.append(voice)

                except KeyError:
                    # Add it to our dictionary otherwise.
                    current_part = score.parts[part_number]
                    part_number += 1

                    parts_converted[tick[-1]] = current_part

                # Get the last voice.
                current_voice = current_part.voices[-1]

            if tick[0] == 1:
                if current_element is not None:
                    # check for precision and adjust
                    rounded = round(current_element.quarterLength)
                    if abs(current_element.quarterLength - rounded) < PRECISION:
                        current_element.quarterLength = rounded

                    # append to the part
                    current_voice.append(current_element)

                # Find how many notes to write. This will always be an int.
                number_of_notes = int(find_number_of_notes_in_tick(tick))

                if number_of_notes == 1:
                    # create a new note
                    current_element = Note(Pitch(pitchClass=tick[3], octave=tick[4]))
                else:
                    pitches = []

                    # create the pitches.
                    # From the beginning to the end of the pitch section of the tick.
                    for i in range(FIRST_PITCH_INDEX, FIRST_PITCH_INDEX + 2 * number_of_notes, 2):
                        pitch = Pitch(pitchClass=tick[i], octave=tick[i + 1])
                        pitches.append(pitch)

                    # create a new chord with these pitches.
                    current_element = Chord(pitches)


                # set the velocity of the note.
                current_element.volume.velocity = DynamicConverter.vmf_to_velocity(tick[DYNAMIC_BIT])
                # set the articulation
                if tick[ARTICULATION_BIT] != 0:
                    current_element.articulations.append(
                        ArticulationConverter.vmf_to_articulation(tick[ARTICULATION_BIT]))

                # set the value for this tick.
                current_element.quarterLength = smallest_note
            elif tick[0] == 2:
                # extend previous note
                current_element.quarterLength += smallest_note

            elif tick[0] == 0 and (isinstance(current_element, note.Note) or current_element is None):
                if current_element is not None:
                    # check for precision and adjust
                    rounded = round(current_element.quarterLength)
                    if abs(current_element.quarterLength - rounded) < PRECISION:
                        current_element.quarterLength = rounded

                    # append to the part
                    current_voice.append(current_element)

                # create new rest
                current_element = Rest()

                # Set the value for this tick.
                current_element.quarterLength = smallest_note

            elif tick[0] == 0 and isinstance(current_element, note.Rest):
                # extend previous rest.
                current_element.quarterLength += smallest_note

        # Append the last element in progress.
        if current_element is not None:
            # check for precision and adjust
            rounded = round(current_element.quarterLength)
            if abs(current_element.quarterLength - rounded) < PRECISION:
                current_element.quarterLength = rounded

            # append to the part
            current_voice.append(current_element)

    # create the stream for time signature changes
    time_signature_stream = Stream()

    for offset, time_signature_str in sorted(vmf['header']['time_signature'].items()):
        time_signature = TimeSignature(time_signature_str)
        time_signature_stream.append(time_signature)
        time_signature_stream[-1].offset = float(offset)

    # finish up the file.
    for part in score.parts:
        for voice in part.voices:
            voice.makeMeasures(inPlace=True, meterStream=time_signature_stream)

        for offset, t in sorted(vmf['header']['tempo'].items()):
            mm = tempo.MetronomeMark(number=t, referent=note.Note(type='quarter'))
            voice.insert(offset, mm)

        for offset, ks in sorted(vmf['header']['key_signature'].items()):
            voice.insert(offset, KeySignature(ks))

    return score
Esempio n. 22
0
from music21.metadata import Metadata
from music21.duration import Duration
from music21.layout import StaffGroup
from music21.instrument import fromString as get_instrument
from music21.clef import BassClef

timestamp = datetime.datetime.utcnow()
metadata = Metadata()
metadata.title = 'The Title'
metadata.composer = 'Jonathan Marmor'
metadata.date = timestamp.strftime('%Y/%m/%d')

score = Score()
score.insert(0, metadata)

part = Part()
parts = [part]

oboe = get_instrument('oboe')
part.insert(0, oboe)
score.insert(0, part)
score.insert(0, StaffGroup(parts))

for dur in [[1, .5], [.25], [.25, 2]]:
    pitch = Pitch(60)
    note = Note(pitch)
    duration = Duration()
    duration.fill(dur)
    note.duration = duration

    part.append(note)
def _setup_parts():
    top = Part()
    top.append(TimeSignature('4/4'))
    bottom = Part()
    bottom.append(TimeSignature('4/4'))
    return top, bottom