def _get_sounding_pitches(self): if "sounding pitch" in inspect(self).indicators(str): return self.written_pitches else: instrument = self._get_effective(instruments.Instrument) if instrument: sounding_pitch = instrument.middle_c_sounding_pitch else: sounding_pitch = abjad_pitch.NamedPitch("C4") interval = abjad_pitch.NamedPitch("C4") - sounding_pitch sounding_pitches = [ interval.transpose(pitch) for pitch in self.written_pitches ] return tuple(sounding_pitches)
def _to_relative_octave(self, pitch, reference): if pitch.pitch_class.number > reference.pitch_class.number: pair = (pitch.pitch_class.name, reference.octave.number) up_pitch = abjad_pitch.NamedPitch(pair) pair = (pitch.pitch_class.name, reference.octave.number - 1) down_pitch = abjad_pitch.NamedPitch(pair) up_octave = up_pitch.octave.number down_octave = down_pitch.octave.number else: pair = (pitch.pitch_class.name, reference.octave.number + 1) up_pitch = abjad_pitch.NamedPitch(pair) pair = (pitch.pitch_class.name, reference.octave.number) down_pitch = abjad_pitch.NamedPitch(pair) up_octave = up_pitch.octave.number down_octave = down_pitch.octave.number if abs( float(up_pitch._get_diatonic_pitch_number()) - float(reference._get_diatonic_pitch_number())) < abs( float(down_pitch._get_diatonic_pitch_number()) - float(reference._get_diatonic_pitch_number())): pair = ( up_pitch.pitch_class.name, up_octave + pitch.octave.number - 3, ) pitch = abjad_pitch.NamedPitch(pair) else: pair = ( down_pitch.pitch_class.name, down_octave + pitch.octave.number - 3, ) pitch = abjad_pitch.NamedPitch(pair) return pitch
def recurse(music): key_signatures = music._get_indicators( abjad_indicators.KeySignature) if key_signatures: for x in key_signatures: tonic = abjad_pitch.NamedPitch((x.tonic.name, 4)) # TODO: cheating to assign to a read-only property x._tonic = abjad_parser.LilyPondParser._transpose_enharmonically( from_pitch, to_pitch, tonic).pitch_class if isinstance(music, core.Note): music.written_pitch = abjad_parser.LilyPondParser._transpose_enharmonically( from_pitch, to_pitch, music.written_pitch) elif isinstance(music, core.Chord): for note_head in music.note_heads: note_head.written_pitch = abjad_parser.LilyPondParser._transpose_enharmonically( from_pitch, to_pitch, note_head.written_pitch) elif isinstance(music, core.Container): for x in music: recurse(x)
def p_pitch__PITCHNAME__commas(self, p): """ pitch : PITCHNAME commas """ p[0] = abjad_pitch.NamedPitch(str(p[1]) + ',' * p[2])
def p_pitch__PITCHNAME__apostrophes(self, p): """ pitch : PITCHNAME apostrophes """ p[0] = abjad_pitch.NamedPitch(str(p[1]) + "'" * p[2])
def p_pitch__PITCHNAME(self, p): """ pitch : PITCHNAME """ p[0] = abjad_pitch.NamedPitch(str(p[1]))
def __init__( self, *arguments, multiplier: typings.DurationTyping = None, tag: Tag = None, ) -> None: from abjad.ly import drums from .Note import Note assert len(arguments) in (0, 1, 2) self._note_heads = NoteHeadList(client=self) if len(arguments) == 1 and isinstance(arguments[0], str): string = f"{{ {arguments[0]} }}" parsed = parse(string) assert len(parsed) == 1 and isinstance(parsed[0], Leaf) arguments = tuple([parsed[0]]) are_cautionary: typing.List[typing.Optional[bool]] = [] are_forced: typing.List[typing.Optional[bool]] = [] are_parenthesized: typing.List[typing.Optional[bool]] = [] if len(arguments) == 1 and isinstance(arguments[0], Leaf): leaf = arguments[0] written_pitches = [] written_duration = leaf.written_duration if multiplier is None: multiplier = leaf.multiplier # TODO: move to dedicated from_note() constructor: if isinstance(leaf, Note) and leaf.note_head is not None: written_pitches.append(leaf.note_head.written_pitch) are_cautionary = [leaf.note_head.is_cautionary] are_forced = [leaf.note_head.is_forced] are_parenthesized = [leaf.note_head.is_parenthesized] elif isinstance(leaf, Chord): written_pitches.extend(x.written_pitch for x in leaf.note_heads) are_cautionary = [x.is_cautionary for x in leaf.note_heads] are_forced = [x.is_forced for x in leaf.note_heads] are_parenthesized = [x.is_parenthesized for x in leaf.note_heads] # TODO: move to dedicated constructor: elif len(arguments) == 2: written_pitches, written_duration = arguments if isinstance(written_pitches, str): written_pitches = [x for x in written_pitches.split() if x] elif isinstance(written_pitches, type(self)): written_pitches = written_pitches.written_pitches elif len(arguments) == 0: written_pitches = [abjad_pitch.NamedPitch(_) for _ in [0, 4, 7]] written_duration = Duration(1, 4) else: raise ValueError(f"can not initialize chord from {arguments!r}.") Leaf.__init__(self, written_duration, multiplier=multiplier, tag=tag) if not are_cautionary: are_cautionary = [None] * len(written_pitches) if not are_forced: are_forced = [None] * len(written_pitches) if not are_parenthesized: are_parenthesized = [None] * len(written_pitches) for written_pitch, is_cautionary, is_forced, is_parenthesized in zip( written_pitches, are_cautionary, are_forced, are_parenthesized ): if not is_cautionary: is_cautionary = None if not is_forced: is_forced = None if not is_parenthesized: is_parenthesized = None if written_pitch not in drums: note_head = NoteHead( written_pitch=written_pitch, is_cautionary=is_cautionary, is_forced=is_forced, is_parenthesized=is_parenthesized, ) else: assert isinstance(written_pitch, str), repr(written_pitch) note_head = DrumNoteHead( written_pitch=written_pitch, is_cautionary=is_cautionary, is_forced=is_forced, is_parenthesized=is_parenthesized, ) self._note_heads.append(note_head) if len(arguments) == 1 and isinstance(arguments[0], Leaf): self._copy_override_and_set_from_leaf(arguments[0])
def _transpose_enharmonically(pitch_a, pitch_b, pitch_c): """ Transpose ``pitch_c`` by the distance between ``pitch_b`` and ``pitch_a1``. This function was reverse-engineered from LilyPond's source code. Returns named pitch. """ def normalize_alteration(step, alteration): while 2.0 < alteration: alteration -= step_size(step) step += 1.0 while alteration < -2.0: step -= 1.0 alteration += step_size(step) return step, alteration def normalize_octave(octave, step): normalized_step = step % len(scale) octave += (step - normalized_step) / len(scale) return octave, normalized_step def step_size(step): normalized_step = step % len(scale) if normalized_step == 6: return 1.0 # b to c return scale[normalized_step + 1] - scale[normalized_step] if not isinstance(pitch_a, abjad_pitch.NamedPitch): pitch_a = abjad_pitch.NamedPitch(pitch_a) if not isinstance(pitch_b, abjad_pitch.NamedPitch): pitch_b = abjad_pitch.NamedPitch(pitch_b) if not isinstance(pitch_c, abjad_pitch.NamedPitch): pitch_c = abjad_pitch.NamedPitch(pitch_c) scale = [0.0, 2.0, 4.0, 5.0, 7.0, 9.0, 11.0] a_oct, a_step = ( pitch_a.octave.number, pitch_a._get_diatonic_pc_number(), ) b_oct, b_step = ( pitch_b.octave.number, pitch_b._get_diatonic_pc_number(), ) c_oct, c_step, c_alt = ( pitch_c.octave.number, pitch_c._get_diatonic_pc_number(), pitch_c.accidental.semitones, ) d_oct, d_step, d_tones = ( b_oct - a_oct, b_step - a_step, float(pitch_b.number) - float(pitch_a.number), ) tmp_alt = float(pitch_c.number) + d_tones # print 'TMP_ALT: %f' % tmp_alt new_oct = c_oct + d_oct new_step = c_step + d_step new_alt = c_alt # print 'NEW:', new_oct, new_step, new_alt new_step, new_alt = normalize_alteration(new_step, new_alt) new_oct, new_step = normalize_octave(new_oct, new_step) # print 'NEW(norm):', new_oct, new_step, new_alt octave_ticks = str(abjad_pitch.Octave(new_oct)) pitch_class_name = abjad_pitch.constants._diatonic_pc_number_to_diatonic_pc_name[ new_step % 7 ] # pitch_class_name = str(abjad_pitch.NamedDiatonicPitchClass( # int(new_step))) accidental = str(abjad_pitch.Accidental(new_alt)) tmp_pitch = abjad_pitch.NamedPitch(pitch_class_name + accidental + octave_ticks) # print 'TMP(pitch): %r' % tmp_pitch new_alt += tmp_alt - float(tmp_pitch.number) # print 'NEW(alt): %f' % new_alt new_step, new_alt = normalize_alteration(new_step, new_alt) new_oct, new_step = normalize_octave(new_oct, new_step) # print 'NEW(norm):', new_oct, new_step, new_alt octave_ticks = str(abjad_pitch.Octave(new_oct)) # pitch_class_name = str(abjad_pitch.NamedDiatonicPitchClass( # int(new_step))) pitch_class_name = abjad_pitch.constants._diatonic_pc_number_to_diatonic_pc_name[ new_step % 7 ] accidental = str(abjad_pitch.Accidental(new_alt)) return abjad_pitch.NamedPitch(pitch_class_name + accidental + octave_ticks)