[PD] tabread4~ interpolation formula (was: a little pitchshifter)

Charles Henry czhenry at gmail.com
Sat Mar 17 07:11:10 CET 2007


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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: view_tabread4~_impulse_response.pd
Type: application/octet-stream
Size: 1181 bytes
Desc: not available
URL: <http://lists.puredata.info/pipermail/pd-list/attachments/20070317/67e14e42/attachment.obj>


More information about the Pd-list mailing list