Main Content

Multistage Rate Conversion using FIR Rate Converter

This example shows how to leverage multiple FIR Rate converters for sample rate conversion from 48 kHz to 44.1 kHz. In the multistage approach, we split the interpolation and decimation factors into simpler factors that reduce the combined filter order, reducing the computational complexity of the filtering process. The conversion of 48 kHz to 44.1 kHz can be performed in a single stage using interpolation factor L = 147 and decimation factor M = 160 or in multiple stages as described below:

  • Stage 1, L = 7 and M = 5 (48 kHz to 67.2 kHz)

  • Stage 2, L= 7 and M = 8 (67.2 kHz to 58.8 kHz)

  • Stage 3, L = 3 and M = 4 (58.8 kHz to 44.1 kHz)

Single-stage v.s. Multistage cost analysis

We can cascade the three rate conversion stages to form a single-stage equivalent filter, which functions in the same manner as a single-stage FIR Rate converter. However, the multistage approach is more efficient in terms of memory because the cascaded rate converters use less memory (states and coefficients) than the single rate converter.

rcSingleStage = dsp.FIRRateConverter(InterpolationFactor=147,...
    DecimationFactor=160);
costSingleStage = cost(rcSingleStage)
costSingleStage = struct with fields:
                  NumCoefficients: 3507
                        NumStates: 24
    MultiplicationsPerInputSample: 21.9187
          AdditionsPerInputSample: 21

rcStage1 = dsp.FIRRateConverter(InterpolationFactor=7,...
    DecimationFactor=5);
rcStage2 = dsp.FIRRateConverter(InterpolationFactor=7,...
    DecimationFactor=8);
rcStage3 = dsp.FIRRateConverter(InterpolationFactor=3,...
    DecimationFactor=4);
rcMultiStage = dsp.FilterCascade(rcStage1,rcStage2,rcStage3);
costMultiStage = cost(rcMultiStage)
costMultiStage = struct with fields:
                  NumCoefficients: 348
                        NumStates: 70
    MultiplicationsPerInputSample: 71.7188
          AdditionsPerInputSample: 68.3750

Comparing the frequency response of single-stage and multistage approach

We use a chirp signal to compare the numerical accuracy between a single-stage rate converter and a cascaded multistage rate converter. To generate a chirp signal, we use a dsp.Chirp System object™. Initially, the frequency is set to 10 Hz which increases exponentially to 24 kHz at time t = 5 sec. The input signal is sampled at 48 kHz and each call to the dsp.Chirp System object returns an output of size 1600-by-1.

% Input sample rate
fsIn = 48e3;

% Output sample rate
fsOut = 441e2;

% Input Rows
inputFrameRows = 1000;

% Signal duration
Ts = 20;

% Creating a chirp signal sampled at 48 kHz
input = dsp.Chirp(Type="Linear",InitialFrequency=10,TargetFrequency=fsIn/2,...
    TargetTime=Ts,SweepTime=Ts,SamplesPerFrame=inputFrameRows,SampleRate=fsIn);

We can compare the frequency response between the single-stage and multistage rate conversion by using spectrumAnalyzer on the filtered outputs.

% Spectrum Analyzer to view the spectrogram of the input
scope1 = spectrumAnalyzer(ViewType="spectrogram",SampleRate=fsIn, ...
    PlotAsTwoSidedSpectrum=false, ...
    RBWSource="Property",RBW=100, ...
    VBWSource="Property",VBW=10, ...
    TimeSpanSource="Property",TimeSpan=Ts, ...
    YLimits=[-220 20], Title="Input signal");

% Spectrum Analyzer to view the spectrogram of the single-stage filtered output
scope2 = spectrumAnalyzer(ViewType="spectrogram",SampleRate=fsOut, ...
    PlotAsTwoSidedSpectrum=false, ...
    RBWSource="Property",RBW=100, ...
    VBWSource="Property",VBW=10, ...
    TimeSpanSource="Property",TimeSpan=Ts, ...
    YLimits=[-220 20], Title="Single-stage filtered output");

