Example #1
0
 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()
Example #2
0
    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
Example #3
0
    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
Example #4
0
 def test_get_id(self):
     octave_id = OctaveType.get_id(OctaveType.LINE_1)
     self.assertEqual(5, octave_id)
Example #5
0
 def test_octave_down(self):
     self.assertEqual(OctaveType.LINE_3, OctaveType.get_octave_down(OctaveType.LINE_4))
Example #6
0
    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)
Example #7
0
 def test_from_id(self):
     octave = OctaveType.from_id(5)
     self.assertEqual(OctaveType.LINE_1, octave)
Example #8
0
    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