コード例 #1
0
 def _get_notes_from_interval(self, note: Note,
                              interval: int) -> list[Note]:
     sdg = note.get_scale_degree()
     octv = note.get_octave()
     adjustment_value = -1 if interval > 0 else 1
     new_sdg, new_octv = sdg + interval + adjustment_value, octv
     if new_sdg < 1:
         new_octv -= 1
         new_sdg += 7
     else:
         while new_sdg > 7:
             new_octv += 1
             new_sdg -= 7
     new_note = Note(new_sdg, new_octv, 8)
     valid_notes = [new_note]
     if (self._mode == ModeOption.DORIAN
             or self._mode == ModeOption.LYDIAN) and new_sdg == 7:
         valid_notes.append(
             Note(new_sdg, new_octv, 8, accidental=ScaleOption.FLAT))
     if self._mode == ModeOption.AEOLIAN and new_sdg == 2:
         valid_notes.append(
             Note(new_sdg, new_octv, 8, accidental=ScaleOption.SHARP))
     if new_sdg in [1, 4, 5]:
         valid_notes.append(
             Note(new_sdg, new_octv, 8, accidental=ScaleOption.SHARP))
     return valid_notes
コード例 #2
0
 def _map_solution_onto_counterpoint_dict(self,
                                          solution: list[Note]) -> None:
     for i, note in enumerate(solution):
         (measure, beat) = self._all_indices[i]
         if measure in self._divided_measures:
             note = Note(note.get_scale_degree(), note.get_octave(), 4,
                         note.get_accidental())
         self._counterpoint[(measure, beat)] = note
コード例 #3
0
 def _backtrack(self) -> None:
     if (self._num_backtracks > 2000 and self._solutions_this_attempt == 0) or self._num_backtracks > 20000:
         return 
     if self._solutions_this_attempt >= 100:
         return 
     self._num_backtracks += 1
     if len(self._remaining_indices) == 0:
         # print("found possible solution!")
         sol = []
         for i in range(len(self._all_indices)):
             note_to_add = self._counterpoint[self._all_indices[i]]
             note_to_add_copy = Note(note_to_add.get_scale_degree(), note_to_add.get_octave(), note_to_add.get_duration(), note_to_add.get_accidental())
             sol.append(note_to_add_copy)
         if self._passes_final_checks(sol):
             # print("FOUND SOLUTION!")
             self._solutions.append(sol)
             self._solutions_this_attempt += 1
         return 
     (bar, beat) = self._remaining_indices.pop() 
     candidates = None
     if bar == 0 and (beat == 0 or self._counterpoint[(0, 0)].get_accidental() == ScaleOption.REST):
         candidates = list(filter(lambda n: self._cantus[0].get_chromatic_interval(n) in [-12, 0, 7, 12], self._valid_pitches))
     else:
         candidates = list(filter(lambda n: self._passes_insertion_checks(n, (bar, beat)), self._valid_pitches)) 
     if bar == 0 and beat == 0:
         candidates.append(Note(1, 0, 4, accidental = ScaleOption.REST))
         shuffle(candidates)
     if bar == self._length - 1:
         candidates = list(filter(lambda n: self._valid_last_note(n), candidates))
     for candidate in candidates:
         #start by making a copy of the note
         candidate = Note(candidate.get_scale_degree(), candidate.get_octave(), 8, candidate.get_accidental())
         temp_highest_placed, temp_lowest_placed = self._highest_has_been_placed, self._lowest_has_been_placed
         if self._mr.is_unison(candidate, self._highest): self._highest_has_been_placed = True  
         if self._mr.is_unison(candidate, self._lowest): self._lowest_has_been_placed = True 
         (may_be_tied, must_be_tied) = self._get_tied_options(candidate, (bar, beat))
         if not must_be_tied:
             candidate.set_duration(4 if bar != self._length - 1 else 16)
             self._counterpoint[(bar, beat)] = candidate 
             if self._current_chain_is_legal((bar, beat)):
                 self._backtrack()
         if may_be_tied or (bar == self._length - 2 and beat == 0):
             candidate.set_duration(8)
             index_to_remove = (bar, 2) if beat == 0 else (bar + 1, 0)
             index_position_all, index_position_remaining = self._all_indices.index(index_to_remove), self._remaining_indices.index(index_to_remove)
             self._all_indices.remove(index_to_remove)
             self._remaining_indices.remove(index_to_remove)
             del self._counterpoint[index_to_remove]
             self._counterpoint[(bar, beat)] = candidate 
             if self._current_chain_is_legal((bar, beat)):
                 self._backtrack()
             self._all_indices.insert(index_position_all, index_to_remove)
             self._remaining_indices.insert(index_position_remaining, index_to_remove)
             self._counterpoint[index_to_remove] = None 
         self._highest_has_been_placed, self._lowest_has_been_placed = temp_highest_placed, temp_lowest_placed
     self._counterpoint[(bar, beat)] = None 
     self._remaining_indices.append((bar, beat))
コード例 #4
0
 def _get_notes_from_interval(self, note: Note, interval: int) -> list[Note]: 
     sdg = note.get_scale_degree()
     octv = note.get_octave()
     adjustment_value = -1 if interval > 0 else 1
     new_sdg, new_octv = sdg + interval + adjustment_value, octv
     if new_sdg < 1:
         new_octv -= 1
         new_sdg += 7
     elif new_sdg > 7:
         new_octv += 1
         new_sdg -= 7
     new_note = Note(new_sdg, new_octv, 8)
     valid_notes = [new_note]
     if (self._mode == ModeOption.DORIAN or self._mode == ModeOption.LYDIAN) and new_sdg == 7:
         valid_notes.append(Note(new_sdg, new_octv, 8, accidental = ScaleOption.FLAT))
     def valid_interval(next_note: Note) -> bool:
         chro_interval = next_note.get_chromatic_with_octave() - note.get_chromatic_with_octave()
         return chro_interval in CONSONANT_MELODIC_INTERVALS_CHROMATIC
     return list(map(lambda n: (interval, n), list(filter(valid_interval, valid_notes))))