BelaPlatform / supercollider

an environment and programming language for real time audio synthesis and algorithmic composition
GNU General Public License v3.0
14 stars 8 forks source link

Bela UGens do not interact nicely with `play` #61

Closed giuliomoro closed 3 years ago

giuliomoro commented 6 years ago

@apmcpherson had found an issue with one of the digital UGens I think, where having it last in a play statement would occasionally cause noisy outputs (probably because the output buffer was not being filled with zeros).

Now I have this:

s.waitForBoot{
    "Server Booted".postln;
    {
        var rate = AnalogIn.ar(0).exprange(0.3, 20);
        var amp = AnalogIn.ar(1); // returns a value from 0-1
        rate.poll(1);
        amp.poll(1);
        AnalogOut.ar(0, SinOsc.ar(rate).range(0.0, amp)); // send to Analog Output 0
    }.play;
}

and this floods the terminal output with

UGen(AnalogIn): 0.000106812

(they are about 50 per second: the trigger input to the Poll receives a trigger every 873 or 889 samples), while the lines from the LinExp (generated by rate.poll)

UGen(LinExp): 0.303403

seem to come in at about the right frequency.

Funny enough, if you comment out, e.g.: rate.poll(1);, thus leaving only the AnalogIn Poll UGen, this one only prints its output only once at the beginning (probably when the constructor calls Poll_next_kk).

Explicitly adding a UGen which produces a valid audio-rate output as the last command of the play block fixes everything, e.g.:

s.waitForBoot{
    "Server Booted".postln;
    {
        var rate = AnalogIn.ar(0).exprange(0.3, 20);
        var amp = AnalogIn.ar(1); // returns a value from 0-1
        rate.poll(1);
        amp.poll(1);
        AnalogOut.ar(0, SinOsc.ar(rate).range(0.0, amp)); // send to Analog Output 0
        Out.ar(0,
            SinOsc.ar(100, 0, 0.1 )
        )
    }.play;
}

@sensestage: is this expected behaviour with play or is there something wrong in the Bela UGens?

Should we just avoid play altogether and do something like this (which works fine) instead?

s.waitForBoot{
SynthDef("AnalogIn",{ arg out=0;
    var rate = AnalogIn.ar(0).exprange(0.3, 20);
    var amp = AnalogIn.ar(1); // returns a value from 0-1
    rate.poll(1);
    amp.poll(1);
    AnalogOut.ar(0, SinOsc.ar(rate).range(0.0, amp)); // send to Analog Output 0
}).send(s);
s.sync;
a = Synth.new("AnalogIn", target: s).postln;
}
sensestage commented 5 years ago

.play wraps the function in some additional UGens, that might be what creates the problem. Could possibly be that we need to remove writeOutputSpecs from the class definition of AnalogOut and DigitalOut and DigitalIO, but have to check.

giuliomoro commented 3 years ago

@sensestage

.play wraps the function in some additional UGens, that might be what creates the problem. Could possibly be that we need to remove writeOutputSpecs from the class definition of AnalogOut and DigitalOut and DigitalIO, but have to check.

do you have any further insight on this?

elgiano commented 3 years ago

I checked how other UGens with no output do it, and for example, SendTrig::ar (and kr) returns 0.0 instead of the output of multiNew. This prevents Function::play from creating an Out UGen (if AnalogOut is the last UGen of the block).

I've tested it and it fixes the issue :)

giuliomoro commented 3 years ago

Closed 313f28a