# Downsampling and Convolution: When Can one Swap Between Them?

(Code snippet with example below).

In MATLAB, assume I have a long signal vector y (length N) that I wish to convolve with a square wave h (consisting of H 1's). This would give a convolution result of length N+H-1.

Since I have to perform this operation quite often, I thought that I could speed up my code by downsampling the signal y (and also the square wave h) and then perform the convolution. The downsampled signals are referred to as y_ds and h_ds.

However, the result is shifted when compared to the downsampled version of the convolution result (if corrected for scaling differences). So in general I found that:

conv(y_ds,h_ds) $\neq$ downsample(conv(y,h))

However, the shift is between the two results is not constant, i.e. shifting such that the maxima align, causes the edges to be different.

## My questions

• Where does this shift originate from?
• How can this code be modified such that the downsampled convolution result equals the convolution result of the downsampled signals?

Kind regards

N = 100;
dsfactor = 3;
H = dsfactor*3;
x = linspace(0,10,N);
y = sind(18*x);
h = ones(H,1);

convyh = conv(y,h);

convyh_ds = downsample(convyh,dsfactor)./H;
convyh_ds3 = conv(downsample(y,dsfactor),downsample(h,dsfactor))./(ceil(H/dsfactor));

figure;
plot(convyh_ds,'DisplayName','downsample(conv)','LineWidth',1);
hold on;
plot(convyh_ds3,'DisplayName','conv(downsample)','LineWidth',1);
grid minor
legend('show');
line([0 length(convyh_ds2)],[0 0],'LineStyle','--');


• Hi! First of all your h vector is purely $1$ s then convolution becomes a moving sum? What about the y vector? Will it always be partial sine waves? And also, do you have pre-determined fixed values for N, H and downsampling factors? Commented Sep 18, 2017 at 14:35
• @Fat32 Thanks for your response. The code snippet above is just an example, but in my application h is indeed purely 1's. The y vector can be anything, but using a sine was a straightforward example. Values for N, H and downsampling factors are not fixed either (yet) Commented Sep 18, 2017 at 14:39
• You down sample the signal so that convolution will be faster ? But it won't be equal to the original convolution ? You probably don't need an exact convolutin result? What's your purpose of convolution ? Commented Sep 18, 2017 at 15:04
• @Fat32 My question is why the convolution using the downsampled signals does not equal the original convolution (downsampled), Ideally, these results would be the same. So I do need the exact convolution result Commented Sep 18, 2017 at 15:44

I thought this was because you were getting aliasing in your signal during one of the downsampling operations. However, I re-wrote your code in R (included below) and I did not see the same effect I suspect conv is doing something odd. You may want to look at using the shape parameter and see if that makes a difference.

Below are four plots of different variants of yours:

• Top left: Yours.
• Top right: a variation that uses slightly different x values.
• Bottom left: Yours at twice the frequency.
• Bottom right: a variation that uses slightly different x values at twice the frequency.

As you can see, in all four examples the red and the black overlay exactly.

Yes, in general, these will not be the same. Below is an example with a sawtooth wave, and the two do not line up.

Here is the specific example you ask about with the triangle wave.

R Code Only Below

#43794
#N = 100;
N <- 100
#dsfactor = 3;
dsfactor <- 3
#H = dsfactor*3;
H <- dsfactor * 3
#x = linspace(0,10,N);
x1 <- seq(0,10,10/(N-1))
x2 <- seq(0,10*(N-1)/N,10/N)
#y = sind(18*x);
y1 <- sin(18*x1/180*pi)
y2 <- sin(18*x2/180*pi)
y3 <- sin(36*x1/180*pi)
y4 <- sin(36*x2/180*pi)
#h = ones(H,1);
h <- rep(1,H)

#convyh = conv(y,h);
convy1h <- filter(y1,h)
convy2h <- filter(y2,h)
convy3h <- filter(y3,h)
convy4h <- filter(y4,h)

downsample <- function(signal, factor)
{
return(signal[seq(1,length(signal), factor)])
}

#convyh_ds = downsample(convyh,dsfactor)./H;
convy1h_ds <- downsample(convy1h, dsfactor)/H
convy2h_ds <- downsample(convy2h, dsfactor)/H
convy3h_ds <- downsample(convy3h, dsfactor)/H
convy4h_ds <- downsample(convy4h, dsfactor)/H
#convyh_ds3 = conv(downsample(y,dsfactor),downsample(h,dsfactor))./(ceil(H/dsfactor));
convy1h_ds3 <- filter(downsample(y1,dsfactor), downsample(h,dsfactor))/ceiling(H/dsfactor)
convy2h_ds3 <- filter(downsample(y2,dsfactor), downsample(h,dsfactor))/ceiling(H/dsfactor)
convy3h_ds3 <- filter(downsample(y3,dsfactor), downsample(h,dsfactor))/ceiling(H/dsfactor)
convy4h_ds3 <- filter(downsample(y4,dsfactor), downsample(h,dsfactor))/ceiling(H/dsfactor)
#figure;
#plot(convyh_ds,'DisplayName','downsample(conv)','LineWidth',1);
#hold on;
#plot(convyh_ds3,'DisplayName','conv(downsample)','LineWidth',1);
#grid minor
#legend('show');
#line([0 length(convyh_ds2)],[0 0],'LineStyle','--');

par(mfrow=c(2,2))
plot(convy1h_ds)
lines(convy1h_ds3, col='red')

plot(convy2h_ds)
lines(convy2h_ds3, col='red')

plot(convy3h_ds)
lines(convy3h_ds3, col='red')

plot(convy4h_ds)
lines(convy4h_ds3, col='red')

• Thank you for your response. However, this confuses me even more because I think that in general the two results can't be the same. Consider the following example where y is a triangular wave (N=21), H=4 and dsfactor = 2: y = [1 2 3 4 5 6 7 8 9 10 11 10 9 8 7 6 5 4 3 2 1] h = [1 1 1 1] conv(y,h) = [1 3 6 10 14...14 10 6 3 1]] conv_ds = [1 6 14 22...34 26 18 10 3] y_ds = [1 3 5...5 3 1] h_ds =[1 1] conv(y_ds,h_ds) = [1 4 8 1 ...12 8 4 1] Both results start with 1, but there is still a non-constant scaling error and/or phase shift, right? Could you please run this example as well? Commented Sep 19, 2017 at 11:44
• @Knippie I ran an example using the sawtooth function from R. Let me try your data also.
– Peter K.
Commented Sep 19, 2017 at 11:49
• @Knippie OK, added that example.
– Peter K.
Commented Sep 19, 2017 at 11:55
• Thanks! So in this specific case the central part of the convolution is delayed by 0.27 sample (i.e. if we shift your right curve to the right by 0.27 sample, the black dots would perfectly align). What's the general conclusion we can draw from this? Commented Sep 19, 2017 at 12:08
• I would have thought the offset would be 0.25 samples.
– Peter K.
Commented Sep 19, 2017 at 12:38