# Fraction Delays using Linear Interpolation and Resampling

01 Nov 2014### Introduction

In this article we look at implementing fractional delays using Linear Interpolation and Resampling Techniques

A integral delay of $M$ is obtained by a delay line of length $M$.A factional delay is implemented cascading the integral part of delay with a block which can approximate a constant phase delay equal to fractional part of $m$

Fractional delay filters receive a sequential stream of input samples and produce a corresponding sequential stream of interpolated output values.

The most intuitive way of obtaining fractional delay is interpolation .

For an ideal fractional-delay filter, the frequency response should be equal to that of an ideal delay

$\displaystyle H^\ast(e^{j\omega}) = e^{-j\omega\Delta}$

where $ \Delta = N+ \eta$ denotes the total desired delay of the filter Thus, the ideal desired frequency response is a linear phase term corresponding to a delay of $ \Delta$ samples.

### Linear Interpolation

Linear interpolation works by effectively drawing a straight line between two neighboring samples and returning the appropriate point along that line.

More specifically, let $ \eta$ be a number between 0 and 1 which represents how far we want to interpolate a signal $ y$ between time $ n$ and time $ n+1$ . Then we can define the linearly interpolated value $ \hat y(n+\eta)$ as follows:

$\displaystyle \hat y(n+\eta) = (1-\eta) \cdot y(n) + \eta \cdot y(n+1) $

$\displaystyle \hat y(n+\eta) = y(n) + \eta\cdot\left[y(n+1) - y(n)\right].$

Thus, the computational complexity of linear interpolation is one multiply and two additions per sample of output.

In case of delay filter $\eta$ is the fractional part of the delay.Thus we pass the sequence throught a filter

for example for a delay of 1/4 $\displaystyle {\hat y}\left(n-\frac{1}{4}\right) \;=\;\frac{3}{4} \cdot y(n) + \frac{1}{4}\cdot y(n-1) $

The python code for implementing fractional delay by interpolation can be found below

def convolution(signal,h): """ function that performs linear convolution """ output=scipy.convolve(signal,h,"same") return output def fdelay(signal,N): """ function introduces a fractional delay of N samples Parameters ----------- signal : numpy-array, The input signal N : factional delay Returns -------- out : numpy-array delayed signal """ f,i=math.modf(N) #perform integral delay signal=delay(signal,i) #perform linear interpolation for fractional delay output=convolution(signal,[f,i-f]) return output def delay(signal,N): """ function introduces a circular delay of N samples Parameters ----------- signal : numpy-array, The input signal N : integer delay Returns -------- out : numpy-array delayed signal """ if N==0: return signal; if N >= len(signal): N=N-len(signal) if N <0: N=N+len(signal) d=signal[len(signal)-N:len(signal)];#numpy.zeros((1,N+1)); signal1=numpy.append(d,signal[0:len(signal)-N]) return signal1;

### Upsampling Technique

Let us assume we can express the fractional delay as rational number $\frac{M}{N}$

The steps to introduce fractional delay are

- upsample the sequence by a factor $N$ which simple inserts N zeros between adjacent samples.
- interpolate the zero values using low pass filter
- Delay the signal by $M$ samples
- downsample by a factor $N$

def fdelay(signal,N,mode="upsample"): """ function introduces a fractional delay of N samples Parameters ----------- signal : numpy-array, The input signal N : factional delay mode : "linear " - linear interpolation "upsample " - upsampling technique Returns -------- out : numpy-array delayed signal """ if mode=="linear": f,i=math.modf(N) #perform integral delay signal=delay(signal,i) #perform linear interpolation for fractional delay output=convolution(signal,[f,i-f]) if mode=="upsample": N=math.ceil(N*100)/100 #get rational approximation result=fractions.Fraction(N).limit_denominator(20) num=result.numerator; den=result.denominator #upsample the signal and interpolate out1=scipy.signal.resample(signal,den*len(signal)) #delay the signal out1=delay(out1,int(num)) #downsample the signal out1=scipy.signal.resample(out1,len(signal)) output=out1 return output

The Rational number has been chosse such that denominator is limited to 20 ,so that we are not upscaling by a large factor.

### Code

The code for the same can be found in the pyVision github repository in files

The function `fdelay`

implements fractional delay while function `delay`

implements integer delay.
The `mode`

parameter of `fdelay`

function specified which method to use to perform fractional delay operations.
presently it support `linear`

- Linear Interpolation and `upsample`

- Upsamling technique