Run shortcut, store "2". next run, read "2" and go to "3" instead - i.e. "incremental shortcut"

It’s hard to put this into words.

I want to start from 2, when I run the shortcut for the first time. then when i run the shortcut for the second time, it should read “oh, 2” and go “well, 3”. then read 3, go to 4.
until reaching the end of a list.

how would this be done, please?

This could be done with a script (i.e. tool) that uses a Document to store values and then call whatever via the API

thanks. i did start saving the preferences.Counter and using that. but when i switch from next (+1) to previous (-1) i need to press the shortcut another time before it will show something.

Sounds like it has to do with the order you are updating the counter and executing your action. Maybe if you shared more about how your code is written it would be easier to help.

2 Likes

i kinda almost have it working, now the +1 / -1 needs to be adjusted a bit. i think i’ll get there. almost done.

ok i’m ready to ask for advice and show what i’m working with…

the issue is that when i reverse direction (instead of going nextSlice, i go prevSlice) - the first time the shortcut is run, it displays the exact same slice. and if i go from prevSlice to nextSlice - the first run displays the exact same slice.

how do i solve this logic? since on nextSlice, the preferences.sliceCounter.value is increased by +1, and by prevSlice, the preferences.sliceCounter.value is increased by -1, i need it to be able to detect, “previous movement was next” == if running prevSlice, act as if sliceCounter actually provided -1 (i.e. nextSlice set it to 4, prevSlice should start as if it’s 3.) or prevSlice set it to 2, and nextSlice should then be 3.

apart from this logic issue, the script works beautifully.

-- Function to select the next slice
function selectNextSliceInOriginalSample()
  local instrument = renoise.song().selected_instrument
  local sample = instrument.samples[renoise.song().selected_sample_index]
  local sliceMarkers = sample.slice_markers
  local sampleLength = sample.sample_buffer.number_of_frames

  if #sliceMarkers < 2 or not sample.sample_buffer.has_sample_data then
    renoise.app():show_status("Not enough slice markers or sample data is unavailable.")
    return
  end

  local currentSliceIndex = preferences.sliceCounter.value
  local nextSliceIndex = currentSliceIndex + 1
  if nextSliceIndex > #sliceMarkers then
    nextSliceIndex = 1
  end

  local thisSlice = sliceMarkers[currentSliceIndex]
  local nextSlice = sliceMarkers[nextSliceIndex]

  local thisSlicePadding = (currentSliceIndex == 1 and thisSlice < 1000) and thisSlice or math.max(thisSlice - 1000, 1)
  local nextSlicePadding = (nextSliceIndex == 1) and math.min(nextSlice + sampleLength, sampleLength) or math.min(nextSlice + 1354, sampleLength)

  renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_SAMPLE_EDITOR
  sample.sample_buffer.display_range = {thisSlicePadding, nextSlicePadding}
  sample.sample_buffer.display_length = nextSlicePadding - thisSlicePadding

  renoise.app():show_status(string.format("Slice Info - Current index: %d, Next index: %d, Slice Start: %d, Slice End: %d", currentSliceIndex, nextSliceIndex, thisSlicePadding, nextSlicePadding))
  
  preferences.sliceCounter.value = nextSliceIndex
end


