def from_pitch_carriers(cls, pitch_carrier_1, pitch_carrier_2): '''Calculate named interval from `pitch_carrier_1` to `pitch_carrier_2`: :: >>> pitchtools.NamedInterval.from_pitch_carriers( ... NamedPitch(-2), ... NamedPitch(12), ... ) NamedInterval('+M9') Returns named interval. ''' from abjad.tools import pitchtools pitch_1 = pitchtools.get_named_pitch_from_pitch_carrier(pitch_carrier_1) pitch_2 = pitchtools.get_named_pitch_from_pitch_carrier(pitch_carrier_2) degree_1 = pitch_1.diatonic_pitch_number degree_2 = pitch_2.diatonic_pitch_number named_interval_number = abs(degree_1 - degree_2) + 1 numbered_interval_number = abs( pitchtools.NumberedPitch(pitch_1).pitch_number - pitchtools.NumberedPitch(pitch_2).pitch_number ) absolute_named_interval = \ pitchtools.spell_numbered_interval_number( named_interval_number, numbered_interval_number) if pitch_2 < pitch_1: named_interval = -absolute_named_interval else: named_interval = absolute_named_interval return cls(named_interval)
def from_pitch_carriers(cls, pitch_carrier_1, pitch_carrier_2): '''Makes numbered interval from `pitch_carrier_1` and `pitch_carrier_2`. :: >>> pitchtools.NumberedInterval.from_pitch_carriers( ... NamedPitch(-2), ... NamedPitch(12), ... ) NumberedInterval(14) Returns numbered interval. ''' from abjad.tools import pitchtools # get pitches pitch_1 = pitchtools.NamedPitch.from_pitch_carrier(pitch_carrier_1) pitch_2 = pitchtools.NamedPitch.from_pitch_carrier(pitch_carrier_2) # get difference in semitones number = pitchtools.NumberedPitch(pitch_2).pitch_number - \ pitchtools.NumberedPitch(pitch_1).pitch_number # change 1.0, 2.0, ... into 1, 2, ... number = mathtools.integer_equivalent_number_to_integer(number) # return numbered interval return cls(number)
def _transpose_pitch_carrier_by_numbered_interval(pitch_carrier, numbered_interval): mci = pitchtools.NumberedInterval(numbered_interval) if isinstance(pitch_carrier, pitchtools.Pitch): number = pitch_carrier.pitch_number + mci.semitones return type(pitch_carrier)(number) elif isinstance(pitch_carrier, numbers.Number): pitch_carrier = pitchtools.NumberedPitch(pitch_carrier) result = _transpose_pitch_carrier_by_numbered_interval( pitch_carrier, mci) return result.pitch_number elif isinstance(pitch_carrier, scoretools.Note): new_note = copy.copy(pitch_carrier) number = pitchtools.NumberedPitch( pitch_carrier.written_pitch).pitch_number number += mci.number new_pitch = pitchtools.NamedPitch(number) new_note.written_pitch = new_pitch return new_note elif isinstance(pitch_carrier, scoretools.Chord): new_chord = copy.copy(pitch_carrier) pairs = zip(new_chord.note_heads, pitch_carrier.note_heads) for new_nh, old_nh in pairs: number = \ pitchtools.NumberedPitch(old_nh.written_pitch).pitch_number number += mci.number new_pitch = pitchtools.NamedPitch(number) new_nh.written_pitch = new_pitch return new_chord else: return pitch_carrier
def invert(self, axis=None): r'''Inverts numbered pitch-class. .. container:: example >>> for n in range(12): ... pitch_class = abjad.NumberedPitchClass(n) ... print(repr(pitch_class), repr(pitch_class.invert())) ... NumberedPitchClass(0) NumberedPitchClass(0) NumberedPitchClass(1) NumberedPitchClass(11) NumberedPitchClass(2) NumberedPitchClass(10) NumberedPitchClass(3) NumberedPitchClass(9) NumberedPitchClass(4) NumberedPitchClass(8) NumberedPitchClass(5) NumberedPitchClass(7) NumberedPitchClass(6) NumberedPitchClass(6) NumberedPitchClass(7) NumberedPitchClass(5) NumberedPitchClass(8) NumberedPitchClass(4) NumberedPitchClass(9) NumberedPitchClass(3) NumberedPitchClass(10) NumberedPitchClass(2) NumberedPitchClass(11) NumberedPitchClass(1) Interprets axis of inversion equal to pitch-class 0. Returns new numbered pitch-class. ''' from abjad.tools import pitchtools axis = axis or pitchtools.NumberedPitch('c') axis = pitchtools.NumberedPitch(axis) this = pitchtools.NumberedPitch(self) interval = this - axis result = axis.transpose(interval) result = type(self)(result) return result
def _get_intervals_in_subrun(subrun_source): from abjad.tools import pitchtools subrun_source = list(subrun_source) result = [0] for first, second in sequencetools.iterate_sequence_nwise(subrun_source): first_pitch = pitchtools.get_named_pitch_from_pitch_carrier(first) second_pitch = pitchtools.get_named_pitch_from_pitch_carrier(second) interval = pitchtools.NumberedPitch(second_pitch).pitch_number - \ pitchtools.NumberedPitch(first_pitch).pitch_number result.append(interval + result[-1]) result.pop(0) return result
def invert(self, axis=None): r'''Inverts numbered pitch-class. Interprets axis of inversion equal to pitch-class 0. Returns new numbered pitch-class. ''' from abjad.tools import pitchtools axis = axis or pitchtools.NumberedPitch('c') axis = pitchtools.NumberedPitch(axis) this = pitchtools.NumberedPitch(self) interval = this - axis result = axis.transpose(interval) result = type(self)(result) return result
def interpolate(self, stop_pitch, fraction): r'''Interpolates between numbered pitch and `stop_pitch` by `fraction`. .. container:: example Interpolates from C4 to C5: >>> start_pitch = abjad.NumberedPitch(0) >>> stop_pitch = abjad.NumberedPitch(12) >>> start_pitch.interpolate(stop_pitch, abjad.Fraction(0)) NumberedPitch(0) >>> start_pitch.interpolate(stop_pitch, abjad.Fraction(1, 4)) NumberedPitch(3) >>> start_pitch.interpolate(stop_pitch, abjad.Fraction(1, 2)) NumberedPitch(6) >>> start_pitch.interpolate(stop_pitch, abjad.Fraction(3, 4)) NumberedPitch(9) >>> start_pitch.interpolate(stop_pitch, abjad.Fraction(1)) NumberedPitch(12) .. container:: example Interpolates from C5 to C4: >>> start_pitch = abjad.NumberedPitch(12) >>> stop_pitch = abjad.NumberedPitch(0) >>> start_pitch.interpolate(stop_pitch, abjad.Fraction(0)) NumberedPitch(12) >>> start_pitch.interpolate(stop_pitch, abjad.Fraction(1, 4)) NumberedPitch(9) >>> start_pitch.interpolate(stop_pitch, abjad.Fraction(1, 2)) NumberedPitch(6) >>> start_pitch.interpolate(stop_pitch, abjad.Fraction(3, 4)) NumberedPitch(3) >>> start_pitch.interpolate(stop_pitch, abjad.Fraction(1)) NumberedPitch(0) Returns new numbered pitch. ''' from abjad.tools import pitchtools assert 0 <= fraction <= 1, repr(fraction) stop_pitch = type(self)(stop_pitch) distance = stop_pitch - self distance = abs(distance.semitones) distance = fraction * distance distance = int(distance) if stop_pitch < self: distance *= -1 pitch_number = self.number pitch_number = pitch_number + distance pitch = pitchtools.NumberedPitch(pitch_number) if self <= stop_pitch: triple = (self, pitch, stop_pitch) assert self <= pitch <= stop_pitch, triple else: triple = (self, pitch, stop_pitch) assert self >= pitch >= stop_pitch, triple return pitch
def from_pitch_carriers(class_, pitch_carrier_1, pitch_carrier_2): '''Makes numbered interval from `pitch_carrier_1` and `pitch_carrier_2`. .. container:: example >>> abjad.NumberedInterval.from_pitch_carriers( ... abjad.NamedPitch(-2), ... abjad.NamedPitch(12), ... ) NumberedInterval(14) >>> abjad.NumberedInterval.from_pitch_carriers( ... abjad.NamedPitch(12), ... abjad.NamedPitch(12), ... ) NumberedInterval(0) >>> abjad.NumberedInterval.from_pitch_carriers( ... abjad.NamedPitch(9), ... abjad.NamedPitch(12), ... ) NumberedInterval(3) >>> abjad.NumberedInterval.from_pitch_carriers( ... abjad.NamedPitch(12), ... abjad.NamedPitch(9), ... ) NumberedInterval(-3) >>> abjad.NumberedInterval.from_pitch_carriers( ... abjad.NamedPitch(12), ... abjad.NamedPitch(-2), ... ) NumberedInterval(-14) Returns numbered interval. ''' from abjad.tools import pitchtools pitch_1 = pitchtools.NamedPitch.from_pitch_carrier(pitch_carrier_1) pitch_2 = pitchtools.NamedPitch.from_pitch_carrier(pitch_carrier_2) number = pitchtools.NumberedPitch(pitch_2).number - \ pitchtools.NumberedPitch(pitch_1).number number = mathtools.integer_equivalent_number_to_integer(number) return class_(number)
def transpose(self, pitch_carrier): r'''Transposes `pitch_carrier`. .. container:: example Transposes chord: >>> chord = abjad.Chord("<c' e' g'>4") >>> interval = abjad.NumberedInterval(1) >>> interval.transpose(chord) Chord("<cs' f' af'>4") Returns newly constructed object of `pitch_carrier` type. ''' from abjad.tools import pitchtools from abjad.tools import scoretools if isinstance(pitch_carrier, pitchtools.Pitch): number = pitch_carrier.number + self.semitones return type(pitch_carrier)(number) elif isinstance(pitch_carrier, numbers.Number): pitch_carrier = pitchtools.NumberedPitch(pitch_carrier) result = self.transpose(pitch_carrier) return result.number elif isinstance(pitch_carrier, scoretools.Note): new_note = copy.copy(pitch_carrier) number = pitchtools.NumberedPitch(pitch_carrier.written_pitch) number = number.number number += self.number new_pitch = pitchtools.NamedPitch(number) new_note.written_pitch = new_pitch return new_note elif isinstance(pitch_carrier, scoretools.Chord): new_chord = copy.copy(pitch_carrier) pairs = zip(new_chord.note_heads, pitch_carrier.note_heads) for new_nh, old_nh in pairs: number = \ pitchtools.NumberedPitch(old_nh.written_pitch).number number += self.number new_pitch = pitchtools.NamedPitch(number) new_nh.written_pitch = new_pitch return new_chord else: return pitch_carrier
def _make_new_notes(anchor_pitch, anchor_written_duration, subrun_intervals): from abjad.tools import pitchtools from abjad.tools import scoretools new_notes = [] for subrun_interval in subrun_intervals: new_pc = (pitchtools.NumberedPitch(anchor_pitch).pitch_number + subrun_interval) % 12 new_note = scoretools.Note(new_pc, anchor_written_duration) new_notes.append(new_note) return new_notes
def from_pitch_carriers(cls, pitch_carrier_1, pitch_carrier_2): '''Calculate named interval from `pitch_carrier_1` to `pitch_carrier_2`: :: >>> pitchtools.NamedInterval.from_pitch_carriers( ... NamedPitch(-2), ... NamedPitch(12), ... ) NamedInterval('+M9') :: .. todo:: Improve this behavior. >>> pitchtools.NamedInterval.from_pitch_carriers( ... NamedPitch("cs'"), ... NamedPitch("cf'"), ... ) NamedInterval('-M2') Returns named interval. ''' from abjad.tools import pitchtools pitch_1 = pitchtools.NamedPitch.from_pitch_carrier(pitch_carrier_1) pitch_2 = pitchtools.NamedPitch.from_pitch_carrier(pitch_carrier_2) degree_1 = pitch_1.diatonic_pitch_number degree_2 = pitch_2.diatonic_pitch_number named_interval_number = abs(degree_1 - degree_2) + 1 numbered_interval_number = abs( pitchtools.NumberedPitch(pitch_1).pitch_number - pitchtools.NumberedPitch(pitch_2).pitch_number) numbered_interval = pitchtools.NumberedInterval( numbered_interval_number, ) absolute_named_interval = numbered_interval.to_named_interval( named_interval_number) if pitch_2 < pitch_1: named_interval = -absolute_named_interval else: named_interval = absolute_named_interval return cls(named_interval)
def numbered_pitch(self): r'''Numbered pitch corresponding to named pitch. :: >>> NamedPitch("cs''").numbered_pitch NumberedPitch(13) Returns numbered pitch. ''' from abjad.tools import pitchtools return pitchtools.NumberedPitch(self)
def __init__( self, source_pitch_range='[A0, C8]', target_octave_start_pitch=0, ): from abjad.tools import pitchtools if isinstance(source_pitch_range, pitchtools.PitchRange): source_pitch_range = copy.copy(source_pitch_range) else: source_pitch_range = pitchtools.PitchRange(source_pitch_range) target_octave_start_pitch = pitchtools.NumberedPitch( target_octave_start_pitch) self._source_pitch_range = source_pitch_range self._target_octave_start_pitch = target_octave_start_pitch
def _parse_range_string(self, range_string): from abjad.tools import pitchtools assert isinstance(range_string, str), repr(range_string) range_string = range_string.replace('-inf', '-1000') range_string = range_string.replace('+inf', '1000') match = self._range_string_regex.match(range_string) if match is None: message = 'can not instantiate pitch range: {!r}' message = message.format(range_string) raise ValueError(message) groups = match.groups() start_punctuation = groups[0] start_pitch_string = groups[1] stop_pitch_string = groups[8] stop_punctuation = groups[-1] start_inclusivity_string = \ self._start_punctuation_to_inclusivity_string[start_punctuation] stop_inclusivity_string = \ self._stop_punctuation_to_inclusivity_string[stop_punctuation] if start_pitch_string == '-1000': start_pitch = None else: try: start_pitch = pitchtools.NamedPitch(start_pitch_string) except TypeError: start_pitch = pitchtools.NumberedPitch(int(start_pitch_string)) if stop_pitch_string == '1000': stop_pitch = None else: try: stop_pitch = pitchtools.NamedPitch(stop_pitch_string) except TypeError: stop_pitch = pitchtools.NumberedPitch(int(stop_pitch_string)) start_pair = (start_pitch, start_inclusivity_string) stop_pair = (stop_pitch, stop_inclusivity_string) return start_pair, stop_pair
def instantiate_pitch_and_interval_test_collection(): r'''Instantiate pitch and interval test collection: :: >>> for x in pitchtools.instantiate_pitch_and_interval_test_collection(): x ... NumberedInversionEquivalentIntervalClass(1) NamedInversionEquivalentIntervalClass('+M2') NumberedInterval(1) NumberedIntervalClass(1) NamedInterval('+M2') NamedIntervalClass('+M2') NamedPitch('c') NamedPitchClass('c') NumberedPitch(1) NumberedPitchClass(1) Use to test pitch and interval interface consistency. Returns list. ''' from abjad.tools import pitchtools result = [] result.append(pitchtools.NumberedInversionEquivalentIntervalClass(1)) result.append(pitchtools.NamedInversionEquivalentIntervalClass('M2')) result.append(pitchtools.NumberedInterval(1)) result.append(pitchtools.NumberedIntervalClass(1)) result.append(pitchtools.NamedInterval('M2')) result.append(pitchtools.NamedIntervalClass('M2')) result.append(pitchtools.NamedPitch('c')) result.append(pitchtools.NamedPitchClass('c')) result.append(pitchtools.NumberedPitch(1)) result.append(pitchtools.NumberedPitchClass(1)) return result
def list_numbered_interval_numbers_pairwise(pitch_carriers, wrap=False): r'''Lists numbered interval numbers pairwise between `pitch_carriers`. :: >>> staff = Staff("c'8 d'8 e'8 f'8 g'8 a'8 b'8 c''8") .. doctest:: >>> f(staff) \new Staff { c'8 d'8 e'8 f'8 g'8 a'8 b'8 c''8 } :: >>> pitchtools.list_numbered_interval_numbers_pairwise(staff[:]) [2, 2, 1, 2, 2, 2, 1] :: >>> pitchtools.list_numbered_interval_numbers_pairwise( ... staff[:], wrap=True) [2, 2, 1, 2, 2, 2, 1, -12] :: >>> notes = [ ... Note("c'8"), Note("d'8"), Note("e'8"), Note("f'8"), ... Note("g'8"), Note("a'8"), Note("b'8"), Note("c''8"), ... ] :: >>> notes.reverse() :: >>> pitchtools.list_numbered_interval_numbers_pairwise(notes) [-1, -2, -2, -2, -1, -2, -2] :: >>> pitchtools.list_numbered_interval_numbers_pairwise( ... notes, wrap=True) [-1, -2, -2, -2, -1, -2, -2, 12] When ``wrap = False`` do not return ``pitch_carriers[-1] - pitch_carriers[0]`` as last in series. When ``wrap = True`` do return ``pitch_carriers[-1] - pitch_carriers[0]`` as last in series. Returns list. ''' from abjad.tools import pitchtools result = [] if len(pitch_carriers) == 0: return result elif len(pitch_carriers) == 1: if pitchtools.Pitch.is_pitch_carrier(pitch_carriers[0]): return result else: message = 'must be pitch, not, note-head or chord.' raise TypeError(message) pairs = sequencetools.iterate_sequence_nwise(pitch_carriers, wrapped=wrap) pairs = list(pairs) for first_carrier, second_carrier in pairs: first_pitch = pitchtools.NamedPitch.from_pitch_carrier(first_carrier) second_pitch = pitchtools.NamedPitch.from_pitch_carrier(second_carrier) signed_interval = \ pitchtools.NumberedPitch(second_pitch).pitch_number - \ pitchtools.NumberedPitch(first_pitch).pitch_number result.append(signed_interval) return result
def target_octave_start_pitch(self, target_octave_start_pitch): from abjad.tools import pitchtools self._target_octave_start_pitch = pitchtools.NumberedPitch( target_octave_start_pitch)