Create Composite System object

This example shows how to create a System object™ composed of other System objects. In this example, build a multi-notch filter using two dsp.NotchPeakFilter System objects. Multi-notch filters are used in many applications. Examples include audio phasers and applications that require the removal of multiple interfering tones.

Create Multi-Notch Filter

Create Moving Average System object (MATLAB) explains in detail how to write a System object using a template file. In this example, the entire System object is provided for convenience in dspdemo.CompositeObj_MultiNotch. To view the MATLAB® code, at the command prompt enter:

edit dspdemo.CompositeObj_MultiNotch
dspdemo.CompositeObj_MultiNotch has five public properties. Public properties are accessible to every user. The first property, SampleRate, is a nontunable property. Nontunable properties cannot change when the filter is locked (after you use step on the filter). The remaining properties, CenterFrequency1, CenterFrequency2, QualityFactor1, and QualityFactor2 control settings in the two notch filters contained in dspdemo.CompositeObj_MultiNotch. These four properties are tunable. You can change the values of these properties while streaming data.

Set Up the Multi-Notch Filters

dspdemo.CompositeObj_MultiNotch uses dsp.NotchPeakFilter to design the two notch filters. The notch filters are set up in the setupImpl method.

methods (Access=protected)
        function setupImpl(obj,~)
            % Construct two notch filters with default values
            obj.NotchFilter1 = dsp.NotchPeakFilter(...
                'Specification', 'Quality factor and center frequency',...
                'CenterFrequency',400);
            obj.NotchFilter2 = dsp.NotchPeakFilter(...
                'Specification', 'Quality factor and center frequency',...
                'CenterFrequency',800);
        end
end

Contain System Objects as Private Properties

The ability to create more than one instance of a System object and having each instance manage its own state is one of the biggest advantages of using System objects over functions. The private properties NotchFilter1 and NotchFilter2 are used to store the two notch filters.

properties (Access=private)
        % This example class contains two notch filters (more can be added
        % in the same way)
        NotchFilter1  
        NotchFilter2  
end

Work with Dependent Properties

The SampleRate property as well as the remaining four public properties are implemented as dependent properties in this example. Whenever you assign a value to one of the dependent properties, the value is set in the corresponding single-notch filter. When you read one of the dependent properties, the value is read from the corresponding single-notch filter. Find the following code block in dspdemo.CompositeObj_MultiNotch.

properties (Dependent)
        %CenterFrequency1 Center frequency of first notch
        %   Specify the first notch center frequency as a finite positive
        %   numeric scalar in Hertz. The default is 400 Hz. This property
        %   is tunable.
        CenterFrequency1;
        %QualityFactor1 Quality factor of first notch
        %   Specify the quality factor (Q factor) for the first notch
        %   filter. The default value is 5. This property is tunable.
        QualityFactor1;
        %CenterFrequency2 Center frequency of second notch
        %   Specify the second notch center frequency as a finite positive
        %   numeric scalar in Hertz. The default is 800 Hz. This property
        %   is tunable.
        CenterFrequency2;
        %QualityFactor2 Quality factor of second notch
        %   Specify the quality factor (Q factor) for the first notch
        %   filter. The default value is 5. This property is tunable.
        QualityFactor2;
end

Use the Multi-Notch Filter - Initialization

To use dspdemo.CompositeObj_MultiNotch, initialize the filter and any other required components. In this example, initialize an audio file reader, a multi-notch filter, a transfer function estimator, an array plotter, and an audio player.

FrameSize = 1024;
AFR = dsp.AudioFileReader('guitar10min.ogg','SamplesPerFrame',FrameSize);
Fs  = AFR.SampleRate;

MNF = dspdemo.CompositeObj_MultiNotch('SampleRate',Fs);

TFE = dsp.TransferFunctionEstimator(...
    'FrequencyRange','onesided','SpectralAverages',5);
AP  = dsp.ArrayPlot('PlotType','Line','YLimits',[-85 15],...
    'SampleIncrement',Fs/FrameSize);
P   = audioDeviceWriter;

Use the Multi-Notch Filter - Streaming

To illustrate the tunability of the two notch filter center frequencies, vary the center frequencies sinusoidally in a loop. The starting center frequencies are 500 and 2000 Hz. The first center frequency oscillates over the range [100, 900] Hz with a frequency of 0.2 Hz. The second center frequency oscillates over the range [1200, 2800] Hz with a frequency of 0.5 Hz. Because CenterFrequency1 and CenterFrequency2 are dependent properties, modifying their values in the loop changes the center frequencies in the two notch filters contained in dspdemo.CompositeObj_MultiNotch. To visualize the multi-notch filter, estimate and plot the transfer function continuously. The quality factors remain constant. The simulation runs for 20 seconds.

MNF.QualityFactor1 = .5; 
MNF.QualityFactor2 = 1;

f0 = 0.2; 
f1 = 0.5; 

k = 0;
tic,
while toc < 20 
    x = AFR();
    t = k*FrameSize/Fs;
    k = k+1;

    MNF.CenterFrequency1 =  500 + 400*sin(2*pi*f0*t);
    MNF.CenterFrequency2 = 2000 + 800*sin(2*pi*f1*t);
    CF1(k) = MNF.CenterFrequency1;
    CF2(k) = MNF.CenterFrequency2;
    
    y = MNF(x);
    
    H = TFE(x(:,1),y(:,1));
    magdB = 20*log10(abs(H));
    AP(magdB);
    P(y);
end

Execute this code to show how the two notch center frequencies varied over the simulation.

subplot(2,1,1)
plot(CF1); 
title('Center Frequency 1');
ylabel('Notch CF (Hz)');
subplot(2,1,2)
plot(CF2);
title('Center Frequency 2');
ylabel('Notch CF (Hz)');
xlabel('Iteration')