Updating SR % 8, how to get it smoother?
- KVRian
- Topic Starter
- 1091 posts since 8 Feb, 2012 from South - Africa
Usually I update LFO's & envelopes at samplerate, but polyphony is killing me at the moment. So I've decided (by recommendation here) to update my LFOs at samplerate % 8 and envelopes samplerate % 4. The clock bleed is pretty bad, so I'm wondering what would be a cheap way to smooth it out, without spoiling all the CPU I gained?
Andrew
Andrew
- KVRAF
- 7868 posts since 12 Feb, 2006 from Helsinki, Finland
Linear interpolation is probably the cheapest approach and works quite well (in my opinion much better than any simple one-pole smoothers that cost more as well).Ichad.c wrote:Usually I update LFO's & envelopes at samplerate, but polyphony is killing me at the moment. So I've decided (by recommendation here) to update my LFOs at samplerate % 8 and envelopes samplerate % 4. The clock bleed is pretty bad, so I'm wondering what would be a cheap way to smooth it out, without spoiling all the CPU I gained?
- KVRian
- Topic Starter
- 1091 posts since 8 Feb, 2012 from South - Africa
Yeah, was thinking of something similiar. Implementation wise, I assume I need to safe the previous value -> then have a "master" phase-accumulator running at SR % 8, that basically just fades between old and new value?
Just to note, both my LFOs and ENVs use phase-accumulators so the next value is unknown.
Just to note, both my LFOs and ENVs use phase-accumulators so the next value is unknown.
- KVRAF
- 7868 posts since 12 Feb, 2006 from Helsinki, Finland
Well, you run your LFOs and envelopes at the reduced control rate, then keep the old and new values. You can do the interpolation with single multiply add as old+t*delta where delta=new-old and t=[0,1] for the interpolation period, not counting the time to come up with the t coeff. You could also use old+=delta accumulators and delta=(new-old)*(1.0/ratediv) to do away with the parameter, at a cost of a memory write.Ichad.c wrote:Yeah, was thinking of something similiar. Implementation wise, I assume I need to safe the previous value -> then have a "master" phase-accumulator running at SR % 8, that basically just fades between old and new value?
Just to note, both my LFOs and ENVs use phase-accumulators so the next value is unknown.
In either case, it's pretty cheap and even if you had an LFO or envelope that was roughtly similar anyway, you still save tests and branches for reset logic and such.
- KVRian
- Topic Starter
- 1091 posts since 8 Feb, 2012 from South - Africa
Thats plenty food for thought, the last idea(memory write) sounds interisting, will definety need to bench these!
Thanks!
Thanks!
- KVRAF
- 7868 posts since 12 Feb, 2006 from Helsinki, Finland
The accumulator is likely to be faster where you have an extra register to cache the values (eg simple gain control) while in other situations it depends..Ichad.c wrote:Thats plenty food for thought, the last idea(memory write) sounds interisting, will definety need to bench these!
- KVRian
- Topic Starter
- 1091 posts since 8 Feb, 2012 from South - Africa
For SR % 8, should...
not be?
Version2 is smoother albeit my implementation seems to accumulate some DC offset when phase is updated - but I have the suspicion that it has to do with the block-based implementation of SE, need to get to the bottom of this. Version1 does not have this issue though. Initial CPU tests show a CPU saving of ~60% - which is great.
Andrew
Code: Select all
//Version1
delta = (new - old) * (1/8);
old +=delta;
Code: Select all
//Version2
delta = (new - old) * (1/8);
accumulator+= delta;
Andrew
- KVRAF
- 7868 posts since 12 Feb, 2006 from Helsinki, Finland
You must either reset the accumulator to the old value as you update delta every 8 samples, or you must calculate the delta against the accumulated value. Otherwise you build up some rounding errors over time.Ichad.c wrote: Version2 is smoother albeit my implementation seems to accumulate some DC offset when phase is updated
That's why I just suggested using the "old" variable directly; you still accumulate a bit of error (over the 8 samples) but then when the delta value is updated, it's calculated from the "wrong" position to the new target, so the error doesn't grow unbounded.
Also just to make sure, you are only supposed to calculate a new delta at control rate.
- KVRian
- Topic Starter
- 1091 posts since 8 Feb, 2012 from South - Africa
That was it. Your version(1) is cheaper. Don't think the error is much of a problem with LFOs, will check how it behaves with envelopes.mystran wrote: Also just to make sure, you are only supposed to calculate a new delta at control rate.
Thanks again!
- KVRAF
- 7868 posts since 12 Feb, 2006 from Helsinki, Finland
The error over 8 samples is typically very small (few least significant digits at best). It only ever becomes meaningful if you allow it to accumulate over longer periods of time and that doesn't happen if you use the accumulated value (that contains the error) to calculate a new delta as the negative feedback will result in the errors staying bounded (and in practice very small).Ichad.c wrote:That was it. Your version(1) is cheaper. Don't think the error is much of a problem with LFOs, will check how it behaves with envelopes.mystran wrote: Also just to make sure, you are only supposed to calculate a new delta at control rate.