Ejemplo n.º 1
0
 def all_tonal_pitches(self, v_note):
     """
     Compute all tonal pitches for the target of a v_note in p_map.
     :param v_note:
     :return:
     """
     target = self[v_note]
     if target is None:
         raise Exception(
             'Internal construction error, v_note target is None.')
     policy_context = target.policy_context
     return PitchScale.compute_tonal_pitches(
         policy_context.harmonic_context.tonality,
         policy_context.pitch_range)
Ejemplo n.º 2
0
    def values(self, p_map, v_note):
        assigned = p_map.assigned_actors(self)
        unassigned = p_map.unassigned_actors(self)
        if v_note in unassigned:
            tonality = p_map[v_note].policy_context.harmonic_context.tonality
            pitches = PitchScale.compute_tonal_pitches(tonality,
                                                       self.pitch_range)
            answer = OrderedSet()
            for p in pitches:
                answer.add(Note(p, v_note.base_duration, v_note.num_dots))
            return answer
            # return {Note(p, v_note.base_duration, v_note.num_dots) for p in pitches}

        if v_note in assigned:
            return OrderedSet([p_map[v_note].note])

        raise Exception(
            '{0} is not in actor list for pitch range constraints.'.format(
                v_note.note))
    def values(self, p_map, v_note):
        """
        Compute possible values for v_note's target.
        :param p_map: note-->contextual_note
        :param v_note: Note
        :return: Candidate Notes.

        Note: Here is why the intervals are reversed for solving for note_one:
              Suppose x --> [x-a, x + b].  Then for some value y, 
              for t with y-b<=t<=y+a, we have t -->[t-a, t+b], but
              from the inequalities, t-a<=y<t+b - so the reverse map is
              [y-b, y+a] <-- y, which is exactly what happens below.
        """
        if v_note == self.note_two:
            source = self.note_one
            target = self.note_two
            comparative = self.comparative
        elif v_note == self.note_one:
            source = self.note_two
            target = self.note_one
            comparative = 4 - self.comparative
        else:
            raise Exception(
                'v_note specification does not match any v_note in constraints.'
            )

        if p_map[target].note is not None:
            return {p_map[target].note}

        if p_map[source].note is None:
            answer_range = p_map[target].policy_context.pitch_range
            source_pitch = None
        else:
            # Establish a pitch range commensurate with comparative.
            qrange = p_map[target].policy_context.pitch_range
            source_pitch = p_map[source].note.diatonic_pitch

            if comparative > 2:
                answer_range = PitchRange(qrange.start_index,
                                          source_pitch.chromatic_distance)
            elif comparative < 2:
                answer_range = PitchRange(source_pitch.chromatic_distance,
                                          qrange.end_index)
            else:
                answer_range = PitchRange(source_pitch.chromatic_distance,
                                          source_pitch.chromatic_distance)

        pitches = PitchScale.compute_tonal_pitches(
            p_map[target].policy_context.harmonic_context.tonality,
            answer_range)
        if comparative == 4 and len(pitches) > 0 and source_pitch is not None and \
                source_pitch.chromatic_distance == pitches[-1].chromatic_distance:
            pitches.pop(-1)
        if comparative == 0 and len(pitches) > 0 and source_pitch is not None and \
                source_pitch.chromatic_distance == pitches[0].chromatic_distance:
            del pitches[0]

        answer = OrderedSet()
        for pitch in pitches:
            answer.add(Note(pitch, target.base_duration, target.num_dots))
        return answer