% Spectrum Analyzer to view the spectrogram of the multi-stage filtered output
scope3 = spectrumAnalyzer(ViewType="spectrogram",SampleRate=fsOut, ...
    PlotAsTwoSidedSpectrum=false, ...
    RBWSource="Property",RBW=100, ...
    VBWSource="Property",VBW=10, ...
    TimeSpanSource="Property",TimeSpan=Ts, ...
    YLimits=[-220 20], Title="Multi-stage filtered output");

% Number of steps required to process a signal of duration 5 seconds
numSteps = Ts * fsIn / inputFrameRows;

% Filter the input of duration 5 seconds.
for i=1:numSteps

    x = input();

    ySingleStage = rcSingleStage(x);
    
    yMultiStage = rcMultiStage(x);

    scope1(x);

    scope2(ySingleStage);

    scope3(yMultiStage);

end
% Input signal
release(scope1)

% Single-stage rate converter output
release(scope2)

% Multistage rate converter output
release(scope3)

Incorrect Ordering of Rate Converters

To demonstrate the effect of incorrect ordering of rate converters in the multistage process, we reorder the stages leading to the following sample rate change:

  • Stage 1, L = 3 and M = 4 (48 kHz to 36 kHz)

  • Stage 2, L = 7 and M = 5 (36 kHz to 50.4 kHz)

  • Stage 3, L = 7 and M = 8 (50.4 kHz to 44.1 kHz)

This ordering of the filters leads to a cutoff frequency of 18 kHz in stage 1. The input signal contains valid frequencies up to 44.1/2 or 22.05 kHz. To avoid aliasing which results in signal content loss, the first FIR rate converter filters out the frequencies in the range 18 kHz to 22.05 kHz.

We use the same input as before to compare the response of the multistage rate conversion process against the reference single-stage rate conversion process. The output spectrogram of the incorrectly ordered filter shows signal content loss due to a drop in the sampling frequency below 44.1 kHz.

input.reset();

rcStage1.reset();
rcStage2.reset();
rcStage3.reset();

% Incorrect order
rcMultiStageIncorrect = dsp.FilterCascade(rcStage3,rcStage1,rcStage2);

% Use single-stage rate converter output as reference
rcSingleStage.reset()

% Spectrum Analyzer to view the spectrogram of the input
scope4 = spectrumAnalyzer(ViewType="spectrogram",SampleRate=fsIn, ...
    PlotAsTwoSidedSpectrum=false, ...
    RBWSource="Property",RBW=100, ...
    VBWSource="Property",VBW=10, ...
    TimeSpanSource="Property",TimeSpan=Ts, ...
    YLimits=[-220 20], Title="Input signal");

% Spectrum Analyzer to view the spectrogram of the multi-stage filtered output
scope5 = spectrumAnalyzer(ViewType="spectrogram",SampleRate=fsOut, ...
    PlotAsTwoSidedSpectrum=false, ...
    RBWSource="Property",RBW=100, ...
    VBWSource="Property",VBW=10, ...
    TimeSpanSource="Property",TimeSpan=Ts, ...
    YLimits=[-220 20], Title="Multi-stage filtered output");

% Spectrum Analyzer to view the spectrogram of the reference output
scope6 = spectrumAnalyzer(ViewType="spectrogram",SampleRate=fsOut, ...
    PlotAsTwoSidedSpectrum=false, ...
    RBWSource="Property",RBW=100, ...
    VBWSource="Property",VBW=10, ...
    TimeSpanSource="Property",TimeSpan=Ts, ...
    YLimits=[-220 20], Title="Reference single-stage output signal");

% Filter the input of duration 5 seconds.
for i=1:numSteps

    x = input();
    
    yMultiStageIncorrect = rcMultiStageIncorrect(x);
    yRef = rcSingleStage(x);

    scope4(x);
    scope5(yMultiStageIncorrect);
    scope6(yRef);

end
% Input signal
release(scope4)

% Incorrect ordering of stages
release(scope5)

% Reference output
release(scope6)

Conclusion

After comparing the two approaches, we can conclude that the multistage approach efficiently converts the input sample rate using a significantly smaller combined filter order. Note that the rate change factors, order of rate converters and filter specifications are chosen in a manner to minimize signal content loss through aliasing and imaging.

See Also

Functions

Objects

Related Topics