New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
should we zeropad [*~] with mc signals of different length? #2009
Comments
Yes, this behavior is intentional. There is no obvious way how to apply a binary operator to a 5-channel and 3-channel signal. Wrap around, zero-padding, ignoring excess channels, etc. are all equally valid. The nice thing about wrap around is that it doesn't require an exception for single-channel signals. Side note: some objects have a different behavior.
That's exactly the point. If the user wants a specific behavior, they can implement it. (This will become easier with additional I don't see a need to change the current behavior, but maybe it is not documented sufficiently? ;-) |
nope, and before documenting it I wanted to make things sure. I still think it is counterintuitive, but I guess it's just arbitrary and a byproduct on how to deal with single channels as I pointed. The thing is that someone was already seeing this as a special feature and hoping for yet more features on how to deal with this based on the way supercollider works, giving it more special commands and arguments on how the wrapping and distribution would work, giving it different breakpoints with interleaving and whatot and, as I see it, this is not "pd-like" or something to expect and yeah, one should always and just build the channel list as desired outside the scope of binary operators. So I wouldn't like people abusing this, treating it as "feature" and then suggesting "hey, can I also this, and that?"... cause arbitrary as it is, I don't see it as something particularly useful and could make sense in the same scenario as SC as part of a full set of ideas. zero-padding seems a nice candidate for a single arbitrary decision but yeah, the code would need to be a bit less lazy, haha |
I think all these things can be done with (new)
Zero-padding might make sense for One nice thing about wrapping is that it works equally "well" for all binops. |
see discussion in pure-data#2009
I documented the way it is but will keep this open so maybe miller says something. I gave the example of [*~] so I expected it to be a good candidate for zero padding and don't see an issue in any other case really |
Thanks!
Actually, I know realized that it is not entirely clear what you mean by "zero-padding" in the first place. Are you talking about the inputs - or the result? There is a big difference! Also, I forgot about another strategy: only use the smaller number of channels and discard the rest. But again, there is no "natural" way of dealing with mismatching channel counts in binops. It is the responsibility of the user to fill up missing channels (or discard excess channels) in a way that is most appropriate for the task at hand. Wrap-around is a good default because it is easy to implement and it is the only one that does not require special treatment of single-channel inputs. |
Hello! i am the one porres was talking about that thinks this is a "special feature". For me this isn't special, is just normal and a good choice for default, i wouldn't like to waste signal processing creating many empty signals, so i don't think that zero pad makes sense either, but having a choice to create a shorter signal would make more sense than zero pad. what i said about supercollider, is about the possibility of having adverbs that change the way the channels interact with each other in the binop operation, currently on sc there are 5 ways (1 one them doesn't make sense in pd, but maybe the other 4 could be interesting, but this is all, just interesting). For reference, in supercollider documentation: https://doc.sccode.org/Reference/Adverbs.html about the "pd way" of doing, i guess i can imagine adding a symbol argument to the binops that could act like the symbol argument for [inlet~] and [outlet~], The situation there is about upsampling and downsampling, and we can choose [inlet~ pad] [inlet~ hold] and [inlet~ lin] to choose how we want the operation on the signal to be performed, and i think binops could do something similar: so, taking the examples from supercollider (excluding "table" adverb, that makes no sense for pd): since the current default is wrap, i think we could have the next could be short, which just takes the smallest size of the two signals and discard the rest: as an alternative to wrap, there is also folding: and an interesting one, that makes more channels, is the cross one: I guess that the short and the fold could be achieved by creating other snake~ methods too, the cross is a bit more complicated so, for the short case, considering a signal A bigger in size than a signal B, and if i can constrain the signal A by the size of signal B, which gives me Ac, Ac + B is the same as short(A + B), in pd:
for folding, we could split the second signal to remove the last element, than merge with the original one, and then do the binop operation: EDIT: this is wrong, i would need to split the B signal to remove the tail, and reverse the signal without its tail and then merge the original B with the reversed signal without tail, but i don't have time now to fix the ascii art ...
the cross one could be done using the default [snake~ out], but i would have to manually connect the number of the signals i want to cross
So, i think that having the possibility of choosing the method directly on the binops is the cleaner solution, but i also understand that extending snake~ methods would make the users have more control on how they want to manage their signals. But in both situations, i think that having the wrap method the default is a very good choice since it can derive the other possibilities and makes sense for the 1 signal case |
imho, overloading the binops with different strategies: that way lies madness. since the built-in binops all share the same codebase, it's probably easy enough to extend them to support such a thing as an argument to specify the signal extension strategy. i'm therefore with @Spacechild1 to
the first option is the only well-defined one, albeit it's a bit harsh (and i think @Spacechild1 did not actually propose that). |
I think @abreubacelar has raised interesting use cases and I am also familiar with sclang adverbs. However, all of these can - and should! - be implemented as To reiterate what @umlaeute has written: With Otherwise M objects would need to implement N adverbs - in a consistent matter at that! I think it is pretty obvious which one is the better strategy. |
I guess my point is that zero padding seems like a neutral thing, not something people expect as a useful and desired behaviour for implementing stuff, well, actually, I'd expect it as the natural behaviour but I mean not as a desired and useful feature. My point is that there is no sensible desired feature and I'm no t excited about people treating this as a desired feature, it'd be more like "abusing" it, just like people usually abuse other entries and back doors in Pd (like using a numeric float into an object and treat it as an abbreviation of [float]). Seems like a sane prediction that people would need to give these objects a list of channels of the same length and that the operations would work "one by one". I'd go as far as zeroing out the result not the input for missing channels and it might be a way of telling people they probably missed or made a mistake. It'd also force them to be careful and deal with the channel matching. Maybe shortening the number of output channels could do the same and might even be 'better', I agree... but I guess the point here is to not worry about what to do and just have this as a somewhat obscure feature for the sake of code simplicity. I have documented it, but I'm not giving explicit examples showing how great it is encouraging people to use it.
+1 (but I guess I was already clear about it)
I can give it in since it's already implemented like this and because of the simplicity implementation advantage that works as desired for single channels |
Just to demonstrate the
If the inputs for Just to show that this also works with more "advanced" adverbs. (Of course, |
I think something along the lines of "identity padding" would make more sense than zero-padding, when considering alternatives to wrap. As in, pad with whatever values correspond with no change for a given operation. So for addition and subtraction, it would pad with zeroes, while for multiplication and division it would pad with ones -- and so on, for any other operation that this makes sense for. Also this would be computationally simple because it amounts to passing any excess channels directly through with no change. |
You wouldn't have to pad the shorter input, but rather copy the larger input. But yes, this would also be a valid strategy. However, it requires a special case for single-channel inputs. Again, any of these strategies are equally valid, it really depends on the use case. There is no point in trying to find the "best" behavior because it simply does not exist. |
I'd rather they'd all become 0 instead.
yup, it's pretty clear people have different expectations and ideas, so I'm settling to whatever we have for the sake of "whatever" and laziness to deal with expectations and possibilities. Closing by giving this topic up... |
At least this thread has brought a few more interesting possible |
I have a spread object in ELSE and I should add mc support to it... it takes whatever input channels and spreads over another number of channels, like getting 8 channels and spreading it over the stereo field. Would be a pretty cool [snake~] method tough |
How is [*~] and other objects supposed to work when you have two multichannel inputs of different channel length?
This is how it works now. Say you have 5 channels on one side (A) and 3 on the other (B). The first 3 channels of each A & B are combined but then for the channel 4 and 5 of A are multiplied to channels 1 and 2 of B.
Is this intentional? I'd expect that the remaining channels 4 and 5 of A would combine with 0 values for the B side has no 4 and 5 channels.
I know that if you have a single channel on one side it makes sense that the single value is multiplied with each channel of the other side, but this would be a special case and maybe the way things were coded to make this work gave us this bug as a side effect.
Or is it an intended feature? I think that we could discuss different ways and choose how to work with this, but having this as the only option seems weird.
One can always create a multichannel signal of the exact same length and create the exact desired list, be it with repeated values or not.
So, my intuition would ask to just pad values to 0 when you have one side with more than one channel and a signal with even more channels on the other side.
ping @millerpuckette
The text was updated successfully, but these errors were encountered: