Hi everyone!
I’m teaching supercollider to a room full of eager college students this semester. I was going over some NodeProxy things and I found an error that only replicated on one computer. in other words, this code worked fine on most computers, mine included, but one student had a catastrophic error.
s.waitForBoot({
~np = NodeProxy.audio(s, 2);
// Set some audio content before playing
~np.source = {nil};
~np.play;
});
Then I changed one line to this:
~np.source = nil;
and the error disappeared.
Is this an existential error for SC lang? Am I telling it to make the Node equal to a synthesis function of nothing, thus, it’s like a tree falling in the forest, with no one to hear it? “the sound of nothing” versus “Nothing”?
Genuinely curious if anyone encountered this, it would deepen my understanding.
the error looked like this:…
PROTECTED CALL STACK:
Meta_MethodError:new 0x120262080
arg this = BinaryOpFailureError
arg what = nil
arg receiver = nil
Meta_DoesNotUnderstandError:new 0x120264040
arg this = BinaryOpFailureError
arg receiver = nil
arg selector = <
arg args = [ 2, nil ]
Object:performBinaryOpOnSomething 0x1381a63c0
arg this = nil
arg aSelector = <
arg thing = 2
arg adverb = nil
a FunctionDef 0x130948d00
sourceCode = “”
var out = nil
var outCtl = nil
SynthDef:buildUgenGraph 0x130971100
arg this = a ProxySynthDef
arg func = a Function
arg rates = nil
arg prependArgs = [ ]
var result = nil
var saveControlNames = nil
a FunctionDef 0x13096f740
sourceCode = “”
Function:prTry 0x130757300
arg this = a Function
var result = nil
var thread = a Thread
var next = nil
var wasInProtectedFunc = false
To me, the essence of imperative programming boils down to three questions:
- What’s the information (or, the state of the system) that I have?
- What’s the information (or final state) that I want?
- What operations get from 1 to 2?
This goes down to the level of a line of code, or even a single method call – the purpose is to transform one state into another state.
So, after this line, the state of the system is that you have a NodeProxy with an empty signal, which I’ll presume to be silent. (It’s definitely silent for audio rate; I’d need to check kr at the computer later.)
~np = NodeProxy.audio(s, 2);
And based on the line ~np.source = {nil};
, I’m guessing that the desired state at the end of this is to have a NodeProxy with an empty signal.
That is, the expected state before ~np.source = {nil};
and the expected state after it are the same – hence, no need for the operation at all… where we run into a version of Occam’s Razor adapted to programming: unnecessary complexity frequently leads to bugs (and, eliminating unnecessary complexity reduces the chance for bugs).
When a proxy’s source is set to a function, AFAIK the function is expected to return a UGen or array of UGens. nil
isn’t that, so I’d expect at best undefined behavior. In this case, “it worked on most machines” really only means that an instruction that doesn’t quite meet the system’s expectation failed to produce an error on most of the machines… but I think that statement isn’t exactly valid.
Not on the computer now. I’ll try it later. EDIT: FWIW, I can’t reproduce the error dump on my machine. You might check whether that student has any extensions? Those could modify the main library’s behavior.
Btw the error seems to involve checking the “signal”'s channel count. Not sure yet how that’s relevant.
hjh