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

Topic/rate fallthrough #1835

Merged
merged 3 commits into from
Sep 6, 2016

Conversation

telephon
Copy link
Member

When determining the rate of a collection of objects, the maximal rate
is returned. Now if the rate happens to be nil, we just assume scalar.
This allows the error to be thrown a bit later, in the UGen that takes
the object as an input. This fixes #1771

When determining the rate of a collection of objects, the maximal rate
is returned. Now if the rate happens to be nil, we just assume scalar.
This allows the error to be thrown a bit later, in the UGen that takes
the object as an input. This fixes supercollider#1771
… as not to give rise to confusions and assume the function as the
receiver of minItem.
@telephon
Copy link
Member Author

discussion on: #1829

@timblechmann
Copy link
Contributor

i don't agree that this is a good solution for #1771. i agree that the error message is bad, but anything which behaves like a ugen should return a rate of scalar, control or audio.

i'd vote for improving the error message instead of accepting the code in #1771. playing back nil sounds like a user bug to me.

@telephon
Copy link
Member Author

This change won't play back nil sounds. It only lets the error appear at the best understood point, namely where nil becomes the input of an Out UGen. As usual, the receiver should be the one to decide what to do with a value.

@telephon
Copy link
Member Author

… but giving it a second thought, what really needs to be correct is that single method that answers the question what is the maximum rate of an array of objects?. Now if one of the objects returns nil, do we count that question as invalid or not?

This question may be asked before the objects are converted into a UGen input.

@timblechmann
Copy link
Contributor

the question should not be: what happens if the object's rate is nil, but rather: what happens if the objects' rate is not understood? someone could pass arbitrary objects, where .rate might return arbitrary values like false or true.

anything, which cannot be compared to scalar, control or audio should throw an exception.

@telephon
Copy link
Member Author

This is what happens (and I think is correct):

{ Out.ar(0, nil); }.asSynthDef

returns

ERROR: Out  input at index  1 ( nil ) is not audio rate

PROTECTED CALL STACK:
    SynthDef:checkInputs    0x10d718b00
        arg this = a SynthDef
        var firstErr = Out  input at index  1 ( nil ) is not audio rate
    SynthDef:finishBuild    0x10d713240
        arg this = a SynthDef
    a FunctionDef   0x10d706000
        sourceCode = "<an open Function>"
    Function:prTry  0x10c7c5080
        arg this = a Function
        var result = nil
        var thread = a Thread
        var next = nil
        var wasInProtectedFunc = false

CALL STACK:
    Exception:reportError   0x110dad9c8
        arg this = <instance of Error>
    Nil:handleError   0x10d9a3d48
        arg this = nil
        arg error = <instance of Error>
    Thread:handleError   0x10e5c1198
        arg this = <instance of Thread>
        arg error = <instance of Error>
    Object:throw   0x10ddabf78
        arg this = <instance of Error>
    Function:protect   0x112338098
        arg this = <instance of Function>
        arg handler = <instance of Function>
        var result = <instance of Error>
    SynthDef:build   0x1117c6938
        arg this = <instance of SynthDef>
        arg ugenGraphFunc = <instance of Function>
        arg rates = nil
        arg prependArgs = nil
    Interpreter:interpretPrintCmdLine   0x112a94718
        arg this = <instance of Interpreter>
        var res = nil
        var func = <instance of Function>
        var code = "{ Out.ar(0, nil); }.asSynthDef"
        var doc = nil
        var ideClass = <instance of Meta_ScIDE>
    Process:interpretPrintCmdLine   0x10bff75a8
        arg this = <instance of Main>
^^ The preceding error dump is for ERROR: Out  input at index  1 ( nil ) is not audio rate

@telephon
Copy link
Member Author

... but note that this doesn't fail:

{ Out.kr(0, nil); }.asSynthDef

Independently of whether this is right or not, in the current design, it is up to the receiver to decide. The current PR's fix is intended to leave the decision to the receiver, which was previously blocked and not passed on. It is a trade off. Maybe the method should be written explicitly as:

Collection {
     rate { ^this.maxRate }
     maxRate {
        ... calculate max ...
     }
}

@timblechmann
Copy link
Contributor

if { Out.kr(0, nil); }.asSynthDef should be allowed, nil.rate should return scalar, no?

@telephon
Copy link
Member Author

I see what you mean.

As it currently is, scalar means something definite, the rate of a constant. nil means that the rate isn't specified. So I'd prefer if we keep nil.rate to be nil.

I think that { Out.kr(0, nil); }.asSynthDef shouldn't be allowed, but we should do that by implementing asUGenInput to throw an error for nil.

@telephon
Copy link
Member Author

Or, even better perhaps, implement checkValidInputs for Out.

Normally, this kind of error is caught in `checkValidInputs`. But as
the args are appended, and nil just appends itself as nothing, we never
see this as an input - it simply is missing. This commit explicitly
checks the input size.
@telephon
Copy link
Member Author

telephon commented Feb 3, 2016

Ok, this should be it.

@telephon
Copy link
Member Author

telephon commented Mar 4, 2016

ping

@crucialfelix crucialfelix added this to the 3.8 milestone Mar 6, 2016
@telephon
Copy link
Member Author

telephon commented May 18, 2016

OK, I try to give a summary here.

The proposed change in the current PR directly concerns the way the rate of an array of objects is calculated.

[SinOsc.ar, SinOsc.kr].rate return \audio (the maximum rate).

What should happen if there is an object that returns nil as a rate?

[SinOsc.ar, SinOsc.kr, nil].rate

This currently fails with a slightly obscure error message, which just points the reader to the implementation of ArrayedCollection and minItem.

The PR changes this by assuming that the above should return \audio, assuming nil to be just scalar. Then the error could be thrown further down, after multichannel expansion, and not in the rate calculation. A UGen may accept nil as an input.

@timblechmann argues that:

anything, which cannot be compared to scalar, control or audio should throw an exception.

Currently, everything can be compared to these, because the implementation (ab)uses the coincidence that \audio < \control and \control < \scalar.

  1. So this may be the place to change it.
  2. But, maybe also, because the rate calculation is only an intermediate step when passing ugens to each other, the resulting error may remain obscure.

@crucialfelix crucialfelix merged commit f86acb0 into supercollider:master Sep 6, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants