Hi, list,
I've finished analyzing the tabread4~ interpolation formula. It's a
real work of art, because it has a great low-pass characteristic, has
an efficient factorization, and has no phase shift.
I want to apply the tabread4~ scheme whenever the playback speed is
less than or equal to 1, and for higher speeds, use an time-dilated
verson of the original polynomial as the low-pass characteristic to
prevent aliasing.
The interpolation polynomial from tabread4~ , g(t) is a piecewise
continuous polynomial function, non-zero between -2 and 2. You can
view the tabread4~ impulse response with an attached patch,
view_tabread4~_impulse_response.pd and see for yourself what it looks
like
g(t)=
{ 1/6*(x+1)(x+2)(x+3) on [-2,-1)
-1/2*(x+2)(x+1)(x-1) on [-1,0)
1/2*(x-2)(x+1)(x-1) on [0,1)
and -1/6*(x-1)(x-2)(x-3) on [1,2]
This function has several ways to be written
g(t)=
{ 1/6*t^3 + t^2 + 11/6*t + 1
-1/2*t^3 - t^2 +1/2*t + 1
1/2*t^3 - t^2 -1/2*t + 1
-1/6*t^3 + t^2 - 11/6*t + 1
using the absolute value function |-1| = 1
and the indicator function I[a,b](t)={ 1 if a<t<b, 0 otherwise
example, I[-2,-2](t)=
1 if -2<t<2,
0 if t<-2 or t>2
g(t)=I[-2,2](t)(-1/6*|t|^3 - 2*t^2 - 11/6*|t| + 1) +
I[-1,1](t)(2/3*|t|^3 - 2*t^2 + 4/3*|t|)
This last factorization is especially compact, and allowed easier
computation of the fourier transform:
G(w)=integral( from t= -2 to 2, g(t)*e^(-iwt) )
G(w)=(1/w^2)*[1/3*cos(2w) - 4/3*cos(w) + 1] + (1/w^4)*[2*cos(2w)
- 8*cos(w) + 6]
where w is in radians per second
I checked that in the limit as w->0, G(w)->1, which is good
And the filter, G(w) has pretty good rejection characteristics, I'd
say. G(pi)= exactly 0.5, which is -3 dB. The stopband attenuation is
at most, 1/w^2 which would mean -6 dB per octave, I think.
An external can be made that will preserve these frequency
characteristics roughly during playback at higher speeds. This would
need to be implemented using convolution. The tabread4~ formula is an
efficient way to calculate c(t)
c(t) the continuous, interpolated function, as a function of input
signal s(t) (sampled at some frequency) and (1/k)*g(t/k) the
table-lookup interpolation formula, for a playback at speed k>1
s(t) is a sum of kronecker delta functions, multiplied by the sampled
function values
and (1/k)*g(t/k) is the function where g(t) is made longer by
factor of k and is reduced in amplitude by factor k
c(t)=s(t) convolved with (1/k)*g(t/k)
Then, we can evaluate c(t) at each of the points at the input of tabread
I would recommend that it be coded using circular convolution, making
a finite sum at each point. Since we only need to evaluate c(t) at the
points specified as input
g(t/k) is zero if outside of -2*k < t < 2*k, so we would have to
evaluate g(t) at no more than (4*k + 1) points, per sample on the
whole block
I think, it's possible to make an anti-aliasing table read. Would it
take better stopband attenuation than -6db/octave to be a good
anti-aliasing filter?
Chuck