-- Function to select the previous slice with proper handling of slice wrapping
function selectPreviousSliceInOriginalSample()
  local instrument = renoise.song().selected_instrument
  local sample = instrument.samples[renoise.song().selected_sample_index]
  local sliceMarkers = sample.slice_markers
  local sampleLength = sample.sample_buffer.number_of_frames
  
  if #sliceMarkers < 2 or not sample.sample_buffer.has_sample_data then
    renoise.app():show_status("Not enough slice markers or sample data is unavailable.")
    return
  end
  
  local currentSliceIndex = preferences.sliceCounter.value
  local previousSliceIndex = currentSliceIndex - 1
  
  if previousSliceIndex < 1 then
    previousSliceIndex = #sliceMarkers  -- Wrap to the last slice
  end

  local previousSlice = sliceMarkers[previousSliceIndex]
  local nextSliceIndex = previousSliceIndex == #sliceMarkers and 1 or previousSliceIndex + 1
  local nextSlice = sliceMarkers[nextSliceIndex]

  -- Calculate the padding for display
  local previousSlicePadding = math.max(previousSlice - 1000, 1)
  local nextSlicePadding = math.min(nextSlice + 1354, sampleLength)

  -- Adjust for wraparound display issue when navigating from first to last slice
  if previousSliceIndex == #sliceMarkers and currentSliceIndex == 1 then
    nextSlicePadding = sampleLength
  end

  -- Set display parameters in the sample editor
  renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_SAMPLE_EDITOR
  sample.sample_buffer.display_range = {previousSlicePadding, nextSlicePadding}
  sample.sample_buffer.display_length = nextSlicePadding - previousSlicePadding

  -- Show status and update slice counter
  renoise.app():show_status(string.format("Slice Info - Previous index: %d, Current index: %d, Slice Start: %d, Slice End: %d",
                                          previousSliceIndex, nextSliceIndex, previousSlicePadding, nextSlicePadding))
  
  preferences.sliceCounter.value = previousSliceIndex
end

-- Function to reset the slice counter
function resetSliceCounter()
  preferences.sliceCounter.value = 1
  renoise.app():show_status("Slice counter reset to 1. Will start from the first slice.")
  selectNextSliceInOriginalSample()
end

-- Keybindings
renoise.tool():add_keybinding{name="Global:Paketti:Select Padded Slice Next Slice", invoke=selectNextSliceInOriginalSample}
renoise.tool():add_keybinding{name="Global:Paketti:Select Padded Slice Previous", invoke=function() selectPreviousSliceInOriginalSample() end}
renoise.tool():add_keybinding{name="Global:Paketti:Reset Slice Counter", invoke=resetSliceCounter}

Padded slice from original sample

i tried a preferences.slicePreviousDirection and setting it to “0” for “previous” and “1” for “next”. but i couldn’t figure out the logic. please help?

p.s. if anyone is wondering what this is, it lets you trim and tweak the slicings so that they hit where they’re supposed to.
and while i like the idea for my own use, there was a request for it from 2022 - and maybe some other years too. Mappable shortcuts to navigate through slice markers (i’m yet to finish going through all the 7300+ ideas and suggestions i’ve archived as PDF per thread, i think i’ve gone through 300 right now.

Hah, coincidently I wrote this exact functionality before for one of my unreleased tools.

Without trying to find the issue in your code I would recommend the following instead

  • Don’t save the counter to the preferences, as you wouldn’t need this value preserved across songs or even instruments. Instead write a function that returns the current slice index based on the cursor/view of the user. This will also solve the issue with the user navigating away from the slice without using your tool and then pressing the shortcut.
  • Write a separate function that receives a slice index and sets up the zoom to cover that slice. This function shouldn’t care about what direction you were coming from, it could just select a slice based on an input number. You can add wrapping and handling no slices here.
  • Finally, implement your shortcuts: the previous one will get the current slice index, decrease it and call the function above. The next will do the same but increase the index instead.

This way you won’t repeat yourself and get rid of other bugs that would arise from your current setup when the user deletes or adds slices, switches instruments or projects.

Hope it helps!

1 Like

what is the slice_index in this case? are we talkin about “2,3” (i.e. slice 2 and slice3)? so i could then use “prev slice” and it’d go “oh, 2,3 is shown, let me jump to 1,2” ?

Depends on how you want to implement it, I’d say it is just a single integer and this zoom function will figure it out if it has any next slice or if it’s the last one in the sample.

You’d query the current slice, if it is zero there are no slices, you do nothing, otherwise offset the index by the direction and wrap around using the number of slices. Then you call your zoom function with that.