def _build_p_map_dict(self, partial_pitch_results=None):
        actors = OrderedSet()
        for p in self.pitch_constraints:
            actors = actors.union(p.actors)

        d = OrderedDict()
        for note in actors:
            hc = self.hct[note.get_absolute_position().position]
            if hc is None:
                raise Exception(
                    'Cannot locate harmonic context for note \'{0}\''.format(
                        note))
            contextual = ContextualNote(PolicyContext(hc, self.pitch_range))
            d[note] = contextual

        if partial_pitch_results is not None:
            for k, v in partial_pitch_results.items():
                if not isinstance(k, Note):
                    raise Exception(
                        'key of partial_pitch_results must be a Note.')
                if not isinstance(v, DiatonicPitch):
                    raise Exception(
                        'value of partial_pitch_results must be a DiatonicPitch.'
                    )
                if k not in d:
                    raise Exception(
                        'Note \'{0}\' of partial result is not a constraint actor.'
                        .format(k))
                d[k].note = Note(v, k.base_duration, k.num_dots)

        return d
Example #2
0
    def create(line_str, pitch_range, target_hct_list=None):
        """
        Create a PMap from
        :param line_str: a melodic string
        :param pitch_range: PitchRange
        :param target_hct_list: list of pairs ('tonality:chord', duration)
        :return: pmap
        Note if target_hct_list is not specified, we use the hct from the line_str.
        """
        lge = LineGrammarExecutor()
        line, hct = lge.parse(line_str)
        if target_hct_list is not None:
            hct = PMap.build_hct(target_hct_list)
        actors = line.get_all_notes()

        d = OrderedDict()
        for note in actors:
            hc = hct[note.get_absolute_position().position]
            if hc is None:
                raise Exception(
                    'Cannot locate harmonic context for note \'{0}\''.format(
                        note))
            contextual_note = ContextualNote(PolicyContext(hc, pitch_range))
            d[note] = contextual_note

        return PMap(d)
    def policy_creator(modality_type, modality_tone, tertian_chord_txt, low_pitch_txt, hi_pitch_txt):
        diatonic_tonality = Tonality.create(modality_type, modality_tone)
        chord = TertianChordTemplate.parse(tertian_chord_txt).create_chord(diatonic_tonality)
        hc = HarmonicContext(diatonic_tonality, chord, Duration(1, 2))

        pitch_range = PitchRange(DiatonicPitch.parse(low_pitch_txt).chromatic_distance,
                                 DiatonicPitch.parse(hi_pitch_txt).chromatic_distance)
        return PolicyContext(hc, pitch_range)
Example #4
0
    def _optimize_note_domain(self, note, constraints, score):
        """
        For note, get all values it can take satisfying all its constraints.
        Then if there is only one, build a fixed pitch constraint for it.
        If there are more than two, use the curve fits values to make a fixed pitch to set.
        :param note:
        :param constraints:
        :param score:
        :return:
        """
        domain = set()
        first = True
        for constraint in constraints:
            # build a pmap for all actor in the constraint
            pmap = PMap()
            for n in constraint.actors:
                hc = score.hct.get_hc_by_position(n.get_absolute_position())
                pmap[n] = ContextualNote(
                    PolicyContext(
                        hc,
                        score.instrument.sounding_pitch_range()
                        if score.instrument is not None else PitchRange.create(
                            'A:0', 'C:8')))
            # Get all possible pitch values for note in this constraint.
            # domain will hold all the values that match across all constraints
            values = {n.diatonic_pitch for n in constraint.values(pmap, note)}
            if first:
                domain = values
                first = False
            else:
                domain = domain.intersection(values)

        if len(domain) == 0:
            return set()

        pitch_list = list(domain)
        if len(domain) > 2:
            # Find 2 pitches in domain that are closest to the curve fit
            valuation = self.pitch_function.eval_as_nearest_pitch(
                note.get_absolute_position().position)
            candidates = [
                (p, abs(p.chromatic_distance - valuation.chromatic_distance))
                for p in domain
            ]
            candidates = sorted(candidates, key=lambda candidate: candidate[1]
                                )  # sort on chromatic distance.
            pitch_list = [candidates[0][0],
                          candidates[1][0]]  # Take the top to

        if len(pitch_list) == 1:
            return {FixedPitchConstraint(note, pitch_list[0])}

        #  set first as best, second as next best.
        (first, second) = (pitch_list[0], pitch_list[1]) if pitch_list[0].chromatic_distance <= \
            pitch_list[1].chromatic_distance else \
            (pitch_list[1], pitch_list[0])

        return {FixedPitchSelectSetConstraint(note, [first, second])}
Example #5
0
    def _build_p_map_dict(self, hct, pitch_constraints):
        actors = set()
        for p in pitch_constraints:
            actors = actors.union(p.actors)

        d = OrderedDict()
        for note in actors:
            hc = hct[note.get_absolute_position().position]
            if hc is None:
                raise Exception(
                    'Cannot locate harmonic context for note \'{0}\''.format(
                        note))
            pitch_range = self.score.instrument.sounding_pitch_range() if self.score.instrument is not None \
                else PitchRange.create('A:0', 'C:8')
            contextual = ContextualNote(PolicyContext(hc, pitch_range))
            d[note] = contextual

        return d
Example #6
0
    def _build_pitch_solutions_old(self, beat_score_results,
                                   pitch_constraints):
        """
        Build the final results using the beat results, then the pitch results, then the reshape constraints.
        :param beat_score_results: Set of (PositionDeltaInfo, LiteScore)'s
        :param pitch_constraints: Set of Constraints
        :return:
        """
        final_results = list()
        pitch_results = list()

        # Solve the pitch constraints using the beat constraint results.
        if beat_score_results is not None:
            for beat_result_pdi, beat_result_score in beat_score_results:
                revised_constraints = TReshape._regenerate_constraints(
                    pitch_constraints, self.score.line, beat_result_score.line)
                pitch_solver = PitchConstraintSolver(revised_constraints)
                p_map_dict = PMap(
                    self._build_p_map_dict(beat_result_pdi.hct,
                                           revised_constraints))
                pitch_solver_results = pitch_solver.solve(p_map_dict)
                for pitch_pmap in pitch_solver_results:
                    line = pitch_pmap.apply(beat_result_score.line)
                    pitch_results.append(
                        (pitch_pmap, beat_result_score,
                         LiteScore(line, beat_result_pdi.hct,
                                   self.score.instrument,
                                   beat_result_pdi.tempo_event_sequence,
                                   beat_result_pdi.ts_event_sequence)))

        else:
            pitch_solver = PitchConstraintSolver(pitch_constraints)
            p_map_dict = PMap(
                self._build_p_map_dict(self.score.hct, pitch_constraints))
            pitch_solver_results = pitch_solver.solve(p_map_dict)
            for pitch_pmap in pitch_solver_results:
                line = pitch_pmap.apply(self.score.line)
                pitch_results.append(
                    (pitch_pmap, self.score,
                     LiteScore(line, self.score.hct, self.score.instrument,
                               self.score.tempo_sequence,
                               self.score.time_signature_sequence)))

        # Solve the reshape constraints using the pitch constraint solutions.
        for pitch_result_pmap, beat_result_score, pitch_result_score in pitch_results:
            # Issue 1. we generate constraints for ALL NOTES on pitch_result_score's line, note that this means
            #          we cannot reliably use pitch_result_pmap further on since pitch_result_score is buily with
            #          an apply - meaning the notes are in the pmap's range, not domain.
            # tersely:  pitch_result_pmap: self.score.line --> pitch_result_score.line
            q = {
                key: value
                for key, value in zip(beat_result_score.line.get_all_notes(),
                                      pitch_result_score.line.get_all_notes())
            }
            ignore_notes = {
                q[n]
                for n in pitch_result_pmap.keys()
                if pitch_result_pmap[n].note is not None
            }
            reshape_constraints = self._generate_reshape_constraints(
                pitch_result_score.line, pitch_result_score.tempo_sequence,
                pitch_result_score.time_signature_sequence, ignore_notes)

            p_map = PMap()
            for c in reshape_constraints:
                note = c.actor_note
                hc = pitch_result_score.hct[
                    note.get_absolute_position().position]
                if hc is None:
                    raise Exception(
                        'Cannot locate harmonic context for note \'{0}\''.
                        format(note))
                contextual = ContextualNote(
                    PolicyContext(
                        hc,
                        pitch_result_score.instrument.sounding_pitch_range()
                        if pitch_result_score.instrument is not None else
                        PitchRange.create('A:0', 'C:8')))
                # Note: p_map maps from pitch_result_score's line notes to something else (does not matter)
                p_map[note] = contextual

            pitch_solver = PitchConstraintSolver(reshape_constraints)
            reshape_results = pitch_solver.solve(p_map)
            # reshape_pmap_result maps pitch_result_score's line notes to something else with a pitch designation.
            # Issue 2): we are getting failures on some notes due to being too close to chord on beat. In these cases,
            #           the solve is not failing, but giving back a partial result.
            for reshape_pmap_result in reshape_results:
                master_pmap = PMap()
                # Not sure  pitch_result_pmap maps from beat_score_result.line notes to a note with pitch desig.
                # reshape_pmap_result pitch_result_score's line notes to something else with a pitch designation.
                # mm: beat_result_score --> self.score or beat_result_score
                mm = {
                    key: value
                    for key, value in zip(
                        beat_result_score.line.get_all_notes() if
                        beat_result_score else self.score.line.get_all_notes(),
                        pitch_result_score.line.get_all_notes())
                }
                for note in pitch_result_pmap.keys():
                    # map notes in pitch_result_score to what beat_score_result would
                    master_pmap[mm[note]] = pitch_result_pmap[note]
                for note in reshape_pmap_result.keys():
                    if note not in master_pmap.keys():
                        master_pmap[note] = reshape_pmap_result[note]
                line_answer = master_pmap.apply(pitch_result_score.line)
                final_results.append(
                    LiteScore(line_answer, pitch_result_score.hct,
                              pitch_result_score.instrument,
                              pitch_result_score.tempo_sequence,
                              pitch_result_score.time_signature_sequence))

        return final_results