Page 2 of 3

Re: De-zipper code?

Posted: Sun Aug 06, 2017 10:39 am
by Perfect Human Interface
tulamide wrote:But I'm not sure, what you are really heading for?


Just to recreate the dezipper outside of Flowstone. The rest of the conversation is just some oddities I found while testing.

If I'm not mistaken what you described is the same as what my partner wrote: "old + (new - old) * coef." If you're correct then maybe the error is elsewhere.

However, would this really be linear if it's recalculated every sample? Should there not be a check to see if current sample is changed from previous sample?

Re: De-zipper code?

Posted: Sun Aug 06, 2017 12:01 pm
by tulamide
Perfect Human Interface wrote:However, would this really be linear if it's recalculated every sample? Should there not be a check to see if current sample is changed from previous sample?

That's why I asked what you're heading for, because while it is strictly linear per moment, you won't see a straight line of change over a longer period.

when a and b change per sample:
-1|0|1|-1 with t mapped to 4 samples, will result in -1, 0.5, -1
-1|-1|-1|-1 with t mapped to 4 samples, will result in -1, -1, -1

when a never changes during transition:
-1|0|1|-1 with t mapped to 4 samples, will result in -1, 0, -1
-1|-1|-1|-1 with t mapped to 4 samples, will result in -1, -1, -1

You see that the first example goes to more extremes in between. Both will result in straight lines, but the first one will seem more hectic. So, if you go with the first one, but don't want "sharp angles", you could go with qarp, which is quadratic interpolation. Easier said, qarp is the linear interpolation of two linear interpolations, and therefore requires 3 samples and t.

Code: Select all

lerp(lerp(a, b, t), lerp(b, c, t), t)
or
(a + t * (b - a)) + t * ((b + t * (c - b)) - (a + t * (b - a)))
Note: requires at least one intermediate step to avoid calculating a + t * (b - a) two times


Another more curvy (read: smoother) approach would be cosine interpolation:

Code: Select all

(a + b + (a - b) * cos(t * 180°)) / 2


Other interpolations are too demanding.

Re: De-zipper code?

Posted: Sun Aug 06, 2017 1:43 pm
by TheOm
This would basically be the corresponding C++ code.

Code: Select all

struct DezipState {
    float output;
    float lastTarget;
    float startValue;
    float coef;
};

float dezip(DezipState& state, float target, float rate) {
    if (target != state.lastTarget) {
        state.lastTarget = target
        state.coef = 0
        state.startValue = state.output
    }
    state.coef = min(state.coef + rate, 1.0f)
    state.output = state.startValue + state.coef * (target - state.startValue)
    return state.output;
}


Perfect Human Interface wrote:By the way, I discovered something interesting! With the dezipper, when the input value changes, it's smoothed to that new value linearly, but if the input is changing continuously, it appears to smooth logarithmically. I can only guess that the input changing continuously causes the algorithm to update at each step which manifests as a curve.


Yes that is exactly what's happening. If the target is changing continuously it basically degrades into a 1-pole lowpass.

Perfect Human Interface wrote:By the way, the Assembler dezipper that TheOm provided above doesn't seem to work at all with the input changing continuously.

The problem was that I updated the coef value after computing the new output.
Try this:

Re: De-zipper code?

Posted: Sun Aug 06, 2017 5:36 pm
by martinvicanek
I think it is easier than that. The updating takes place at hop(128). An increment is calculated such that the (current) target will be reached after an integer number of hops. The code is so lightweight you don't even have to asm it.

Re: De-zipper code?

Posted: Sun Aug 06, 2017 6:02 pm
by Perfect Human Interface
That's a neat smoother Martin, although it creates a logarithmic curve, and linear is what we're looking for.
(PS glad to see you're still around. Hopefully I will be contacting you within the next few months.)

Many thanks TheOm and everyone else in this thread. I think we'll be able to figure it out now. And I learned some stuff to boot. :D

Re: De-zipper code?

Posted: Sun Aug 06, 2017 7:14 pm
by Spogg
Yay!! We're all making stream de-zippers!

Here's my offering. I'm using this in my current project to limit slew rate to be like the old 741 op-amp (0.5V/uS for a 10 volt p-p swing in open loop).

Cheers

Spogg

Re: De-zipper code?

Posted: Sun Aug 06, 2017 7:57 pm
by martinvicanek
Perfect Human Interface wrote:it creates a logarithmic curve, and linear is what we're looking for.

:?: :o :!: The output consists of linear segments.

Re: De-zipper code?

Posted: Sun Aug 06, 2017 9:17 pm
by tulamide
martinvicanek wrote:
Perfect Human Interface wrote:it creates a logarithmic curve, and linear is what we're looking for.

:?: :o :!: The output consists of linear segments.

See, Martin? That's what was confusing me as well!

tulamide wrote:That's why I asked what you're heading for, because while it is strictly linear per moment, you won't see a straight line of change over a longer period.

Re: De-zipper code?

Posted: Mon Aug 07, 2017 6:43 am
by Perfect Human Interface
See the difference here.
I think Spogg's might be too subtle to visualize.

Re: De-zipper code?

Posted: Mon Aug 07, 2017 7:14 am
by adamszabo
To make Martins version linear, you have to have the multiplier coefficient be the hop numbers ratio. So you have to divide 1 by the hop number. Martins 128 it too small, but if you increase it to 2048, or even 4096, you will see a difference and it will be linear.

Code: Select all

streamin in;
streamout out;

float step = 0;

hop(2048) {
       // 1/2048 = 0.00048828125
   step = (in - out) * 0.00048828125;
}

out = out + step;