Skip to content
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

SplayAz fails when input array has only one element #1045

Closed
telephon opened this issue Mar 1, 2014 · 10 comments
Closed

SplayAz fails when input array has only one element #1045

telephon opened this issue Mar 1, 2014 · 10 comments
Assignees
Labels
bug Issues that relate to unexpected/unwanted behavior. Don't use for PRs. comp: sclang sclang C++ implementation (primitives, etc.). for changes to class lib use "comp: class library"

Comments

@telephon
Copy link
Member

telephon commented Mar 1, 2014

{ SplayAz.ar(2, [Dust.ar(10)]) }.play;

returns:

PanAz arg: 'in' has bad input: nan
 ARGS:
   numChans: a Dust Dust
   in: nan Float
   pos: 1 Float
   level: 2 Integer
   width: 0.5 Float
SynthDef temp__6 build failed
ERROR: PanAz arg: 'in' has bad input: nan

The reason is that resamp1 doesn't work correctly for size=1.
Both (SplayAz and resamp1) need their own respective fix.

@telephon telephon self-assigned this Mar 1, 2014
@telephon
Copy link
Member Author

telephon commented Mar 2, 2014

*ar { arg numChans = 4, inArray, spread = 1, level = 1, width = 2, center = 0.0, orientation = 0.5, levelComp = true;
    var n = max(1, inArray.size);
    var pos = if(n == 1) { 0 } { [ center - spread, center + spread ].resamp1(n) };
    if (levelComp) { level = level * n.reciprocal.sqrt };
    ^PanAz.ar(numChans, inArray, pos, level, width, orientation).flop.collect(Mix(_))
}

and:

resamp1 { arg newSize;
    var factor = this.size - 1 / (newSize - 1).max(1);
        ^this.species.fill(newSize, { |i| this.blendAt(i * factor) })
    }

@LucaDanieli
Copy link
Contributor

I think that "center" instead of "0" would be a good solution, to allow the user to move the source:

var pos = if(n == 1) { center } { [ center - spread, center + spread ].resamp1(n) };

I think also that would be good to inform the user that, when spread=1, array[0] is moved to channel= (numChans/2) counterclockwise.

@telephon
Copy link
Member Author

Good idea, yes.

@timblechmann
Copy link
Contributor

the fix does not look good to me: especially, it introduces a possible division by zero in the resamp functions when passing a newSize of 1. it is probably better to define the semantics of resampling to one element as single-element collection with the mean of the collection. something like:

   resamp1 { arg newSize;
    if (newSize == 1) {
      ^this.species.fill(1, this.mean)
    } {       
      var factor = this.size - 1 / (newSize - 1);
      ^this.species.fill(newSize, { |i| this.blendAt(i * factor) })
  }

@LucaDanieli
Copy link
Contributor

This could solve also the thread "SequenceableCollection resamp0/1
broken (e.g. SplayAz) #727"

It is true that:

[1,6,7].resamp1(4).mean
[1,6,7].mean

return the same values, and if we set newSize= "high number", the result
is subject to little approximation. So probably the Tim's solution is
very good to solve two issues.

Luca

On 15/03/14 16:51, Tim Blechmann wrote:

the fix does not look good to me: especially, it introduces a possible
division by zero in the resamp functions when passing a |newSize| of
|1|. it is probably better to define the semantics of resampling to
one element as single-element collection with the mean of the
collection. something like:

| resamp1 { arg newSize;
if (newSize == 1) {
^this.species.fill(1, this.mean)
} {
var factor = this.size - 1 / (newSize - 1);
^this.species.fill(newSize, { |i| this.blendAt(i * factor) })
}
|


Reply to this email directly or view it on GitHub
#1045 (comment).

@telephon
Copy link
Member Author

I was thinking along the same lines. It isn't entirely clear though if you think about it, because resamp1 leaves the first element in a collection unchanged, irrespective of the new size.

[1, 2, 3, 100].resamp1(2)
[1, 2, 3, 100].resamp1(5)

Now whether that is right or not is another question, but it is a conscious decision of how to think about boundaries when you interpolate. The fix I committed sticks to the conventions so far, perhaps an argument could be added that specifies of how to deal with the boundaries in general (not only for n=1).

@telephon
Copy link
Member Author


[1, 100].resamp1(4) // [ 1, 1.75, 2.5, 27.25, 100 ]
[1].resamp1(4) // [ 1, 34, 67, 100 ]


[1, 100].resamp1(1) // [ 1 ]
[1].resamp1(1) // [ 1 ]

@telephon
Copy link
Member Author

the fix does not look good to me: especially, it introduces a possible division by zero in the resamp functions when passing a newSize of 1.

resamp1 { arg newSize;
        var factor = this.size - 1 / (newSize - 1).max(1);
        ^this.species.fill(newSize, { |i| this.blendAt(i * factor) })
    }

Will never have a division by zero.

@timblechmann
Copy link
Contributor

sry ... diffed in reverse ...

3 resampling to one element will have 3 different possibilities:

  • the first element
  • the mean of first and second element
  • the mean of all elements.

for resamp0, one should probably use the first, for resamp1, i tend to prefer the third option, though no strong preference ...

@telephon
Copy link
Member Author

So how would that be for n -> 1 elements?
The mean of all? Only the first? Only the first and second?
Those options seem not really convincing, I agree.
And what when we resample n -> melements?
Even more complicated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issues that relate to unexpected/unwanted behavior. Don't use for PRs. comp: sclang sclang C++ implementation (primitives, etc.). for changes to class lib use "comp: class library"
Projects
None yet
Development

No branches or pull requests

3 participants