def compute_result(self, arg_contextual_note, target_contextual_note, down_steps, up_steps): arg_pitch = arg_contextual_note.note.diatonic_pitch pitches = PitchScale.compute_tonal_pitch_range( target_contextual_note.policy_context.harmonic_context.tonality, arg_pitch, down_steps, up_steps) result = OrderedSet() for pitch in pitches: result.add( Note(pitch, self.note_two.base_duration, self.note_two.num_dots)) return result
def verify(self, parameter_map): """ Verify that p_map has values satisfying the constraint. :param parameter_map: :return: """ first_contextual_note = parameter_map[self.note_one] second_contextual_note = parameter_map[self.note_two] if first_contextual_note.note is None or second_contextual_note.note is None: return False pitches = PitchScale.compute_tonal_pitch_range( second_contextual_note.policy_context.harmonic_context.tonality, first_contextual_note.note.diatonic_pitch, self.lower_steps, self.upper_steps) return second_contextual_note.note.diatonic_pitch in pitches
def test_compute_tonal_pitch_range(self): logging.debug('Start test_compute_tonal_pitch_range') tonality = Tonality.create(ModalityType.Major, DiatonicTone('Ab')) pitch = DiatonicPitch(4, 'B#') pitches = PitchScale.compute_tonal_pitch_range(tonality, pitch, 5, 7) for p in reversed(pitches): print(p) test_pitches = [ 'A:4', 'B:4', 'C:4', 'D:4', 'E:4', 'F:4', 'G:4', 'Ab:4', 'Bb:4', 'Db:4', 'Eb:4', 'C#:4', 'D#:4', 'G#:4', 'A#:4', 'B#:4', 'Cb:4', 'B##:4', 'Cbb:4' ] ranges = [[0, 5], [-5, 0], [-4, 2], [-5, -3], [5, 7]] answers = [ '[Ab:4,Bb:4,C:5,Db:5,Eb:5,F:5,G:5]', '[C:4,Db:4,Eb:4,F:4,G:4,Ab:4,Bb:4]', '[Db:4,Eb:4,F:4,G:4,Ab:4,Bb:4,C:5,Db:5]', '[C:4,Db:4,Eb:4]', '[G:5,Ab:5,Bb:5]', '[Bb:4,C:5,Db:5,Eb:5,F:5,G:5,Ab:5]', '[Db:4,Eb:4,F:4,G:4,Ab:4,Bb:4,C:5]', '[Eb:4,F:4,G:4,Ab:4,Bb:4,C:5,Db:5,Eb:5]', '[Db:4,Eb:4,F:4]', '[Ab:5,Bb:5,C:6]', '[C:4,Db:4,Eb:4,F:4,G:4,Ab:4]', '[Eb:3,F:3,G:3,Ab:3,Bb:3,C:4]', '[F:3,G:3,Ab:3,Bb:3,C:4,Db:4,Eb:4]', '[Eb:3,F:3,G:3]', '[Ab:4,Bb:4,C:5]', '[Db:4,Eb:4,F:4,G:4,Ab:4,Bb:4,C:5]', '[F:3,G:3,Ab:3,Bb:3,C:4,Db:4,Eb:4]', '[G:3,Ab:3,Bb:3,C:4,Db:4,Eb:4,F:4,G:4]', '[F:3,G:3,Ab:3]', '[C:5,Db:5,Eb:5]', '[Eb:4,F:4,G:4,Ab:4,Bb:4,C:5,Db:5]', '[G:3,Ab:3,Bb:3,C:4,Db:4,Eb:4,F:4]', '[Ab:3,Bb:3,C:4,Db:4,Eb:4,F:4,G:4,Ab:4]', '[G:3,Ab:3,Bb:3]', '[Db:5,Eb:5,F:5]', '[F:4,G:4,Ab:4,Bb:4,C:5,Db:5]', '[Ab:3,Bb:3,C:4,Db:4,Eb:4,F:4]', '[Bb:3,C:4,Db:4,Eb:4,F:4,G:4,Ab:4]', '[Ab:3,Bb:3,C:4]', '[Db:5,Eb:5,F:5]', '[G:4,Ab:4,Bb:4,C:5,Db:5,Eb:5]', '[Bb:3,C:4,Db:4,Eb:4,F:4,G:4]', '[C:4,Db:4,Eb:4,F:4,G:4,Ab:4,Bb:4]', '[Bb:3,C:4,Db:4]', '[Eb:5,F:5,G:5]', '[Ab:4,Bb:4,C:5,Db:5,Eb:5,F:5]', '[C:4,Db:4,Eb:4,F:4,G:4,Ab:4]', '[Db:4,Eb:4,F:4,G:4,Ab:4,Bb:4,C:5]', '[C:4,Db:4,Eb:4]', '[F:5,G:5,Ab:5]', '[Bb:4,C:5,Db:5,Eb:5,F:5,G:5]', '[Db:4,Eb:4,F:4,G:4,Ab:4,Bb:4]', '[Eb:4,F:4,G:4,Ab:4,Bb:4,C:5,Db:5]', '[Db:4,Eb:4,F:4]', '[G:5,Ab:5,Bb:5]', '[Db:4,Eb:4,F:4,G:4,Ab:4,Bb:4]', '[F:3,G:3,Ab:3,Bb:3,C:4,Db:4]', '[G:3,Ab:3,Bb:3,C:4,Db:4,Eb:4,F:4]', '[F:3,G:3,Ab:3]', '[Bb:4,C:5,Db:5]', '[Eb:4,F:4,G:4,Ab:4,Bb:4,C:5]', '[G:3,Ab:3,Bb:3,C:4,Db:4,Eb:4]', '[Ab:3,Bb:3,C:4,Db:4,Eb:4,F:4,G:4]', '[G:3,Ab:3,Bb:3]', '[C:5,Db:5,Eb:5]', '[Db:4,Eb:4,F:4,G:4,Ab:4,Bb:4]', '[F:3,G:3,Ab:3,Bb:3,C:4,Db:4]', '[G:3,Ab:3,Bb:3,C:4,Db:4,Eb:4,F:4]', '[F:3,G:3,Ab:3]', '[Bb:4,C:5,Db:5]', '[Eb:4,F:4,G:4,Ab:4,Bb:4,C:5]', '[G:3,Ab:3,Bb:3,C:4,Db:4,Eb:4]', '[Ab:3,Bb:3,C:4,Db:4,Eb:4,F:4,G:4]', '[G:3,Ab:3,Bb:3]', '[C:5,Db:5,Eb:5]', '[Ab:4,Bb:4,C:5,Db:5,Eb:5,F:5]', '[C:4,Db:4,Eb:4,F:4,G:4,Ab:4]', '[Db:4,Eb:4,F:4,G:4,Ab:4,Bb:4,C:5]', '[C:4,Db:4,Eb:4]', '[F:5,G:5,Ab:5]', '[Bb:4,C:5,Db:5,Eb:5,F:5,G:5]', '[Db:4,Eb:4,F:4,G:4,Ab:4,Bb:4]', '[Eb:4,F:4,G:4,Ab:4,Bb:4,C:5,Db:5]', '[Db:4,Eb:4,F:4]', '[G:5,Ab:5,Bb:5]', '[C:5,Db:5,Eb:5,F:5,G:5,Ab:5]', '[Eb:4,F:4,G:4,Ab:4,Bb:4,C:5]', '[F:4,G:4,Ab:4,Bb:4,C:5,Db:5,Eb:5]', '[Eb:4,F:4,G:4]', '[Ab:5,Bb:5,C:6]', '[Bb:3,C:4,Db:4,Eb:4,F:4,G:4,Ab:4]', '[Db:3,Eb:3,F:3,G:3,Ab:3,Bb:3,C:4]', '[Eb:3,F:3,G:3,Ab:3,Bb:3,C:4,Db:4,Eb:4]', '[Db:3,Eb:3,F:3]', '[Ab:4,Bb:4,C:5]', '[Db:5,Eb:5,F:5,G:5,Ab:5,Bb:5]', '[F:4,G:4,Ab:4,Bb:4,C:5,Db:5]', '[G:4,Ab:4,Bb:4,C:5,Db:5,Eb:5,F:5]', '[F:4,G:4,Ab:4]', '[Bb:5,C:6,Db:6]', '[Bb:3,C:4,Db:4,Eb:4,F:4,G:4]', '[Db:3,Eb:3,F:3,G:3,Ab:3,Bb:3]', '[Eb:3,F:3,G:3,Ab:3,Bb:3,C:4,Db:4]', '[Db:3,Eb:3,F:3]', '[G:4,Ab:4,Bb:4]', ] answer_idx = 0 for pitch_str in test_pitches: for r in ranges: pitch = DiatonicPitch.parse(pitch_str) pitches = PitchScale.compute_tonal_pitch_range( tonality, pitch, r[0], r[1]) answer_str = '[' + (','.join(str(p) for p in pitches)) + ']' # print '\'[' + (','.join(str(p) for p in pitches)) + ']\',' answer = answers[answer_idx] answer_idx = answer_idx + 1 print('{0} [{1}, {2}]: {3}'.format(pitch, r[0], r[1], answer_str)) assert answer == answer_str logging.debug('End test_compute_tonal_pitch_range')
def values(self, p_map, v_note): """ :param p_map: :param v_note: :return: """ index = self.actors.index(v_note) if v_note in self.actors else None if index is None: raise Exception('Cannot find v_note in constraints actors') if p_map[v_note].note is not None: return OrderedSet([p_map[v_note].note]) # find the first assigned note assigned_index = None for i in range(0, len(self.actors)): if p_map[self.actors[i]].note is not None: assigned_index = i break if assigned_index is None: pitches = p_map.all_tonal_pitches(v_note) return OrderedSet([Note(p, v_note.base_duration, v_note.num_dots) for p in pitches]) known_note = p_map[self.actors[assigned_index]].note if assigned_index < index: for i in range(assigned_index + 1, index + 1): unknown_contextual_note = p_map[self.actors[i]] unknown_note = unknown_contextual_note.note if unknown_note is not None: known_note = unknown_note continue lower_index = self.variance_list[i - 1] if self.variance_list[i - 1] < 0 else 0 upper_index = self.variance_list[i - 1] if self.variance_list[i - 1] > 0 else 0 pitches = PitchScale.compute_tonal_pitch_range( unknown_contextual_note.policy_context.harmonic_context.tonality, known_note.diatonic_pitch, lower_index, upper_index) pitch_index = self.variance_list[i - 1] + (len(pitches) - 1 if self.variance_list[i - 1] < 0 else 0) if pitch_index < 0 or pitch_index >= len(pitches): if pitches is None or len(pitches) == 0: return OrderedSet() pitch = pitches[0] if pitch_index < 0 else pitches[len(pitches) - 1] else: pitch = pitches[pitch_index] known_note = Note(pitch, self.actors[i].base_duration, self.actors[i].num_dots) return OrderedSet([known_note]) for i in range(assigned_index - 1, index - 1, -1): unknown_contextual_note = p_map[self.actors[i]] unknown_note = unknown_contextual_note.note if unknown_note is not None: known_note = unknown_note continue upper_index = -self.variance_list[i] if self.variance_list[i] < 0 else 0 lower_index = -self.variance_list[i] if self.variance_list[i] > 0 else 0 pitches = PitchScale.compute_tonal_pitch_range( unknown_contextual_note.policy_context.harmonic_context.tonality, known_note.diatonic_pitch, lower_index, upper_index) pitch_index = -self.variance_list[i] + (len(pitches) - 1 if self.variance_list[i] > 0 else 0) if pitch_index < 0: pitch_index = 0 elif pitch_index >= len(pitches): pitch_index = len(pitches) - 1 pitch = pitches[pitch_index] known_note = Note(pitch, self.actors[i].base_duration, self.actors[i].num_dots) return OrderedSet([known_note])