..

It’s simple making your custom “songpos” class with a “global_line_index”. That way you can easily convert between global_line_index and normal sequence_index&line_index. I’ve done so and use it in several tools, I think.

Not enough?

PS. I agree that it is something that would make sense to be included natively. (My suspicion is that devs didn’t wanna open a cesspit of confusion occurring when patterns are used more than once and data is being manipulated…)

Yep, I’ve done this kind of thing too.

https://github.com/renoise/xrnx/blob/master/Tools/com.renoise.xLib.xrnx/source/xLib/classes/xSongPos.lua

It has options for how to treat pattern loops and block loops too (realtime usage).

Hm, yes. Sure. But this would be again custom made.

I suggested this also, to define a standard for handling such cases. So not every tool does it different.

Also I cannot imagine any tool so far that handles pattern boundaries’ cases?

Or just integrate a class to the standard api, like Joule said.

Again… a less complete but more simple and slightly incomplete class here :wink: Usable if you’re just doing iterative tasks.

Click to view contents
local rns = renoise.song()
class 'gSongPos'
function gSongPos:__init(sequence_index, line_index)
 self._line_index = line_index
 self._sequence_index = sequence_index
end
gSongPos.line_index = property(
 function(obj) return obj._line_index end,
 function(obj, val)
 obj._line_index = val
 end)
gSongPos.pattern_index = property(
 function(obj) return rns.sequencer.pattern_sequence[obj._sequence_index] end)
gSongPos.sequence_index = property(
 function(obj) return obj._sequence_index end,
 function(obj, val)
 obj._sequence_index = val
 end)
gSongPos.global_line_index = property(
 function(obj)
 local line = obj._line_index
 for seq_index = 1, obj._sequence_index - 1 do
 line = line +
 rns:pattern(rns.sequencer.pattern_sequence[seq_index]).number_of_lines
 end
 return line
 end,
 function(obj, val)
 local lines = 0
 for seq_index, pat_index in ipairs(rns.sequencer.pattern_sequence) do
 lines = lines + rns:pattern(pat_index).number_of_lines
 if lines >= val then
 lines = lines - rns:pattern(pat_index).number_of_lines
 obj._line_index = val - lines
 obj._sequence_index = seq_index
 return nil
 end
 end
 end)

(Hoping I didn’t mess something up…)

Thx Joule, but somehow missed my point:

The idea was to make the api as simple as possible for new comers. So if you write a line number outside the current pattern, the renoise api would automatically place it in the other pattern, or even would duplicate the other pattern on-the-fly, if it wasn’t a unique one.

This would be :

  • 100% compatible to all existing tools
  • very very easy to use
  • make an extension of any existing tool quite easy

So renoise api handles boundaries problems, not the tool coder.

Now more clear?

So the line index actually was a pre generated array pointing to current and other patterns. Including a logic to auto duplicate patterns.

I don’t think I misunderstood. If the songpos class would include a global_line_index, that would be just fine I think.

Also, there is already a pattern_iterator available, with several different scopes that could be useful in these cases (but not practical in all cases).

(An important premise: One should be very careful trying to build away ‘ignorance’ by adding bloated or somewhat inconsistent syntax or solutions. LUA is a very elegant language, and I think many scripters would cringe if the Renoise API didn’t follow the same feel… I’d probably consider the current pattern_iterator such a bloat, as it doesn’t even add anything in terms of performance.)

Why are you talking about auto duplicating patterns? This idea sounds very specific with a bloat alarm attached :slight_smile:

Because if you extend the operations e.g. To the next pattern and that pattern was already used in the sequence, it would place something on wrong positions. So a simple logic is to auto-duplicate the next pattern as soon as it is used more than once in the sequence.

Is there any reason why this should not be working automatically?

Maybe the cases for an auto duplication are more complex, but is the idea understandable?

Duplicate/make new copy of next pattern , if

  • pattern is not unique AND previous pattern is not always the current pattern in the reused places

Is there any reason why this should not be working automatically?

Well, like joule said, it feels very specific:

Duplicate/make new copy of next pattern , if

  • pattern is not unique AND previous pattern is not always the current pattern in the reused places

What you are describing basically sounds like the logic for a tool :slight_smile:

If the API was designed like this, it would be harder to do something that didn’t do automagic stuff.

If the API was designed like this, it would be harder to do something that didn’t do automagic stuff.

Mh, that is not really true.

Remember that if you still checking for boundaries (like most tools), the suggested “auto”-case would not happen.

So only if you would access line 129 in a 128-line-pattern. Or line -1. etc.

So the coders still can do their own (IMO a bit silly) boundary magic.

My suggestion would in fact not change any behavior of existing tools, but add some really simplicity to auto-circumvent pattern structure… Since most songs nowadays are linear, times for saving 100 bytes of memory are over.

Since most songs nowadays are linear

This is my point exactly, you end up working from assumptions about what it “means” to have a linear song.
Sure, one that starts from the start and ends with the end. Or, as you’re suggestion, maybe the end does not mean the end. Maybe it will extend the song, or start writing from the beginning (wrap around)?

And hey, maybe you’re not working in a linear fashion at all, but want your code to wrap it’s output around the current pattern or block-loop instead?
In the end, this would make the API more complicated than it needs to be.

Much better IMO that it’s up to us as script authors to define these conditions.

Hm,

maybe I still did not explain it properly, or do not understand you correctly…

If you extend - let’s say a note echo effect - to the next pattern, in any case the next pattern has to be unique. Or repeated in combination with the current pattern.

You could still apply the note echo just to the current pattern.

Please explain to me any scenario where the next pattern should not be unique, if it actually holds info related to the current pattern (like a echo tap).

And why does it make the API more complicated? It was exactly my point to absolutely make it simple and 100% backwards compatible.

So I would like to know from you, danoise, if you now will add selection in matrix to the advanced options, how you would do manage those boundary cases? So I can understand what you think is the correct way for it?

So I would like to know from you, danoise, if you now will add selection in matrix to the advanced options, how you would do manage those boundary cases? So I can understand what you think is the correct way for it?

Yes, I saw that other post. You mentioned notes being pushed out the pattern e.g. when using the “nudge down” feature?

As it is, this would obviously be an improvement natively, in Renoise. Because, currently those notes will simply disappear (say, when using “whole song” as the scope, which also will process multiple patterns). So I could definitely see it as an improvement to Renoise itself.

But “automagic” creeps in once the creation of unique patterns and such also applies in the API. That one is purely about raw access to the song data. If you for instance already had programmed a tool that nudges notes and preserves their position, you might have memorized pattern indices to achieve this.

Now, if the API magically was to create a new pattern by itself, that tool would break. See the problem?

Sure, Renoise can have “options” to decide on a given behaviour, but it only spells trouble when a programming language has such a thing.

Ok. So I understand you point of view.

What about to add an additional line-index to the base API then, which can access the whole song structure, and starting with 0 in the current pattern, without auto-adding anything?

And maybe adding this also into the c++ structure, so you also could really easily extend adv. operations? And also easily add selection over boundaries?

Yes, I saw that other post. You mentioned notes being pushed out the pattern e.g. when using the “nudge down” feature?

This also happens for quantization, basically all operations that are placing something new and moving stuff around. In both directions.

Considering that off-by-one errors are one of the most common coding errors, my guess is that if Renoise API automatically placed stuff in the previous / next pattern then you’d get a lot of unintended misplaced notes :slight_smile: