def get_id(self) -> int: """ Pobierz identyfikator dla nuty. Numer ten jest zgodny z numeracją MIDI. Używany jest przy generowaniu interwałów """ return self.get_base_note_id() + OctaveType.get_id( self.octave) * 12 + self.get_accidentals_value()
def __sub__(self, other): if isinstance(other, Interval): octave_lower = copy.deepcopy(self) octave_lower.octave = OctaveType.get_octave_down(self.octave) return octave_lower + other.get_complement_interval() else: raise NotImplementedError( 'This operation is not implemented') # pragma: no cover
def get_random_note(self, longest_duration: Optional[int] = None) -> Note: """ Wygeneruj nutę z losowymi parametrami o pewnej maksymalnej długości podanej w parametrze. Args: longest_duration: Najdłuższa możliwa wartość rytmiczna, która może wystąpić podana w ilości shortest_note_duration. Jeśli nie podano, skrypt zakłada że nuta o każdej długości jest dozwolona. Returns: Nuta z losowymi parametrami o maksymalnej długości wynoszącej longest_duration """ # Jeśli nie był podany parametr najdłuższej możliwej wartości rytmicznej, to zakładamy że nuta o każdej długości # jest dozwolona do wygenerowania if longest_duration is None: longest_duration = self.shortest_note_duration available_mods = [] base_note = np.random.choice(Note.base_notes) octave = OctaveType.random() base_duration = self.get_random_duration( longest_duration=longest_duration) has_mod = np.random.choice([True, False]) note = Note(note=base_note, octave=octave, base_duration=base_duration) # Jeśli długość nuty jest najkrótsza jaką możemy uzyskać, to nie możemy dodać modyfikatora wydłużającego, # gdyż kropka lub podwójna kropka doda mniejszą wartość rytmiczną if base_duration >= self.shortest_note_duration: has_mod = False # Jeśli dostępne miejsce jest większej lub równej długości niż potencjalna nuta z kropką, to do dostępnych # modyfikatorów możemy dodać przedłużenie w postaci kropki if longest_duration >= note.get_duration( self.shortest_note_duration) * 1.5: available_mods.append(NoteModifier.DOT) # Jeśli dostępne miejsce jest większej lub równej długości niż potencjalna nuta z podwójną kropką, to do # dostępnych modyfikatorów możemy dodać przedłużenie w postaci podwójnej kropki. # Sprawdzamy również, czy nie jest to przedostatnia dostępna wartość rytmiczna. Jeśli tak jest, to nie możemy # dodać podwójnej kropki, gdyż skutkowałoby to dodaniem nuty o połowę mniejszej wartości rytmicznej niż # dozwolona if longest_duration >= note.get_duration(self.shortest_note_duration) * 1.75 \ and note.base_duration > 2 * self.shortest_note_duration: available_mods.append(NoteModifier.DOUBLE_DOT) if has_mod and len(available_mods) > 0: note.add_modifier(np.random.choice(available_mods)) return note
def test_get_id(self): octave_id = OctaveType.get_id(OctaveType.LINE_1) self.assertEqual(5, octave_id)
def test_octave_down(self): self.assertEqual(OctaveType.LINE_3, OctaveType.get_octave_down(OctaveType.LINE_4))
def test_from_id_out_of_range(self): octave = OctaveType.from_id(-1) self.assertEqual(OctaveType.DOUBLE_CONTRA, octave) octave = OctaveType.from_id(11) self.assertEqual(OctaveType.LINE_6, octave)
def test_from_id(self): octave = OctaveType.from_id(5) self.assertEqual(OctaveType.LINE_1, octave)
def __add__(self, other): if isinstance(other, Interval): # Find new base note according to the current note new_base_note_idx = (self.base_notes_indexes[self.get_base_note()] + other.degrees - 1) \ % len(self.base_notes) new_base_note = self.base_notes[new_base_note_idx] new_base_note_id = self.base_notes_ids[new_base_note] new_id = self.get_id() + other.semitones new_octave_id = OctaveType.get_id(self.octave) + \ int(self.get_base_note() in self.base_notes[8 - other.degrees:]) new_octave = OctaveType.from_id(new_octave_id) # Na podstawie naszego nowego ID wyliczamy pozycję naszej nuty w oktawie # new_id % 12 zwraca indeks od 0 do 11 co obrazuje która to nuta w oktawie # Następnie odejmujemy od tego nowe ID nuty bazowej id_difference = new_id % 12 - new_base_note_id # Wstępna redukcja ilości znaków chromatycznych do maksymalnie trzech if id_difference > 3: id_difference -= 12 if id_difference < -3: id_difference += 12 # Jeśli otrzymaliśmy nutę o więcej niż 3 bemolach, to musimy zredukować tą ilość do maksymalnie dwóch while id_difference <= -3: # Znajdujemy poprzednią nutę bazową previous_base_note_idx = new_base_note_idx - 1 previous_base_note = self.base_notes[previous_base_note_idx] previous_base_note_id = self.base_notes_ids[previous_base_note] # Liczmy różnicę w półtonach między tymi nutami (jeśli indeks jest równy -1 to znaczy że przeszliśmy z # nuty c na nutę b i sposób obliczania różnicy w półtonach będzie inny if previous_base_note_idx == -1: semitones_diff = 12 - previous_base_note_id else: semitones_diff = new_base_note_id - previous_base_note_id # Ustawiamy na nowo parametry nuty. # Jeśli miałaby wystąpić kolejna iteracja pętli to zostaną użyte do zredukowania znaków chromatycznych # W przeciwnym wypadku zostaną użyte do stworzenia nowej nuty new_base_note_idx = previous_base_note_idx new_base_note = previous_base_note new_base_note_id = previous_base_note_id id_difference += semitones_diff # Jeśli otrzymaliśmy nutę o więcej niż 3 krzyżykach, to musimy zredukować tą ilość do maksymalnie dwóch while id_difference >= 3: # Znajdujemy następną nutę bazową next_base_note_idx = new_base_note_idx + 1 if next_base_note_idx == len(self.base_notes): next_base_note_idx = 0 next_base_note = self.base_notes[next_base_note_idx] next_base_note_id = self.base_notes_ids[next_base_note] # Liczymy różnicę w półtonach między tymi nutami (jeśli indeks jest równy 0 to znaczy że przeszliśmy z # nuty b na nutę c i sposób obliczania różnicy w półtonach będzie inny if next_base_note_idx == 0: semitones_diff = 12 - new_base_note_id else: semitones_diff = next_base_note_id - new_base_note_id # Ustawiamy na nowo parametry nuty # Jeśli miałaby wystąpić kolejna iteracja pętli to zostaną użyte do zredukowania znaków chromatycznych # W przeciwnym wypadku zostaną użyte do stworzenia nowej nuty new_base_note_idx = next_base_note_idx new_base_note = next_base_note new_base_note_id = next_base_note_id id_difference -= semitones_diff return Note( f'{new_base_note}{self.create_accidentals_string(id_difference)}', new_octave) else: raise NotImplementedError( 'This operation is not implemented') # pragma: no cover