[PD] better tabread4~
Matt Barber
brbrofsvl at gmail.com
Sat Jun 28 08:23:05 CEST 2008
> Date: Fri, 27 Jun 2008 00:39:18 -0500
> From: "Charles Henry" <czhenry at gmail.com>
> Subject: Re: [PD] better tabread4~
> To: "Mathieu Bouchard" <matju at artengine.ca>, pd-list at iem.at
> Message-ID:
> <518fe7b20806262239y377186afka8b0f348ecca80d1 at mail.gmail.com>
> Content-Type: text/plain; charset=ISO-8859-1
>
> On Thu, Jun 26, 2008 at 11:18 AM, Mathieu Bouchard <matju at artengine.ca> wrote:
>> I fucked up here. To get a C2 curve you may need to solve an equation system
>> covering the whole table (!). Anyhow, a C1 system is fine enough for most
>> uses, and it would be already much better than pd's.
>>
>> The thing is that you can only match the 2nd derivatives if you let the 1st
>> derivatives just match but freely float. Then there will be one curve going
>> through all points of the whole table supposing that the 2nd derivative is
>> zero at the beginning and end of the table. Clearly this is a wholly
>> different game because you need to compute a 2nd table to remember what the
>> 1st derivatives are supposed to be and then you can't change anything in the
>> 1st table without recomputing the 2nd table from scratch, or something.
>
> I get what you're saying now. I had to read it a couple times through
> to see :) You're referring to piecewise cubic polynomials, right? We
> would wind up with an overdetermined system of equations if we didn't
> float the 1st *and* 2nd derivatives, which would come out as a linear
> algebra problem of the size of the table.
>
> but I think it gets even worse. There could be a non-zero null space
> to the problem. There are infinite solutions to interpolate a table
> full of zeros, with these conditions. What a mess :)
>
It's also bad because while a natural cubic spline is conceivable for
a tabread (fixing the 2nd derivative to zero on both ends, reading in
and keeping all the derived data in a buffer somewhere), you might
need a different kind of spline (periodic?) for a tabosc~, and it
shouldn't work at all for a vd~ since there is no codified beginning
or end to the table (yes-no?).
>>> or we could set x[0],x[1] and x'[0]=(x[1]-x[-1])/2 and x'[1]=(x[2]-x[0])/2
>>> again, 4 constraints, cubic polynomial, etc...
>>
>> Seems reasonable. What I want has to have constraints on x'[0] and x'[1].
>> Those would be a possibility. The problem is that it uses a gap of 2 samples
>> instead of one, so it uses a "blurry" derivative, but the alternative is to
>> have to pick between forward-difference and backwards-difference. The
>> "blurry" derivative happens to be the average of the 1-sample
>> forward-difference and backward-difference.
Which is equivalent to the slope between the 2-sample gap. This would
have another advantage over forward- or backward-differences such that
going through the table in reverse would produce a symmetric result.
(or actually, would it matter after all, since the four points are in
the same order whether you're going forward or backward through the
table... ?)
>>> and x''[0]=x[1]-2*x[0]+x[-1] and x''[1]=x[2]-2*x[1]+x[0]
>>> 6 constraints, 5th degree polynomial
>>
>> I think that the replacement for tabread4~ should be another cubic, so that
>> it takes almost the same time to compute it. What I said about C2 was based
>> on a mistaken reading of webpages trying to refresh myself on splines. I
>> should've been more careful.
>
> Yeah, a cubic polynomial makes the most sense for small changes. I
> haven't ever heard of people interpolating 4 points with a 5th degree
> polynomial.... but I think I could make it work....
>
The following bit of code might work to that end as a test, borrowing
Cyrille's general notation:
cminusb = c-b;
aminusd = a-d;
a0 = aminusd + 3.0 * cminusb;
a1 = -2.5f * aminusd - 7.5f * cminusb;
a2 = 1.5f * aminusd + 4.5f * cminusb;
a3 = 0.5f * (c + a) - b;
a4 = 0.5f * (c - a);
a5 = b;
*out++ = ((((a0*frac+a1)*frac+a2)*frac+a3)*frac+a4)*frac+a5;
The variables would have to be declared further up, obviously. Also,
the compiler should optimize the a5 definition out and just use b
(right?), so the above might be clearer and more explicit from a
formal standpoint. I'm very prone to algebraic mistakes (especially
on friday nights), so if someone else is interested you can check my
work and see if you arrive at the same result (x''[n] = x[n-1] -2*x[n]
+ x[n+1] , x'[n] = 0.5*(x[n+1] - x[n-1]) for both x[0] and x[1] )
-- the result may be able to be further optimized as well due to some
redundancies in the coefficients. Following the naming scheme of the
other tests, this might be [tabread4fi~] or some such (fi for
"fifth"-order-polynomial).
As this line of experimentation proceeds, it might make sense to
develop a set of benchmarks both for quality and performance. One
place to start might be to test the residual error between all of the
new and old [tabosc~] objects running through a cosine table and an
[osc~] with the same frequency and phase, trying out different
respective table sizes, and then further test with various cosinesum
combinations.
Of course the "ear" test will probably determine things more,
especially with sampled data, but it's still a little unclear to me
exactly what these interpolations are "supposed" to do when the
waveform has transients and discontinuities among the samples -- e.g.
what bandwidth should result from moving through a table that's filled
with white noise, or what should happen when moving slowly through a
table that's filled with alternating 1 -1, or what should a snare-drum
or bongo hit sound like at a fifth the speed? These seem to me to be
more a matter of taste and interpretation than the cosine tests.
Thanks,
Matt
More information about the Pd-list
mailing list