atk-sc3
atk-sc3 copied to clipboard
HoaBLT-based ugens fail when angle is pi/2
I observed that HoaBLT
-based plugins fail with an error, if the distortion angle is exactly pi/2
or -pi/2
(constant value).
Examples:
// fail
x.free; x = {HoaZoom.ar(DC.ar(0 ! 4), pi/2, 0, 0, AtkHoa.refRadius, 1)}.play;
x.free; x = {HoaFocus.ar(DC.ar(0 ! 4), pi/2, 0, 0, AtkHoa.refRadius, 1)}.play;
x.free; x = {HoaBalance.ar(DC.ar(0 ! 4), pi/2, AtkHoa.refRadius, 1)}.play;
x.free; x = {HoaAsymmetry.ar(DC.ar(0 ! 4), pi/2, AtkHoa.refRadius, 1)}.play;
// negative extreme also fails
x.free; x = {HoaZoom.ar(DC.ar(0 ! 4), -pi/2, 0, 0, AtkHoa.refRadius, 1)}.play;
Error:
ERROR: binary operator '+' failed.
RECEIVER:
Float nan 00000000 7FF80000
ARGS:
Instance of BinaryOpUGen { (0x118abdbc8, gc=14, fmt=00, flg=00, set=04)
instance variables [9]
synthDef : instance of SynthDef (0x128da4fc8, size=16, set=4)
inputs : instance of Array (0x1181555d8, size=2, set=2)
rate : Symbol 'audio'
synthIndex : Integer 36
specialIndex : Integer 2
antecedents : nil
descendants : nil
widthFirstAntecedents : nil
operator : Symbol '*'
}
nil
PROTECTED CALL STACK:
Meta_MethodError:new 0x139027540
arg this = BinaryOpFailureError
arg what = nil
arg receiver = nan
Meta_DoesNotUnderstandError:new 0x139029800
arg this = BinaryOpFailureError
arg receiver = nan
arg selector = +
arg args = [ a BinaryOpUGen, nil ]
Object:performBinaryOpOnSomething 0x138479dc0
arg this = nan
arg aSelector = +
arg thing = a BinaryOpUGen
arg adverb = nil
a FunctionDef 0x13a5d8040
sourceCode = "<an open Function>"
arg i = 0
Integer:do 0x13a2fba40
arg this = 4
arg function = a Function
var i = 0
SequenceableCollection:performBinaryOpOnSeqColl 0x13a5d7b80
arg this = [ nan, nan, nan, nan ]
arg aSelector = +
arg theOperand = [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ]
arg adverb = nil
var size = 4
var newList = [ ]
a FunctionDef 0x13a4aae00
sourceCode = "<an open Function>"
arg elem = [ nan, nan, nan, nan ]
ArrayedCollection:do 0x13a557c40
arg this = [ [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ nan, nan, nan, nan ] ]
arg function = a Function
var i = 1
Collection:sum 0x13a4aa5c0
arg this = [ [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ nan, nan, nan, nan ] ]
arg function = nil
var sum = [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ]
a FunctionDef 0x13a4978c0
sourceCode = "<an open Function>"
arg elem = [ [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ nan, nan, nan, nan ] ]
arg i = 1
ArrayedCollection:do 0x13a557c40
arg this = [ [ [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ a BinaryOpUGen, 0.0, a BinaryOpUGen, -0.0 ], [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ] ], [ [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ nan, nan, nan, nan ] ] ]
arg function = a Function
var i = 1
Collection:collectAs 0x13a497500
arg this = [ [ [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ a BinaryOpUGen, 0.0, a BinaryOpUGen, -0.0 ], [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ] ], [ [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ nan, nan, nan, nan ] ] ]
arg function = a Function
arg class = Array
var res = [ [ a Sum4, 0.0, a Sum4, 0.0 ] ]
Meta_Mix:new 0x138adc740
arg this = Mix
arg array = [ [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ a BinaryOpUGen, 0.0, a BinaryOpUGen, -0.0 ], [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ nan, nan, nan, nan ] ]
var reducedArray = [ [ [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ a BinaryOpUGen, 0.0, a BinaryOpUGen, -0.0 ], [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ] ], [ [ a BinaryOpUGen, 0.0, a BinaryOpUGen, 0.0 ], [ nan, nan, nan, nan ] ] ]
var mixedArray = nil
Meta_HoaBLT:bltLook 0x139e8f200
arg this = HoaBLT
arg in = [ an OutputProxy, an OutputProxy, an OutputProxy, an OutputProxy ]
arg alpha = 1.0
arg theta = 0
arg phi = 0
arg weightFunc = a Function
arg radius = 1.5
arg n = 1
var toPhi = -1.5707963267949
SynthDef:buildUgenGraph 0x13b068e00
arg this = a SynthDef
arg func = a Function
arg rates = nil
arg prependArgs = [ ]
var result = nil
var saveControlNames = [ ControlName P 0 i_out scalar 0 ]
a FunctionDef 0x13a180700
sourceCode = "<an open Function>"
arg i_out = an OutputProxy
var result = nil
var rate = nil
var env = nil
SynthDef:buildUgenGraph 0x13b068e00
arg this = a SynthDef
arg func = a Function
arg rates = nil
arg prependArgs = [ ]
var result = nil
var saveControlNames = nil
a FunctionDef 0x13b067440
sourceCode = "<an open Function>"
Function:prTry 0x1394241c0
arg this = a Function
var result = nil
var thread = a Thread
var next = nil
var wasInProtectedFunc = false
CALL STACK:
DoesNotUnderstandError:reportError
arg this = <instance of BinaryOpFailureError>
Nil:handleError
arg this = nil
arg error = <instance of BinaryOpFailureError>
Thread:handleError
arg this = <instance of Thread>
arg error = <instance of BinaryOpFailureError>
Object:throw
arg this = <instance of BinaryOpFailureError>
Function:protect
arg this = <instance of Function>
arg handler = <instance of Function>
var result = <instance of BinaryOpFailureError>
SynthDef:build
arg this = <instance of SynthDef>
arg ugenGraphFunc = <instance of Function>
arg rates = nil
arg prependArgs = nil
Function:play
arg this = <instance of Function>
arg target = <instance of Group>
arg outbus = 0
arg fadeTime = 0.02
arg addAction = 'addToHead'
arg args = nil
var def = nil
var synth = nil
var server = <instance of Server>
var bytes = nil
var synthMsg = nil
< closed FunctionDef > (no arguments or variables)
Interpreter:interpretPrintCmdLine
arg this = <instance of Interpreter>
var res = nil
var func = <instance of Function>
var code = "x = {HoaZoom.ar(DC.ar(0 ! 4)..."
var doc = nil
var ideClass = <instance of Meta_ScIDE>
Process:interpretPrintCmdLine
arg this = <instance of Main>
^^ ERROR: binary operator '+' failed.
RECEIVER: nan
However, exceeding the range seems okay (i.e. there's no error):
x.free; x = {HoaZoom.ar(DC.ar(0 ! 4), pi, 0, 0, AtkHoa.refRadius, 1)}.play;
Using control signal (as opposed to a constant) with the same value seems to work fine as well...
x.free; x = {HoaZoom.ar(DC.ar(0 ! 4), DC.kr(pi/2), 0, 0, AtkHoa.refRadius, 1)}.play;
I had a quick look and, given these angle.sin
is 1
in these cases, and given the nan
s in the error dump, I suspect this needs protection from divide-by-zero?
https://github.com/ambisonictoolkit/atk-sc3/blob/346dfe8dc4e8d7a33d4af22198c50d0f1e899871/Classes/HoaUGen.sc#L229-L231
This quick and dirty "fix" seems to ... not break at least
warpFunc = { |mu, alpha|
var denom = (1 + (alpha * mu));
if(denom.rate == \scalar) {
if(denom == 0) {denom = 0.0000001};
};
(mu + alpha) / denom;
};
I haven't reasoned through the actual function or expected output, but given there aren't any other variables I'd imagine in this condition we might just know the exact value this function should return in the case the denom==0
, and the division would just be altogether avoided.
Care should be taken in the case of running signals that these low denominator values divide nicely. ATM they may just be surviving because many UGens zapgremlins
.
It would be good to check against the BLT implementations in HoaMatrixXformer
, i.e., HoaMatrixXformer:-newDominate
When we're at ±pi/2
the result should collapse nicely into a cardioid.