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
Ejemplo n.º 2
0
    def testPitchEquality(self):
        '''
        Test updating accidental display.
        '''
        data = [
            ('a', 'b', False),
            ('a', 'a', True),
            ('a#', 'a', False),
            ('a#', 'b-', False),
            ('a#', 'a-', False),
            ('a##', 'a#', False),
            ('a#4', 'a#4', True),
            ('a-3', 'a-4', False),
            ('a#3', 'a#4', False),
        ]
        for x, y, match in data:
            p1 = Pitch(x)
            p2 = Pitch(y)
            self.assertEqual(p1 == p2, match)
        # specific case of changing octave
        p1 = Pitch('a#')
        p2 = Pitch('a#')
        self.assertEqual(p1, p2)

        p1.octave = 4
        p2.octave = 3
        self.assertNotEqual(p1, p2)
        p1.octave = 4
        p2.octave = 4
        self.assertEqual(p1, p2)
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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')
Ejemplo n.º 5
0
    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 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 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)
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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 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
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
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
Ejemplo n.º 13
0
    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')
Ejemplo n.º 14
0
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
Ejemplo n.º 15
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])
Ejemplo n.º 16
0
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)
Ejemplo n.º 17
0
    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))
Ejemplo n.º 18
0
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,
              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
Ejemplo n.º 20
0
    def testUpdateAccidentalDisplaySeries(self):
        '''Test updating accidental display.
        '''
        def proc(_pList, past):
            for p in _pList:
                p.updateAccidentalDisplay(pitchPast=past)
                past.append(p)

        def compare(past, _result):
            # environLocal.printDebug(['accidental compare'])
            for i in range(len(_result)):
                p = past[i]
                if p.accidental is None:
                    pName = None
                    pDisplayStatus = None
                else:
                    pName = p.accidental.name
                    pDisplayStatus = p.accidental.displayStatus

                targetName = _result[i][0]
                targetDisplayStatus = _result[i][1]

                self.assertEqual(
                    pName, targetName,
                    f'name error for {i}: {pName} instead of desired {targetName}'
                )
                self.assertEqual(
                    pDisplayStatus, targetDisplayStatus,
                    f'{i}: {p} display: {pDisplayStatus}, target {targetDisplayStatus}'
                )

        # alternating, in a sequence, same pitch space
        pList = [
            Pitch('a#3'),
            Pitch('a3'),
            Pitch('a#3'),
            Pitch('a3'),
            Pitch('a#3')
        ]
        result = [('sharp', True), ('natural', True), ('sharp', True),
                  ('natural', True), ('sharp', True)]
        proc(pList, [])
        compare(pList, result)

        # alternating, in a sequence, different pitch space
        pList = [
            Pitch('a#2'),
            Pitch('a6'),
            Pitch('a#1'),
            Pitch('a5'),
            Pitch('a#3')
        ]
        result = [('sharp', True), ('natural', True), ('sharp', True),
                  ('natural', True), ('sharp', True)]
        proc(pList, [])
        compare(pList, result)

        # alternating, after gaps
        pList = [
            Pitch('a-2'),
            Pitch('g3'),
            Pitch('a5'),
            Pitch('a#5'),
            Pitch('g-3'),
            Pitch('a3')
        ]
        result = [('flat', True), (None, None), ('natural', True),
                  ('sharp', True), ('flat', True), ('natural', True)]
        proc(pList, [])
        compare(pList, result)

        # repeats of the same: show at different registers
        pList = [
            Pitch('a-2'),
            Pitch('a-2'),
            Pitch('a-5'),
            Pitch('a#5'),
            Pitch('a#3'),
            Pitch('a3'),
            Pitch('a2')
        ]
        result = [('flat', True), ('flat', False), ('flat', True),
                  ('sharp', True), ('sharp', True), ('natural', True),
                  ('natural', True)]
        proc(pList, [])
        compare(pList, result)

        # the always- 'unless-repeated' setting
        # first, with no modification, repeated accidentals are not shown
        pList = [Pitch('a-2'), Pitch('a#3'), Pitch('a#5')]
        result = [('flat', True), ('sharp', True), ('sharp', True)]
        proc(pList, [])
        compare(pList, result)

        # second, with status set to always
        pList = [Pitch('a-2'), Pitch('a#3'), Pitch('a#3')]
        pList[2].accidental.displayType = 'always'
        result = [('flat', True), ('sharp', True), ('sharp', True)]
        proc(pList, [])
        compare(pList, result)

        # status set to always
        pList = [Pitch('a2'), Pitch('a3'), Pitch('a5')]
        pList[2].accidental = Accidental('natural')
        pList[2].accidental.displayType = 'always'
        result = [(None, None), (None, None), ('natural', True)]
        proc(pList, [])
        compare(pList, result)

        # first use after other pitches in different register
        # note: this will force the display of the accidental
        pList = [Pitch('a-2'), Pitch('g3'), Pitch('a-5')]
        result = [('flat', True), (None, None), ('flat', True)]
        proc(pList, [])
        compare(pList, result)

        # first use after other pitches in different register
        # note: this will force the display of the accidental
        pList = [Pitch('a-2'), Pitch('g3'), Pitch('a-2')]
        # pairs of accidental, displayStatus
        result = [('flat', True), (None, None), ('flat', True)]
        proc(pList, [])
        compare(pList, result)

        # accidentals, first usage, not first pitch
        pList = [Pitch('a2'), Pitch('g#3'), Pitch('d-2')]
        result = [(None, None), ('sharp', True), ('flat', True)]
        proc(pList, [])
        compare(pList, result)
Ejemplo n.º 21
0
def midi_to_name(midi):
    return Pitch(midi).nameWithOctave
Ejemplo n.º 22
0
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
Ejemplo n.º 23
0
def get_mapping(samples, starting_point):
    if isinstance(starting_point, str):
        starting_point = Pitch(starting_point).midi
    mapping = {s: i + starting_point for i, s in enumerate(samples)}
    mapping[' '] = 0
    return mapping
Ejemplo n.º 24
0
    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),
}
Ejemplo n.º 25
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
Ejemplo n.º 26
0
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()
Ejemplo n.º 27
0
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))
Ejemplo n.º 28
0
 def __post_init__(self):
     self.low_no = Pitch(self.low).midi
     self.high_no = Pitch(self.high).midi
Ejemplo n.º 29
0
def getPitchFromString(p):
    """Cached method. Calls music21.pitch.Pitch()."""
    cachedGetPitchFromString.append(p)
    return Pitch(p)
Ejemplo n.º 30
0
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')