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
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)
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')
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
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
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)
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
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
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
def part(sequence): part = Part() for elem in sequence: part.append(elem) return part
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
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)
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