librelist archives

« back to archive

tick-once, a ugen ticking optimization

tick-once, a ugen ticking optimization

From:
Tom Lieber
Date:
2010-01-17 @ 22:15
To reduce overhead and boilerplate in the ugens' tick functions, I've
just committed code that makes some important changes:

1) each ugen's tick function is called exactly once per sample
2) rather than return the next sample, a ugen's tick should set self.last
3) speaking of which, ugen.last_value is now ugen.last
4) UGen.initialize_io is no longer required

So while I previously recommended writing a ugen like this:

  Noise = {
    new = function(class, gain)
      return UGen.initialize_io({
        gain = gain or 1.0,
        last_value = 0.0,
        tick = function(self)
          if not(now() == self.last_tick) then
            self.last_value = (math.random() * 2.0 - 1.0) * self.gain;
            self.last_tick = now();
          end
          return self.last_value
        end
      })
    end
  }

You can now slim that down to something like this:

  Noise = {
    new = function(class, gain)
      return {
        gain = gain or 1.0,
        tick = function(self)
          self.last = (math.random() * 2.0 - 1.0) * self.gain;
        end
      }
    end
  }

The changes to how ugens are ticked are not trivial, so please let me
know about any bugs I have introduced. :)

The way I ensure that ugens are ticked only once is by sorting the
ugen graph by longest path length from speaker & blackhole, and
caching the resulting queue until the next time a connection is made
or broken. All in all I see a ~20% speed improvement (using ex01.ckv
as a benchmark), which I expect to be greater on more complicated
graphs, and less on graphs that change frequently.

-- 
Tom Lieber
http://AllTom.com/
http://ckvlang.org/