function 'designMultirateFIR' attenuates output signal for ratio of SampleRate​In/SampleR​ateOut > 4

2 views (last 30 days)
I wish to resample a signal from a given sample rate to 15.36MHz using a FIR as follows:
-----------------
| |
-----------------| FIR |---------------
^ | | ^
| ----------------- |
SampleRateIn SampleRateOut
= 15.36MHz
I have four potential values for SampleRateIn. When using the function 'designMultirateFIR' to calculate the FIR coeffiecients, I find that in some case (where ratios of SampleRateIn / SampleRateOut > 4) the amplitude of the output signal is attenuated.
Please explain why the amplitude of the output signal is attenuated, and what can be done to achieve unity gain through the FIR?
Below is a script that compares the results between functions 'resample' and 'designMultirateFIR'. In the latter case the output signal can be seen to be attenuated for ratios of SampleRateIn / SampleRateOut > 4.
%
% Script by Mark Walters to investigate behaviour of
% function 'designMultirateFIR' attenuating signal after FIR.
%
% This script compares the results between functions 'resample' and 'designMultirateFIR'
%
% Use case:
% For four given input sample rates, design a FIR to provide
% a fixed output sample rate of 15.36MHz.
%
% -----------------
% | |
% -----------------| FIR |---------------
% ^ | | ^
% | ----------------- |
% SampleRateIn SampleRateOut
% = 15.36MHz
%
% Problem:
% Using 'designMultirateFIR' with ratio of SampleRateIn/SampleRateOut > 4
% the output signal is attenuated.
%
%
%%
clearvars
close all
clc
% input signal freq (Hz)
SigFreq = 1e6;
% sample rate of signal into FIR
SampleRateIn = [2448000000/40, 2448000000/20, 2448000000/10, 2448000000/5];
% FIR settings to achieve output sample rate of 15.36MHz
FirInterpolation = [64, 32, 16, 8];
FirDecimation = [255, 255, 255, 255];
% sample rate of signal out of FIR
SampleRateOut = SampleRateIn .* FirInterpolation ./ FirDecimation;
Ratio = SampleRateIn ./ SampleRateOut;
figure(1)
clf
% iterate through the four given sample rates
for i = 1 : length(SampleRateIn)
% Create a sine wave
samplesPerFrame = FirDecimation(i)*i; % firrc() requires input vector length of multiple of decimation
sine = dsp.SineWave(1,SigFreq,'SampleRate',SampleRateIn(i),'SamplesPerFrame',samplesPerFrame);
x = sine();
% resample signal using 'resample'
y1 = resample(x,FirInterpolation(i),FirDecimation(i));
% resample signal using 'designMultirateFIR', uses dsp.FIRRateConverter
firrc = designMultirateFIR(FirInterpolation(i),FirDecimation(i),'SystemObject',true);
y2 = firrc(x);
% plot results
subplot(2,2,i)
tx = (0:length(x)-1)/sine.SampleRate;
FsIn = sine.SampleRate;
[delay,FsOut] = outputDelay(firrc,FsIn=FsIn);
ty1 = (0:length(y1)-1)/FsOut;
ty2 = (0:length(y2)-1)/FsOut-delay;
stem(tx,x,'filled',MarkerSize=4)
hold on
stem(ty1,y1)
stem(ty2,y2)
hold off
xlim([0.0 1e-6])
ylim([-1.1 1.1])
grid minor
legend('Original Signal','using resample','using designMultirateFIR')
str = sprintf("SRin=%.1fMHz FirInt=%d FirDec=%d SRout=%.2fMHz Ratio=%f", SampleRateIn(i)/1e6, FirInterpolation(i), FirDecimation(i), SampleRateOut(i)/1e6, Ratio(i));
title(str);
end

Accepted Answer

Harshit Saini
Harshit Saini on 23 Dec 2022
This behavior is due to the characteristics of the lowpass FIR used in the FIR rate converter (antialiasing in this case), which is controlled by the polyphase half-length parameter, P of the “designMultirateFIR” function. The default value of P is 12, and it may be too small for the input signals you are working with.
This issue can be fixed with any of the three approaches mentioned below:
  • Approach 1: An easy way to fix this issue is to increase the value of P to a larger number, i.e., P = 64. This can be achieved by setting the third positional argument of the “designMultirateFIR” function to control the value of P.
>> P = 64; % default was 12
>> firrc = designMultirateFIR(FirInterpolation(i), FirDecimation(i), P, SystemObject=true);
You should expect a much better result after changing the value of P.
Refer to the documentation here,
  • Approach 2: You can set the transition width directly instead of the FIR length. The third positional argument is also used in this case, but the value should be a fraction between 0 and 1.
>> TW = 0.005;
>> firrc = designMultirateFIR(FirInterpolation(i), FirDecimation(i), TW, SystemObject=true);
Refer to the documentation here,
  • Approach 3: Another option is to use the “dsp.SampleRateConverter” object. This will allow a direct control of the bandwidth rather than transition width. This usually performs better than a “single-stage FIRRateConverter.”
>> firrc = dsp.SampleRateConverter(InputSampleRate = SampleRateIn(i), OutputSampleRate = SampleRateOut(i));
Refer to the documentation link for a detailed description of the “dsp.SampleRateConverter”.
  1 Comment
Mark Walters
Mark Walters on 10 Jan 2023
Hi Harshit
Thank you for the comprehensive response! I have tried all three approaches you suggested. While the dsp.SampleRateConverter is clearly the best option, it will consume far more FPGA resources than the designMultirateFIR with P=64, so I have opted for this approach.
Regards
Mark

Sign in to comment.

More Answers (0)

Products


Release

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!