def notate_note(self, note): if note['pitch'] == 'rest': n = Rest() else: if isinstance(note['pitch'], list): pitches = [] for pitch_number in note['pitch']: p = Pitch(pitch_number) # Force all flats if p.accidental.name == 'sharp': p = p.getEnharmonic() pitches.append(p) n = Chord(notes=pitches) else: p = Pitch(note['pitch']) # Force all flats if p.accidental.name == 'sharp': p = p.getEnharmonic() n = Note(p) d = Duration() if note['duration'] == 0: d.quarterLength = .125 d = d.getGraceDuration() else: d.fill(note['durations']) n.duration = d return n
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 __init__(self, original_figure: str = None, spotify_figure: str = None, figure: str = None, bass: str = None, root: str = None, kind: str = None): # This is the original figure, which is kept because it is needed to create a SpotifyChord equivalent to THIS # SpotifyChordSymbol self.original_figure = original_figure if spotify_figure == 'NC': self.bass = None self.root = None self.structure = 'NC' elif figure: assert root self.bass = Pitch(bass[1:]) if bass else None if self.bass: self.bass.octave = None self.root = Pitch(root) self.root.octave = None self.structure = figure else: assert root and kind chord_symbol = ChordSymbol(bass=bass[1:], root=root, kind=kind) self.bass = Pitch(bass[1:]) if bass else None if self.bass: self.bass.octave = None self.root = Pitch(root) self.root.octave = None self.structure = chord_symbol.figure
def move_pitch(note: Pitch, pitch: Pitch) -> Note: while abs(note.midi - pitch.midi) > 6: dist = note.midi - pitch.midi if dist < 0: note = note.transpose(12) else: note = note.transpose(-12) return note
def generate_closed_chord(self, root_note: PitchInit, anchor_note: PitchInit = "C4", max_notes: int = 5, bass_note: Optional[PitchInit] = None, include_root: bool = True): if isinstance(root_note, str): root_note = Pitch(root_note) if isinstance(anchor_note, str): anchor_note = Pitch(anchor_note) if isinstance(bass_note, str): bass_note = Pitch(bass_note) if max_notes < 2: raise ValueError("Not really a chord with only one or no notes.") chord_heap = [] third = root_note.transpose(self.third_quality.interval) fifth = root_note.transpose(self.fifth_quality.interval) harmonies = [root_note.transpose(harm.interval) for harm in self.harmonies] heappush(chord_heap, (9, third)) for harmony in harmonies: heappush(chord_heap, (7, harmony)) heappush(chord_heap, (1, fifth)) if include_root: heappush(chord_heap, (3, root_note)) if self.upper_quality is not None: heappush(chord_heap, (9, (root_note.transpose(self.upper_quality.interval)))) while len(chord_heap) > max_notes: heappop(chord_heap) chord_base = Chord(note for _, note in chord_heap) chord_base.sortDiatonicAscending(inPlace=True) chord_base = move_chord(chord_base, anchor_note) chord_base = chord_base.closedPosition() inversions = all_inversions(chord_base) inversions = [move_chord(c, anchor_note) for c in inversions] best_option = min(inversions, key=lambda x: chord_mad(x, anchor_note)) if bass_note is not None: bass_note = move_pitch(bass_note, anchor_note.transpose(-12)) best_option.add(bass_note, runSort=True) return best_option
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 split(figure): _figure = figure.replace('bpedal', '-pedal') root = match(r'[A-Ga-g][#-]*', _figure).group() _figure = _figure.replace(root, '', 1) root_pitch = Pitch(root) root = str(root_pitch) bass = search(r'/[A-Ga-g][#-]*', _figure) structure = _figure.replace(bass.group(), '', 1) if bass else _figure if bass: bass_pitch = Pitch(bass.group()[1:]) bass = '/' + str(bass_pitch) return root, structure.strip(), bass if bass else ''
def make_music21_note( pitch_number=None, duration=1.0, staccato=False, tenuto=False, accent=False, falloff=False, plop=False, scoop=False, doit=False, breath_mark=False, ): if pitch_number == None or pitch_number == 'rest': n = Rest() elif isinstance(pitch_number, list): pitches = [Pitch(p) for p in pitch_number] for p in pitches: if p.accidental.name is 'natural': p.accidental = None n = Chord(pitches) else: p = Pitch(pitch_number) if p.accidental.name is 'natural': p.accidental = None n = Note(p) d = Duration() d.quarterLength = duration n.duration = d if staccato: n.articulations.append(Staccato()) if tenuto: n.articulations.append(Tenuto()) if accent: n.articulations.append(Accent()) if falloff: n.articulations.append(Falloff()) if plop: n.articulations.append(Plop()) if scoop: n.articulations.append(Scoop()) if doit: n.articulations.append(Doit()) if breath_mark: n.articulations.append(BreathMark()) return n
def _transpose_pitch_in_scale_space( original_pitch: pitch.Pitch, steps: int, reference_scale: scale.ConcreteScale, ) -> pitch.Pitch: if steps == 0: return if steps > 0: direction = "ascending" else: direction = "descending" steps *= -1 new_pitch = reference_scale.next(original_pitch, direction, steps) original_pitch.step = new_pitch.step original_pitch.octave = new_pitch.octave original_pitch.accidental = new_pitch.accidental
def transposed_to( self, pitch: Pitch = Pitch()) -> Tuple['SpotifyChord', Optional[Interval]]: if self.is_no_chord(): return self, None tr_int = interval.notesToInterval(self.root, pitch) return self.transposed_by(tr_int), tr_int
def testCopyAndDeepcopy(self): ''' Test copying all objects defined in this module ''' for part in sys.modules[self.__module__].__dict__: match = False for skip in ['_', '__', 'Test', 'Exception']: if part.startswith(skip) or part.endswith(skip): match = True if match: continue name = getattr(sys.modules[self.__module__], part) # noinspection PyTypeChecker if callable(name) and not isinstance(name, types.FunctionType): try: # see if obj can be made w/ args obj = name() except TypeError: continue copy.copy(obj) copy.deepcopy(obj) p1 = Pitch('C#3') p2 = copy.deepcopy(p1) self.assertIsNot(p1, p2) self.assertIsNot(p1.accidental, p2.accidental)
def plot_instrument_ranges(sounds): inst_info = {(snd.short_name, snd.low_no, snd.high_no, snd.section): None for snd in sounds}.keys() color_map = { Section.PERCUSSION: "orange", Section.WOODWINDS: "green", Section.BRASS: "red", Section.STRINGS: "blue", } names, lows, highs, sections = zip(*inst_info) fig, ax = plt.subplots(figsize=(6, 6)) ax.barh( y=list(range(len(names))), left=lows, width=[high - low for (low, high) in zip(lows, highs)], tick_label=names, color=[color_map[sec] for sec in sections], ) # grid at Cs and Gs xticks = sorted(list(range(24, 111, 12)) + list(range(19, 111, 12))) ax.set_xticks(xticks) ax.set_xticklabels([Pitch(no) for no in xticks], rotation=0) ax.grid(axis="x", which="major") ax.set_title("Instrument Ranges") plt.tight_layout() plt.show()
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
def main(): parser = get_cmd_line_parser(description=__doc__) ParserArguments.filename(parser) ParserArguments.tempo(parser) ParserArguments.framerate(parser) ParserArguments.set_defaults(parser) ParserArguments.best(parser) args = parser.parse_args() defaults.framerate = args.framerate song = Stream() roots = 'ABCDEFG' scales = [scale.MajorScale, scale.MinorScale, scale.WholeToneScale, scale.ChromaticScale] print('Choosing a random scale from Major, Minor, Whole Tone, Chromatic.') rscale = random.choice(scales)(Pitch(random.choice(roots))) print('Using: %s' % rscale.name) print('Generating a score...') random_note_count = 50 random_note_speeds = [0.5, 1] print('100 Random 1/8th and 1/4th notes in rapid succession...') for i in range(random_note_count): note = Note(random.choice(rscale.pitches)) note.duration.quarterLength = random.choice(random_note_speeds) song.append(note) scale_practice_count = 4 print('Do the scale up and down a few times... maybe %s' % scale_practice_count) rev = rscale.pitches[:] rev.reverse() updown_scale = rscale.pitches[:] updown_scale.extend(rev[1:-1]) print('updown scale: %s' % updown_scale) for count, pitch in enumerate(cycle(updown_scale)): print(' note %s, %s' % (count, pitch)) song.append(Note(pitch)) if count >= scale_practice_count * len(updown_scale): break print('Composition finished:') song.show('txt') if args.best: print('Audifying the song to file "{}"...') wave = audify_to_file(song, args.tempo, args.filename, verbose=True) else: wave = audify_basic(song, args.tempo, verbose=True) print('Writing Song to file "{}"...'.format(args.filename)) with wav_file_context(args.filename) as fout: fout.write_frames(wave.frames) return 0
def testQuarterToneA(self): p1 = Pitch('D#~') # environLocal.printDebug([p1, p1.accidental]) self.assertEqual(str(p1), 'D#~') # test generation of raw musicxml output xmlOut = m21ToXml.GeneralObjectExporter().parse(p1).decode('utf-8') match = '<step>D</step><alter>1.5</alter><octave>4</octave>' xmlOut = xmlOut.replace(' ', '') xmlOut = xmlOut.replace('\n', '') self.assertNotEqual(xmlOut.find(match), -1) s = stream.Stream() for pStr in ['A~', 'A#~', 'A`', 'A-`']: p = Pitch(pStr) self.assertEqual(str(p), pStr) n = note.Note() n.pitch = p s.append(n) self.assertEqual(len(s), 4) match = [e.pitch.ps for e in s] self.assertEqual(match, [69.5, 70.5, 68.5, 67.5]) s = stream.Stream() alterList = [ None, 0.5, 1.5, -1.5, -0.5, 'half-sharp', 'one-and-a-half-sharp', 'half-flat', 'one-and-a-half-flat', '~' ] sc = scale.MajorScale('c4') for x in range(1, 10): n = note.Note(sc.pitchFromDegree(x % sc.getDegreeMaxUnique())) n.quarterLength = 0.5 n.pitch.accidental = Accidental(alterList[x]) s.append(n) match = [str(n.pitch) for n in s.notes] self.assertEqual(match, [ 'C~4', 'D#~4', 'E-`4', 'F`4', 'G~4', 'A#~4', 'B`4', 'C-`4', 'D~4' ]) match = [e.pitch.ps for e in s] self.assertEqual( match, [60.5, 63.5, 62.5, 64.5, 67.5, 70.5, 70.5, 58.5, 62.5])
def valid_voicing(s): """Verifies a string of 4 space-separated pitches as a valid voicing.""" pitchStrings = s.split() if len(pitchStrings) != 4: msg = "The voicing should have exactly 4 notes" raise argparse.ArgumentTypeError(msg) b, t, a, s = [Pitch(p) for p in pitchStrings] if not b <= t <= a <= s: msg = "The notes of the given voicing should be ordered BTAS" raise argparse.ArgumentTypeError(msg) return tuple(pitchStrings)
def voiceNote(noteName, pitchRange): """Generates voicings for a note in a given pitch range. Returns a list of `Pitch` objects with the same name as the note that also fall within the voice's range. """ lowerOctave = pitchRange[0].octave upperOctave = pitchRange[1].octave for octave in range(lowerOctave, upperOctave + 1): n = Pitch(noteName + str(octave)) if pitchRange[0] <= n <= pitchRange[1]: yield n
def __init__(self): self.names = ['vln', 'gtr'] self.vln = vln = Violin() self.gtr = gtr = AcousticGuitar() self.l = [vln, gtr] self.d = {} for name, inst in zip(self.names, self.l): inst.nickname = name self.d[name] = inst # lowest, highest notes ranges = [ ('G3', 'B6'), # Violin ('E2', 'G5') # Guitar ] for r, i in zip(ranges, self.l): i.lowest_note = Pitch(r[0]) i.highest_note = Pitch(r[1]) i.all_notes = list(frange(i.lowest_note.ps, i.highest_note.ps + 1)) i.all_notes_24 = list( frange(i.lowest_note.ps, i.highest_note.ps + 1, 0.5))
def notate_note(note): if note['pitch'] == 'rest': n = Rest() else: if isinstance(note['pitch'], list): pitches = [] for pitch_number in note['pitch']: p = Pitch(pitch_number) # Force all flats if p.accidental.name == 'sharp': p = p.getEnharmonic() pitches.append(p) n = Chord(notes=pitches) else: p = Pitch(note['pitch']) # Force all flats if p.accidental.name == 'sharp': p = p.getEnharmonic() n = Note(p) d = Duration() if note['duration'] == 0: d.quarterLength = .125 d = d.getGraceDuration() else: # music21 docs say `fill` is for testing. I can't remember why I chose # to use it originally. It works. But not for tuplets. Maybe this blog # post contains a better solution: # http://music21-mit.blogspot.com/2015/09/durations-and-durationtuples.html d.fill(note['durations']) n.duration = d return n
def testUpdateAccidentalDisplaySimple(self): '''Test updating accidental display. ''' past = [Pitch('A#3'), Pitch('C#'), Pitch('C')] a = Pitch('c') a.accidental = Accidental('natural') a.accidental.displayStatus = True self.assertEqual(a.name, 'C') self.assertTrue(a.accidental.displayStatus) a.updateAccidentalDisplay(pitchPast=past, overrideStatus=True) self.assertFalse(a.accidental.displayStatus) b = copy.deepcopy(a) self.assertFalse(b.accidental.displayStatus) self.assertEqual(b.accidental.name, 'natural')
def __init__(self, spotify_figure: str = None, figure: str = None, bass: str = None, root: str = None, kind: str = None, chord: Chord = None): if spotify_figure == 'NC': self.bass = None self.root = None self.chord = Chord() self.structure = 'NC' elif chord: assert root and figure self.bass = Pitch(bass[1:]) if bass else None self.root = Pitch(root) self.chord = chord self.structure = spotify_figure if spotify_figure else figure elif figure: assert root chord_symbol = ChordSymbol(figure=figure) self.chord = Chord(chord_symbol.pitches) self.bass = Pitch(bass[1:]) if bass else None if self.bass: self.bass.octave = None self.root = Pitch(root) self.root.octave = None self.structure = figure else: assert root and kind chord_symbol = ChordSymbol(bass=bass, root=root, kind=kind) self.chord = Chord(chord_symbol.pitches) self.bass = Pitch(bass) if bass else None if self.bass: self.bass.octave = None self.root = Pitch(root) self.root.octave = None self.structure = chord_symbol.figure
def freq_to_midi(freq): base_pitch = Pitch() current_interval = Interval( integer_interval_from(freq, base_pitch.frequency)) return base_pitch.transpose(current_interval).midi
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
def main1(): all_pitches = MajorScale(tonic="C").getPitches("C1", "C8") pitch2index = {p: ix for ix, p in enumerate(all_pitches)} C2 = Pitch("C2") C3 = Pitch("C3") C4 = Pitch("C4") C5 = Pitch("C5") C6 = Pitch("C6") def get_next_triplets(triplet: Triplet) -> Set[Triplet]: next_triplets = set() for i, pitch in enumerate(triplet.pitches): # TODO: improve construct_graph to accept negative values here for diff in [1]: # TODO: make this a utility function moved_pitch = all_pitches[pitch2index[pitch] + diff] if moved_pitch in triplet.pitches: continue next_pitches = tuple( p if i != j else moved_pitch for j, p in enumerate(triplet.pitches) ) if ( not C2 <= next_pitches[0] <= C4 or not C3 <= next_pitches[1] <= C5 or not C4 <= next_pitches[2] <= C6 ): continue next_triplets.add(Triplet(next_pitches)) return next_triplets init_pitches = (Pitch("C2"), Pitch("C3"), Pitch("C4")) init_triplet = Triplet(init_pitches) _, edges = construct_graph(init_triplet, get_next_triplets, 48) G = nx.DiGraph() G.add_edges_from(edges) plot_hierarchical_graph(G) # blocking progression = [] chord = init_triplet while chord: progression.append(chord) successors = list(G.successors(chord)) if successors: chord = successors[len(successors) // 2] else: chord = None print(progression) sounds, _ = midi.initialize() _ = query_sound(sounds, Section.STRINGS, Instrument.BASSES, Articulation.SPICCATO) celli = query_sound( sounds, Section.STRINGS, Instrument.CELLI, Articulation.SPICCATO ) violas = query_sound( sounds, Section.STRINGS, Instrument.VIOLAS, Articulation.SPICCATO ) violins = query_sound( sounds, Section.STRINGS, Instrument.VIOLINS_1, Articulation.SPICCATO ) _ = query_sound(sounds, Section.BRASS, Instrument.TUBA, Articulation.STACCATISSIMO) trombones = query_sound( sounds, Section.BRASS, Instrument.TENOR_TROMBONES_A3, Articulation.STACCATISSIMO ) trumpets = query_sound( sounds, Section.BRASS, Instrument.TRUMPETS_A3, Articulation.STACCATISSIMO ) horns = query_sound( sounds, Section.BRASS, Instrument.HORNS_A4, Articulation.STACCATISSIMO ) strings = (celli, violas, violins) brass = (trombones, trumpets, horns) dt = 0.175 dur = 0.125 p = Player() for measure, triplet in enumerate(progression): for beat in range(4): for note, snd in zip(triplet.pitches, strings): p.schedule(snd, Pitch(note).midi, (beat + measure * 4) * dt, dur, 100) for note, snd in zip(triplet.pitches, brass): p.schedule(snd, Pitch(note).midi, measure * 4 * dt, dur * 2, 100) p.schedule(snd, Pitch(note).midi, (measure * 4 + 3.25) * dt, dur * 0.5, 100) p.play()
def __post_init__(self): self.low_no = Pitch(self.low).midi self.high_no = Pitch(self.high).midi
import copy import argparse import itertools from fractions import Fraction from music21.note import Note from music21.pitch import Pitch from music21.chord import Chord from music21.roman import RomanNumeral from music21.key import Key from music21.meter import TimeSignature from music21.clef import BassClef, TrebleClef from music21.instrument import Piano from music21.stream import Part, Score, Voice SOPRANO_RANGE = (Pitch("C4"), Pitch("G5")) ALTO_RANGE = (Pitch("G3"), Pitch("C5")) TENOR_RANGE = (Pitch("C3"), Pitch("G4")) BASS_RANGE = (Pitch("E2"), Pitch("C4")) def voiceNote(noteName, pitchRange): """Generates voicings for a note in a given pitch range. Returns a list of `Pitch` objects with the same name as the note that also fall within the voice's range. """ lowerOctave = pitchRange[0].octave upperOctave = pitchRange[1].octave for octave in range(lowerOctave, upperOctave + 1): n = Pitch(noteName + str(octave))
def __init__(self, n, piece, movement, quadlet, couplet, lines): self.n = n self.piece = piece self.movement = movement self.quadlet = quadlet self.couplet = couplet self.lines = lines self.duration = quadlet.phrase_duration self.first = False if n == 1 and couplet.n == 1: self.first = True for line in lines: # print ('.' * int(line['rhythm'][0] * 2)) + ('-' * int(line['rhythm'][1] * 2)) + ('.' * int(line['rhythm'][2] * 2)) part = piece.parts.d[line['instrument']] measure = Measure() if self.first and quadlet.previous_phrase_duration != self.duration: ts = TimeSignature('{}/4'.format(self.duration), self.duration) # ts.beatSequence.partitionByList(subdivide(self.duration, 4)) # for i, b in enumerate(ts.beatSequence): # if b.duration.quarterLength == 4: # ts.beatSequence[i] = b.subdivide(2) # # ts.beatSequence[i][0] = b.subdivide(2) # # ts.beatSequence[i][1] = b.subdivide(2) # elif b.duration.quarterLength == 3: # ts.beatSequence[i] = b.subdivideByList([2, 1]) # # ts.beatSequence[i][0] = ts.beatSequence[i].subdivide(2) # elif b.duration.quarterLength == 2: # ts.beatSequence[i] = b.subdivide(2) measure.timeSignature = ts r1_dur, note_dur, r2_dur = line['rhythm'] line['notes'] = [] if r1_dur > 0: line['notes'].append({ 'duration': r1_dur, 'pitch': 'rest' }) line['notes'].append({ 'duration': note_dur, 'pitch': line['pitch'] }) if r2_dur > 0: line['notes'].append({ 'duration': r2_dur, 'pitch': 'rest' }) self.fix_durations(line['notes']) for note in line['notes']: if note['pitch'] == 'rest': n = Rest() else: p = Pitch(note['pitch']) # Force all flats if p.accidental.name == 'sharp': p = p.getEnharmonic() n = Note(p) # TODO add slurs # TODO add glissandos # TODO add -50 cent marks d = Duration() d.fill(note['durations']) n.duration = d measure.append(n) # if r1_dur > 0: # r1 = Rest() # r1.duration = Duration(r1_dur) # measure.append(r1) # p = Pitch(line['pitch']) # # Force all flats # if p.accidental.name == 'sharp': # p = p.getEnharmonic() # note = Note(p) # note.duration = Duration(note_dur) # measure.append(note) # if r2_dur > 0: # r2 = Rest() # r2.duration = Duration(r2_dur) # measure.append(r2) part.append(measure) # Put full measure rests in instruments that aren't playing playing = [line['instrument'] for line in lines] resting = [i for i in piece.instruments.names if i not in playing] for i in resting: # print '.' * self.duration * 2 part = piece.parts.d[i] measure = Measure() if self.first and quadlet.previous_phrase_duration != self.duration: ts = TimeSignature('{}/4'.format(self.duration), self.duration) # ts.beatSequence.subdivideNestedHierarchy(3) # ts.beatSequence.partitionByList(subdivide(self.duration, 4)) # for i, b in enumerate(ts.beatSequence): # if b.duration.quarterLength == 4: # ts.beatSequence[i] = b.subdivide(2) # # ts.beatSequence[i][0] = b.subdivide(2) # # ts.beatSequence[i][1] = b.subdivide(2) # elif b.duration.quarterLength == 3: # ts.beatSequence[i] = b.subdivideByList([2, 1]) # # ts.beatSequence[i][0] = ts.beatSequence[i].subdivide(2) # elif b.duration.quarterLength == 2: # ts.beatSequence[i] = b.subdivide(2) measure.timeSignature = ts r = Rest() r.duration = Duration(self.duration) measure.append(r) # fixed_measure = measure.sliceByBeat() # part.append(fixed_measure) part.append(measure)
Rule.SEVENTH_UNPREPARED: Cost.BAD, Rule.SEVENTH_UNRESOLVED: Cost.VERYBAD, Rule.LEADINGTONE_UNRESOLVED: Cost.VERYBAD, # voicing rules Rule.VERTICAL_NOT_DOUBLINGROOT: Cost.NOTIDEAL, Rule.VERTICAL_SEVENTH_MISSINGNOTE: Cost.MAYBEBAD, } def applyRule(rule): """Given a rule enum, provide the cost of breaking that rule.""" return _ruleCostMapping[rule] voice_ranges = { PartEnum.SOPRANO: (Pitch("C4"), Pitch("G5")), PartEnum.ALTO: (Pitch("G3"), Pitch("D5")), PartEnum.TENOR: (Pitch("C3"), Pitch("G4")), PartEnum.BASS: (Pitch("E2"), Pitch("C4")), } verticalHorizontalMapping = { IntervalV.ALTO_SOPRANO: (PartEnum.SOPRANO, PartEnum.ALTO), IntervalV.TENOR_SOPRANO: (PartEnum.TENOR, PartEnum.SOPRANO), IntervalV.TENOR_ALTO: (PartEnum.TENOR, PartEnum.ALTO), IntervalV.BASS_SOPRANO: (PartEnum.BASS, PartEnum.SOPRANO), IntervalV.BASS_ALTO: (PartEnum.BASS, PartEnum.ALTO), IntervalV.BASS_TENOR: (PartEnum.BASS, PartEnum.TENOR), }
def midi_to_name(midi): return Pitch(midi).nameWithOctave
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) score.show('musicxml', '/Applications/Sibelius 7.5.app')
def transposePitchFromC(self, p: pitch.Pitch, *, inPlace=False) -> Optional[pitch.Pitch]: ''' Takes a pitch in C major and transposes it so that it has the same step position in the current key signature. >>> ks = key.KeySignature(-3) >>> p1 = pitch.Pitch('B') >>> p2 = ks.transposePitchFromC(p1) >>> p2.name 'D' Original pitch is unchanged: >>> p1.name 'B' >>> ks2 = key.KeySignature(2) >>> p2 = ks2.transposePitchFromC(p1) >>> p2.name 'C#' For out of scale pitches the relationship still works; note also that original octave is preserved. >>> p3 = pitch.Pitch('G-4') >>> p4 = ks.transposePitchFromC(p3) >>> p4.nameWithOctave 'B--4' If inPlace is True then nothing is returned and the original pitch is modified. >>> p5 = pitch.Pitch('C5') >>> ks.transposePitchFromC(p5, inPlace=True) >>> p5.nameWithOctave 'E-5' New method in v6. ''' transInterval = None transTimes = 0 originalOctave = p.octave if not inPlace: p = copy.deepcopy(p) if self.sharps == 0: if inPlace: return else: return p elif self.sharps < 0: transTimes = abs(self.sharps) transInterval = interval.Interval('P4') else: transTimes = self.sharps transInterval = interval.Interval('P5') for i in range(transTimes): transInterval.transposePitch(p, inPlace=True) if originalOctave is not None: p.octave = originalOctave if not inPlace: return p
def __init__(self, ranges=False): score = self.score = Score() self.instruments = self.i = Instruments() self.parts = Parts(self.i) # Make Metadata timestamp = datetime.datetime.utcnow() metadata = Metadata() metadata.title = 'Early Montreal' metadata.composer = 'Jonathan Marmor' metadata.date = timestamp.strftime('%Y/%m/%d') score.insert(0, metadata) [score.insert(0, part) for part in self.parts.l] score.insert(0, StaffGroup(self.parts.l)) if ranges: # Don't make a piece, just show the instrument ranges for inst, part in zip(self.instruments.l, self.parts.l): measure = Measure() measure.timeSignature = TimeSignature('4/4') low = Note(inst.lowest_note) measure.append(low) high = Note(inst.highest_note) measure.append(high) part.append(measure) return # 18 to 21 minutes piece_duration_minutes = scale(random.random(), 0, 1, 18, 21) # Make the "songs" songs = [] total_minutes = 0 n = 1 while total_minutes < piece_duration_minutes: print 'Song {}'.format(n) n += 1 song = Song(self) songs.append(song) total_minutes += song.duration_minutes # Make notation previous_duration = None for song in songs: for bar in song.bars: for part in bar.parts: measure = Measure() if bar.tempo: measure.insert(0, MetronomeMark(number=bar.tempo, referent=Duration(1))) measure.leftBarline = 'double' if bar.duration != previous_duration: ts = TimeSignature('{}/4'.format(bar.duration)) measure.timeSignature = ts # Fix Durations durations = [note['duration'] for note in part['notes']] components_list = split_at_beats(durations) components_list = [join_quarters(note_components) for note_components in components_list] for note, components in zip(part['notes'], components_list): note['durations'] = components for note in part['notes']: if note['pitch'] == 'rest': n = Rest() if isinstance(note['pitch'], list): pitches = [] for pitch_number in note['pitch']: p = Pitch(pitch_number) # Force all flats if p.accidental.name == 'sharp': p = p.getEnharmonic() pitches.append(p) n = Chord(notes=pitches) # TODO add slurs # TODO add glissandos # TODO add -50 cent marks else: p = Pitch(note['pitch']) # Force all flats if p.accidental.name == 'sharp': p = p.getEnharmonic() n = Note(p) # TODO add slurs # TODO add glissandos # TODO add -50 cent marks d = Duration() if note['duration'] == 0: d.quarterLength = .5 d = d.getGraceDuration() else: d.fill(note['durations']) n.duration = d measure.append(n) self.parts.d[part['instrument_name']].append(measure) previous_duration = bar.duration
def getPitchFromString(p): """Cached method. Calls music21.pitch.Pitch().""" cachedGetPitchFromString.append(p) return Pitch(p)
def __init__(self, number, piece, movement): self.number = number self.piece = piece self.movement = movement instrument_opts = piece.instruments.names[:] self.note_opts = {} for name in instrument_opts: self.note_opts[name] = piece.i.d[name].all_notes form = self.form = song_forms.choose() self.duration = len(form) * 4 self.type = 'solo' if number % 2: self.type = 'ensemble' if self.type == 'solo': if len(movement.solo_ensemble_options) == 0: movement.solo_ensemble_options = piece.i.get_unison_ensembles(min_notes=6) print 'Hey, we ran out of unison ensembles! Cool!' solo_ensemble_hash = random.choice(movement.solo_ensemble_options.keys()) self.soloists = movement.solo_ensemble_options[solo_ensemble_hash]['instruments'] self.soloist_names = [s.nickname for s in self.soloists] self.soloists_shared_notes = movement.solo_ensemble_options[solo_ensemble_hash]['notes'] # Remove chosen ensemble from options del movement.solo_ensemble_options[solo_ensemble_hash] # remove chosen soloists from instrument options for the song for soloist in self.soloist_names: instrument_opts.remove(soloist) self.accompanist_names = instrument_opts len_accompanists = len(self.accompanist_names) if len_accompanists == 2: ensemble_size = 2 elif len_accompanists == 3: ensemble_size = random.choice([2, 3]) elif len_accompanists == 4: ensemble_size = random.choice([1, 2, 3, 4]) self.accompanist_names = random.sample(self.accompanist_names, ensemble_size) else: # who plays, who sits out? # ensemble_size = weighted_choice([3, 4, 5, 6], [1, 4, 5, 4]) # self.ensemble_names = random.sample(instrument_opts, ensemble_size) # Everyone plays self.ensemble_names = instrument_opts # make a phrase for each unique part of the form (eg, an `a` in `abacabac`) unique_phrases = [] for f in set(form): if self.type == 'solo': PhraseClass = SoloPhrase elif self.type == 'ensemble': PhraseClass = EnsemblePhrase unique_phrases.append(PhraseClass(piece, movement, self)) # Copy the phrases in the order specified by form phrases = [] for f in form: phrases.append(unique_phrases[f]) # Render phrases as music21 objects for phrase in phrases: for part in phrase.parts: measure = Measure() if movement.first_measure: ts = TimeSignature('4/4') # ts.beatSequence = ts.beatSequence.subdivide(4) ts.beamSequence = ts.beamSequence.subdivide(4) # ts.beatSequence.partitionByList(subdivide(self.duration, 4)) # for i, b in enumerate(ts.beatSequence): # if b.duration.quarterLength == 4: # ts.beatSequence[i] = b.subdivide(2) # # ts.beatSequence[i][0] = b.subdivide(2) # # ts.beatSequence[i][1] = b.subdivide(2) # elif b.duration.quarterLength == 3: # ts.beatSequence[i] = b.subdivideByList([2, 1]) # # ts.beatSequence[i][0] = ts.beatSequence[i].subdivide(2) # elif b.duration.quarterLength == 2: # ts.beatSequence[i] = b.subdivide(2) measure.timeSignature = ts # ts.getBeams() self.fix_durations(part['notes']) for note in part['notes']: if note['pitch'] == 'rest': n = Rest() else: p = Pitch(note['pitch']) # Force all flats if p.accidental.name == 'sharp': p = p.getEnharmonic() n = Note(p) # TODO add slurs # TODO add glissandos # TODO add -50 cent marks d = Duration() d.fill(note['durations']) n.duration = d measure.append(n) # if len(measure.notesAndRests) > 1: # measure.sliceByBeat(inPlace=True) # measure.makeBeams(inPlace=True) piece.parts.d[part['instrument_name']].append(measure) movement.first_measure = False