def __init__()

in pedalboard/_pedalboard.py [0:0]


    def __init__(self, plugin: "ExternalPlugin", parameter_name: str, search_steps: int = 1000):
        self.__plugin = plugin
        self.__parameter_name = parameter_name

        self.ranges: Dict[Tuple[float, float], Union[str, float, bool]] = {}

        with self.__get_cpp_parameter() as cpp_parameter:
            for fetch_slow in (False, True):
                start_of_range: float = 0
                text_value: Optional[str] = None

                self.ranges = {}
                for x in range(0, search_steps + 1):
                    raw_value = x / search_steps
                    x_text_value = get_text_for_raw_value(cpp_parameter, raw_value, fetch_slow)
                    if text_value is None:
                        text_value = x_text_value
                    elif x_text_value != text_value:
                        # End current range and start a new one
                        self.ranges[(start_of_range, raw_value)] = text_value
                        text_value = x_text_value
                        start_of_range = raw_value
                results_look_incorrect = not self.ranges or (
                    len(self.ranges) == 1 and all(looks_like_float(v) for v in self.ranges.values())
                )
                if not results_look_incorrect:
                    break
            if text_value is None:
                raise NotImplementedError(
                    f"Plugin parameter '{parameter_name}' failed to return a valid string for its"
                    " value."
                )
            self.ranges[(start_of_range, 1)] = text_value

            self.python_name = to_python_parameter_name(cpp_parameter)

        self.min_value = None
        self.max_value = None
        self.step_size = None
        self.approximate_step_size = None
        self.type: Type = str

        if all(looks_like_float(v) for v in self.ranges.values()):
            self.type = float
            float_ranges = {
                k: float(strip_common_float_suffixes(v)) for k, v in self.ranges.items()
            }
            self.min_value = min(float_ranges.values())
            self.max_value = max(float_ranges.values())

            if not self.label:
                # Try to infer the label from the string values:
                a_value = next(iter(self.ranges.values()))
                if isinstance(a_value, str):
                    stripped_value = strip_common_float_suffixes(a_value, strip_si_prefixes=False)
                    if (
                        stripped_value != a_value
                        and isinstance(stripped_value, str)
                        and stripped_value in a_value
                    ):
                        # We probably have a label! Iterate through all values just to make sure:
                        all_possible_labels = set()
                        for value in self.ranges.values():
                            if not isinstance(value, str):
                                continue
                            stripped_value = strip_common_float_suffixes(
                                value, strip_si_prefixes=False
                            )
                            if not isinstance(stripped_value, str):
                                continue
                            all_possible_labels.add(value.replace(stripped_value, "").strip())
                        if len(all_possible_labels) == 1:
                            self._label = next(iter(all_possible_labels))

            sorted_values = sorted(float_ranges.values())
            first_derivative_steps = set(
                [round(abs(b - a), 8) for a, b in zip(sorted_values, sorted_values[1:])]
            )
            if len(first_derivative_steps) == 1:
                self.step_size = next(iter(first_derivative_steps))
            elif first_derivative_steps:
                self.approximate_step_size = sum(first_derivative_steps) / len(
                    first_derivative_steps
                )
            self.ranges = dict(float_ranges)
        elif len(self.ranges) == 2 and (
            TRUE_BOOLEANS & {(v.lower() if isinstance(v, str) else v) for v in self.ranges.values()}
        ):
            self.type = bool
            self.ranges = {
                k: (v.lower() if isinstance(v, str) else v) in TRUE_BOOLEANS
                for k, v in self.ranges.items()
            }
            self.min_value = False
            self.max_value = True
            self.step_size = 1

        self.valid_values = list(self.ranges.values())
        self.range = self.min_value, self.max_value, self.step_size
        self._value_to_raw_value_ranges = {value: _range for _range, value in self.ranges.items()}