monome / norns

norns is many sound instruments.
http://monome.org
GNU General Public License v3.0
630 stars 145 forks source link

Performance quirk using sin() in supercollider #440

Closed markwheeler closed 6 years ago

markwheeler commented 6 years ago

Ran into this oddness while working on an additive synthdef. Not quite sure what to make of it... Here's some demo code (warning, horrible sounds!):

Engine_PerfTest : CroneEngine {
    var <synthVoice;
    *new { arg context, doneCallback;
        ^super.new( context, doneCallback );
    }
    alloc {
        synthVoice = {
            arg out;
            var signal, phase, mult = 5;

            phase = LFSaw.ar( freq: 100, iphase: 1, mul: pi, add: pi );
            signal = Mix.fill( 35, {
                sin(phase * mult) / 50;
            });
            Out.ar( bus: out, channelsArray: signal );
        }.play( args: [\out, context.out_b], target:context.xg );
    }
    free {
        synthVoice.free;
    }
}

This engine works fine for me and shows around 25% CPU usage according to top with no system FX running. However, change the mult var to 50 and the CPU usage now jumps to 90%.

It seems there is a number which if sin() is passed a value greater than, performance drops drastically. I'm unable to reproduce anything similar on desktop so assuming this is some quirk of norns software or hardware?

antonhornquist commented 6 years ago

I haven't tried your code out but you might wanna try wrapping the phase, ie. see NOTE on phase argument in http://doc.sccode.org/Classes/SinOsc.html .

Also I mostly use SinOsc.ar rather than sin() in my SynthDefs, I don't know if that matters.

markwheeler commented 6 years ago

Aha good shout, it hadn't occurred to me that I'd need to wrap values there but that solves it!

As an aside, I'm using sin() rather than SinOsc here as phase drifts between SinOscs unfortunately.

antonhornquist commented 6 years ago

arguably wrapping should not be needed but glad if it solved the problem :)