[Lowfer] Re: SDRadio Version 0.93 available

Alberto di Bene [email protected]
Mon, 12 Jan 2004 14:53:53 +0100


Hello Johan,

  I had replied to your question about the fractional delay, but my reply
didn't show on the reflector, probably beacuse it was in HTML format,
as it had an embedded picture.

I am resending it, taking away the picture and changing the format to
plain text.

-------- Original Message --------

"Johan Bodin" <[email protected]> wrote:

> How you solved the problem of "sub-sampling-interval-delay-correction"
> remains a mystery to me... Interpolating up to huge FS, do the delay and
> decimate back to the original FS would take too much CPU power.
> May I curiously ask, how did you do it?


The multirate technique is one of the possibilities, but, as you said, 
if you want to have a
fine granularity of the fractional delay, it involves interpolating to a 
very high sampling freq.,
with all the undesired effects that you mention.
Stewart Nelson in a private mail suggested me to search with Google for 
the words
"fractional delay" and this gave quite a lot of results, almost all not 
so easily palatable.
I did some search on the subject, including letting some kind soul 
sending me a couple of
IEEE papers meant for IEEE members only (which I am not, I plead Guilty, 
Your Honor...) ,
and what came out is summarized below.

<warning, long, technical and boring stuff --- skip if not 
interested--------------->

In an uniformly sampled signal, you have samples only at precise 
instants in time. The
values of the sampled signal are undefined between samples, so you have 
to resort
to a so-called band-limited interpolation to approximate them.
In one of those papers it is shown that this can be implemented with a 
discrete-time,
linear-phase allpass filter, whose (ideal) coefficients are computed via 
an inverse FFT as:

   hid(n) = sin(pi * (n - D)) / (pi * (n - D))   (the common sinc function)

When D (the delay) has an integer value, the impulse response reduces to 
a single
impulse at n = D, but for noninteger values of D, the impulse response 
is an infinitely long,
shifted and sampled version of the sinc function. The two cases are 
shown in this picture:

[---- embedded picture removed ----]

So the problem is now to approximate somehow those hid coefficients with 
a causal,
real-valued, realizable filter. There are some techniques described in 
the literature,
I won't go through them, as probably you are not interested. Suffice to 
say that initially
I implemented a Thiran IIR maximally-flat allpass filter. Some 
simulations done with Matlab
gave as 127 the order of the filter to have the error on the delay 
almost zero up to more
than 95% of Nyquist. Unfortunately, while on paper the Thiran filter is 
unconditionally
stable,  a recursive filter with such an high order requires a very high 
computational
precision, much greater than those offered by C-language doubles. The 
result was that
the filter became unstable with N > 16, let alone 127....
Then I briefly examined the Lagrange interpolator, very simple to 
implement, but the
flatness of the delay leaves something to be desired...
Finally I settled for for the LS (Least Squared) windowed approach, 
where the ideal
coefficients hid are truncated, the overall delay D is placed in the 
"center of gravity"
of the ideal impulse response, and a suitable window is applied to 
minimize the Gibbs
phenomenon caused by truncation. I chose a Kaiser window with a beta 
value of 6,
even if Laakso reports that the Dolph-Chebyshev window is optimal. My 
choice was
dictated by the greater computational effort for such a window. Don't 
forget that when
the user moves one of the two phase-delay sliders, all the filter 
coefficients must be
recomputed on-the-fly, the filter itself must be reinitialized, all in 
almost real time...

So, to sum up, the fractional delay is implemented by delaying the left 
channel by a
fixed amount of integer sampling periods, which can be 62, 63 or 64 
depending on the
fractional delay needed on the right channel. The right channel itself 
is delayed by
an amount of 63 + d samples, where d can range from -0.5 to +0.5. The 
left channel
delay is simply implemented via a circular buffer, while the right 
channel delay uses
a FIR filter, order 127,  whose coefficients are computed as described above

</warning>

Sorry Johan for the length of the above explanations, but, after all, 
you asked for it !

73  Alberto  I2PHD