def _insert_step(self, time_range, time_index, param_index, envelope, value): param = self.parameters[param_index] envelope_value = self._parameter_floats[time_index][param_index] if param.is_quantized: value_to_insert = clamp(envelope_value + value / EnumerableSetting.STEP_SIZE, param.min, param.max) else: value_range = param.max - param.min value_to_insert = clamp(envelope_value + value * value_range, param.min, param.max) self._parameter_floats[time_index][param_index] = value_to_insert envelope.insert_step(time_range[0], time_range[1] - time_range[0], value_to_insert)
def _touch_strip_to_scroll_position(self, value, offset): detailed = self._shift_button and self._shift_button.is_pressed() max_pitchbend = 16384.0 num_pad_rows = 32 max_pad_row = 28 bank_size = 4 offsetted_value = clamp(value - offset, 0, max_pitchbend) return min(int(offsetted_value / max_pitchbend * num_pad_rows), max_pad_row) if detailed else clamp( int( int(value / max_pitchbend * num_pad_rows + 3) / float(bank_size)) * bank_size - 3, 0, max_pad_row)
def _normalize_offset(self, index): if index >= 0: if index >= self._offset + self._num_visible_items: self._offset = index - (self._num_visible_items - 1) elif index < self._offset: self._offset = index self._offset = clamp(self._offset, 0, len(self._items) - self._num_visible_items)
def handle_value(self, value, notify): range, position = self.handle.range, self.handle.position if not self._grabbed and range[0] <= value - position < range[1]: self._offset = value - position self._grabbed = True else: notify(clamp(value - self._offset, 0, MAX_PITCHBEND))
def _on_content_lists_changed(self): components = self._list_components contents = self._browser_model.content_lists messages = self._browser_model.empty_list_messages for component, content, message in map(None, components, contents, messages): if component != None: component.scrollable_list = content component.empty_list_message = message active_lists = len(contents) num_head = clamp(active_lists - 1, 0, self.NUM_COLUMNS - 1) head = components[:num_head] last = components[num_head:] def set_data_sources_with_separator(component, sources, separator): for source in sources: source.separator = separator component.set_data_sources(sources) component.set_enabled(True) for idx, component in enumerate(head): offset = idx * self.COLUMN_SIZE sources = self._data_sources[offset:offset + self.COLUMN_SIZE] set_data_sources_with_separator(component, sources, '|') if last: sources = self._data_sources[num_head * self.COLUMN_SIZE:] set_data_sources_with_separator(last[0], sources, '') for component in last[1:]: component.set_enabled(False) self.set_select_buttons(self._select_buttons) self.set_state_buttons(self._state_buttons) self.set_encoder_controls(self._encoder_controls)
def _on_record_quantization_value(self, value): self._record_quantization_float = clamp( self._record_quantization_float + value, 0.0, 1.0) self._record_quantization = float_to_record_quantization( self._record_quantization_float) self._update_record_quantization() self._update_record_quantization_display()
def convert_value_to_graphic(value, value_range): value_bar = GRAPH_VOL graph_range = float(len(value_bar)) value = clamp(int(value / value_range * graph_range), 0, len(value_bar) - 1) display_string = value_bar[value] return display_string
def _on_clip_warp_mode_value(self, value): if self._clip != None: self._warp_mode_encoder_value = clamp(self._warp_mode_encoder_value + value, 0.0, 1.0) if self._clip.warping: warp_mode_index = int(self._warp_mode_encoder_value * (len(self._available_warp_modes) - 1)) self._clip.warp_mode = self._available_warp_modes[warp_mode_index] return
def _touch_strip_to_scroll_position(self, value, offset): detailed = self._shift_button and self._shift_button.is_pressed() max_pitchbend = 16384.0 num_pad_rows = 32 max_pad_row = 28 bank_size = 4 offsetted_value = clamp(value - offset, 0, max_pitchbend) return min(int(offsetted_value / max_pitchbend * num_pad_rows), max_pad_row) if detailed else clamp(int(int(value / max_pitchbend * num_pad_rows + 3) / float(bank_size)) * bank_size - 3, 0, max_pad_row)
def clamp(self, time, extra_time=0.0): result = clamp( self._looped_time(time, extra_time), self.left_boundary(), self.start - self.offset + self.length - BEAT_TIME_EPSILON) if result < self.clip_start: return result - self.clip_start + self.clip_end else: return result
def _add_offset_to_selected_index(self, offset): if self.is_enabled() and self._scrollable_list: with self._delay_activation(): with self._in_encoder_selection(): self._selected_index_float = clamp( self._selected_index_float + offset * self.ENCODER_FACTOR, 0, len(self._scrollable_list.items) ) self._scrollable_list.select_item_index_with_border(int(self._selected_index_float), 1)
def _set_option_names(self, value): self._option_names = value if self._selected_option: currently_selected_option = self.selected_option self.selected_option = clamp(self._selected_option, 0, len(self._option_names) - 1) if currently_selected_option != self.selected_option: self.notify_selected_option(self.selected_option) self._update_data_sources()
def prev_page(self): if self.can_scroll_up(): current_page = self.selected_item_index / self.num_visible_items last_page_index = len(self.items) - self.num_visible_items if self.selected_item_index <= last_page_index: index = clamp((current_page - 1) * self.num_visible_items, 0, len(self.items) - self.num_visible_items) else: index = max(len(self.items) - self.num_visible_items, 0) self.select_item_index_with_offset(index, 0)
def next_page(self): if self.can_scroll_down(): current_page = self.selected_item_index / self.num_visible_items last_page_index = len(self.items) - self.num_visible_items if self.selected_item_index < last_page_index: index = clamp((current_page + 1) * self.num_visible_items, 0, len(self.items) - self.num_visible_items) else: index = len(self.items) - 1 self.select_item_index_with_offset(index, 0)
def _touch_strip_to_page_position(self, value): bank_size = self._slideable.page_length num_pad_rows = self._slideable.position_count max_pad_row = num_pad_rows - bank_size offset = bank_size - self._slideable.page_offset return clamp( int( int(value / MAX_PITCHBEND * num_pad_rows + offset) / float(bank_size)) * bank_size - offset, 0, max_pad_row)
def clamp(self, time, extra_time=0.0): result = clamp( self._looped_time(time, extra_time), self.left_boundary(), self.start - self.offset + self.length - BEAT_TIME_EPSILON, ) if result < self.clip_start: return result - self.clip_start + self.clip_end else: return result
def _add_offset_to_selected_index(self, offset): if self.is_enabled() and self._scrollable_list: with self._delay_activation(): with self._in_encoder_selection(): self._selected_index_float = clamp( self._selected_index_float + offset * self.ENCODER_FACTOR, 0, len(self._scrollable_list.items)) self._scrollable_list.select_item_index_with_border( int(self._selected_index_float), 1)
def _set_option_names(self, value): self._option_names = value self.select_buttons.control_count = len(value) if self._selected_option: currently_selected_option = self.selected_option self.selected_option = clamp(self._selected_option, 0, len(self._option_names) - 1) if currently_selected_option != self.selected_option: self.notify_selected_option(self.selected_option) self._update_select_buttons() self._update_data_sources()
def visible_drum_pads(self): if self._visible_drum_pads and self._all_drum_pads: first_pad = first(self._visible_drum_pads) if first_pad: size = self.width * self.height first_note = first_pad.note if first_note > 128 - size: size = 128 - first_note offset = clamp(first_note, 0, 128 - len(self._visible_drum_pads)) return self._all_drum_pads[offset : offset + size] return []
def select_item_index_with_border(self, index, border_size): """ Selects an item with an index. Moves the view if the selection would exceed the border of the current view. """ if index >= 0 and index < len(self._items): if not in_range(index, self._offset + border_size, self._offset + self._num_visible_items - border_size): offset = index - (self._num_visible_items - 2 * border_size) if self.selected_item_index < index else index - border_size self._offset = clamp(offset, 0, len(self._items)) self._normalize_offset(index) self._do_set_selected_item_index(index)
def select_item_index_with_offset(self, index, offset): """ Selects an item index but moves the view such that there are, if possible, 'offset' number of elements visible before the selected one. Does nothing if the item was already selected. """ if not (index != self.selected_item_index and index >= 0 and index < len(self._items) and self.selected_item_index != -1): raise AssertionError self._offset = clamp(index - offset, 0, len(self._items)) self._normalize_offset(index) self._do_set_selected_item_index(index)
def visible_drum_pads(self): if self._visible_drum_pads and self._all_drum_pads: first_pad = first(self._visible_drum_pads) if first_pad: size = self.width * self.height first_note = first_pad.note if first_note > 128 - size: size = 128 - first_note offset = clamp(first_note, 0, 128 - len(self._visible_drum_pads)) return self._all_drum_pads[offset:offset + size] return []
def select_item_index_with_border(self, index, border_size): """ Selects an item with an index. Moves the view if the selection would exceed the border of the current view. """ if self.fixed_offset is not None: self.select_item_index_with_offset(index, self.fixed_offset) elif index >= 0 and index < len(self._items): if not in_range(index, self._offset + border_size, self._offset + self._num_visible_items - border_size): offset = index - (self._num_visible_items - 2 * border_size) if self.selected_item_index < index else index - border_size self._offset = clamp(offset, 0, len(self._items)) self._normalize_offset(index) self._do_set_selected_item_index(index)
def _on_content_lists_changed(self): components = self._list_components contents = self._browser_model.content_lists[self._scroll_offset:] messages = self._browser_model.empty_list_messages scroll_depth = len(self._browser_model.content_lists) - len( self._list_components) self._max_scroll_offset = max(0, scroll_depth + 2) self._max_hierarchy = max(0, scroll_depth) for component, content, message in map(None, components, contents, messages): if component != None: component.scrollable_list = content component.empty_list_message = message active_lists = len(contents) num_head = clamp(active_lists - 1, 0, self.NUM_COLUMNS - 1) head = components[:num_head] last = components[num_head:] def set_data_sources_with_separator(component, sources, separator): for source in sources: source.separator = separator component.set_data_sources(sources) component.set_enabled(True) for idx, component in enumerate(head): offset = idx * self.COLUMN_SIZE sources = self._data_sources[offset:offset + self.COLUMN_SIZE] set_data_sources_with_separator(component, sources, '|') if last: offset = num_head * self.COLUMN_SIZE scrollable_list = last[0].scrollable_list if scrollable_list and find_if(lambda item: item.content.is_folder, scrollable_list.items): sources = self._data_sources[offset:offset + self.COLUMN_SIZE] map(DisplayDataSource.clear, self._data_sources[offset + self.COLUMN_SIZE:]) else: sources = self._data_sources[offset:] set_data_sources_with_separator(last[0], sources, '') for component in last[1:]: component.set_enabled(False) self.set_select_buttons(self._select_buttons) self.set_state_buttons(self._state_buttons) self.set_encoder_controls(self._encoder_controls) self._update_navigation_button_state() return
def _on_content_lists_changed(self): components = self._list_components contents = self._browser_model.content_lists[self._scroll_offset:] messages = self._browser_model.empty_list_messages scroll_depth = len(self._browser_model.content_lists) - len(self._list_components) self._max_scroll_offset = max(0, scroll_depth + 2) self._max_hierarchy = max(0, scroll_depth) for component, content, message in map(None, components, contents, messages): if component != None: component.scrollable_list = content component.empty_list_message = message active_lists = len(contents) num_head = clamp(active_lists - 1, 0, self.NUM_COLUMNS - 1) head = components[:num_head] last = components[num_head:] def set_data_sources_with_separator(component, sources, separator): for source in sources: source.separator = separator component.set_data_sources(sources) component.set_enabled(True) for idx, component in enumerate(head): offset = idx * self.COLUMN_SIZE sources = self._data_sources[offset:offset + self.COLUMN_SIZE] set_data_sources_with_separator(component, sources, '|') if last: offset = num_head * self.COLUMN_SIZE scrollable_list = last[0].scrollable_list if scrollable_list and find_if(lambda item: item.content.is_folder, scrollable_list.items): sources = self._data_sources[offset:offset + self.COLUMN_SIZE] map(DisplayDataSource.clear, self._data_sources[offset + self.COLUMN_SIZE:]) else: sources = self._data_sources[offset:] set_data_sources_with_separator(last[0], sources, '') for component in last[1:]: component.set_enabled(False) self.set_select_buttons(self._select_buttons) self.set_state_buttons(self._state_buttons) self.set_encoder_controls(self._encoder_controls) self._update_navigation_button_state() return
def set(self, base_name=None, playing_slot_index=None, preset_index=None): # type: (Optional[str], Optional[int], Optional[int]) -> None playing_slot_index = playing_slot_index if playing_slot_index is not None else self.playing_slot_index playing_slot_index = clamp(playing_slot_index, -1, len(self.track.song.scenes) - 1) if base_name and base_name != self.base_name: # noinspection PyUnresolvedReferences self.notify_base_name() name = "%s - %s" % (base_name if base_name else self.base_name, playing_slot_index) if self.track.instrument: preset_index = preset_index if preset_index is not None else self.preset_index preset_index = max(0, preset_index) name += " - %s" % preset_index self.track.name = name
def _tempo_encoder_value(self, value): if self.is_enabled(): step = 0.1 if self.shift_button.is_pressed else 1.0 amount = value - 128 if value >= 64 else value self.song().tempo = clamp(self.song().tempo + amount * step, 20, 999)
def _scroll_position(self, delta): if self.is_enabled(): model = self._slideable model.position = clamp(model.position + delta, 0, model.position_count - model.page_length)
def _touch_strip_to_page_position(self, value): bank_size = self._slideable.page_length num_pad_rows = self._slideable.position_count max_pad_row = num_pad_rows - bank_size offset = bank_size - self._slideable.page_offset return clamp(int(int(value / MAX_PITCHBEND * num_pad_rows + offset) / float(bank_size)) * bank_size - offset, 0, max_pad_row)
def on_num_sends_changed(self): self.send_select_buttons.control_count = clamp(self.num_sends, 0, 8)
def _clamp_send_index(self): self._selected_send_index = clamp(self._selected_send_index, 0, self.num_sends - 1) if self._selected_send_index % 2 > 0: self._selected_send_index -= 1
def _on_clip_transpose_value(self, value): if self._clip != None: self._pitch_coarse = clamp( self._pitch_coarse + value * 96 * self._encoder_factor, -48.0, 48.0) self._clip.pitch_coarse = int(self._pitch_coarse)
def clamp(self, time, extra_time = 0.0): return clamp(time + extra_time, self.left_boundary(), self.right_boundary())
def _jump_relative(self, relative_position): current_position = self.values.index(self.value) new_position = clamp(current_position + relative_position, 0, len(self.values) - 1) self.value = self.values[new_position] return new_position if current_position != new_position else None
def _on_clip_gain_value(self, value): if self._clip != None: delta = value * self._encoder_factor new_gain = self._clip.gain + delta self._clip.gain = clamp(new_gain, 0.0, 1.0)
def _on_quantize_amount_value(self, value): self._quantize_amount = clamp(self._quantize_amount + value, 0.0, 1.0) self._update_quantize_amount_display()
def _on_swing_amount_value(self, value): self.song().swing_amount = clamp(self.song().swing_amount + value * 0.5, 0.0, 0.5)
account current modifiers. If the note is not within the given step, returns the note as-is. If the time_step is inside a loop, the last part of the loop is considered as being the same as the part just before the loop, so the resulting note may, in this case, jump between the beginning and the end. """ if time_step.includes_time(time): time = time_step.clamp(time, self._nudge_offset) if self._length_offset <= -time_step.length and length + self._length_offset < time_step.length: if length > time_step.length: length = time_step.length else: length = max(0, length + self._length_offset) velocity = 127 if self.full_velocity else clamp(velocity + self._velocity_offset, 1, 127) mute = not step_mute if self._mute_button and self._mute_button.is_pressed() else mute return (pitch, time, length, velocity, mute) def _min_max_for_notes(self, notes, start_time, min_max_values = None): for note in notes: note_values = list(note[:4]) note_values[1] -= start_time for index, value in enumerate(note_values): if not min_max_values: min_max_values = [(99999, -99999)] * 4 min_value, max_value = min_max_values[index]
def _change_swing_amount_value(self, value): self._set_swing_amount_value( clamp(self.song().swing_amount + value * 0.025, 0.0, 0.99))
def _on_tracks_changed(self): tracks = tracks_to_use_from_song(self.song()) self._track_offset = clamp(self._track_offset, 0, len(tracks) - 1) self._on_fired_slot_index_changed.replace_subjects(tracks, count()) self._on_playing_slot_index_changed.replace_subjects(tracks, count()) self._update_all_stop_buttons()
def _on_record_quantization_value(self, value): self._record_quantization_float = clamp(self._record_quantization_float + value, 0.0, 1.0) self._record_quantization = float_to_record_quantization(self._record_quantization_float) self._update_record_quantization() self._update_record_quantization_display()
account current modifiers. If the note is not within the given step, returns the note as-is. If the time_step is inside a loop, the last part of the loop is considered as being the same as the part just before the loop, so the resulting note may, in this case, jump between the beginning and the end. """ if time_step.includes_time(time): time = time_step.clamp(time, self._nudge_offset) if self._length_offset <= -time_step.length and length + self._length_offset < time_step.length: if length > time_step.length: length = time_step.length else: length = max(0, length + self._length_offset) velocity = 127 if self.full_velocity else clamp( velocity + self._velocity_offset, 1, 127) mute = not step_mute if self._mute_button and self._mute_button.is_pressed( ) else mute return (pitch, time, length, velocity, mute) def _min_max_for_notes(self, notes, start_time, min_max_values=None): for note in notes: note_values = list(note[:4]) note_values[1] -= start_time for index, value in enumerate(note_values): if not min_max_values: min_max_values = [(99999, -99999)] * 4 min_value, max_value = min_max_values[index] min_max_values[index] = (min(value, min_value), max(value, max_value))
def clamp(self, time, extra_time=0.0): return clamp(time + extra_time, self.left_boundary(), self.right_boundary())
def _page_length_in_beats(self): return clamp(self._paginator.page_length, 0.5, self._one_measure_in_beats)
def _on_clip_transpose_value(self, value): if self._clip != None: self._pitch_coarse = clamp(self._pitch_coarse + value * 96 * self._encoder_factor, -48.0, 48.0) self._clip.pitch_coarse = int(self._pitch_coarse)