Skip to Main Content Skip to Search
Product Documentation

Tutorial: Integrating MATLAB Code with a Simulink Model for Filtering an Audio Signal

Learning Objectives

In this tutorial, you will learn how to:

Tutorial Prerequisites

What You Need to Know

To work through this tutorial, you should have basic familiarity with MATLAB software. You should also understand how to create a basic Simulink model and how to simulate that model. For more information, see Simulink Software Basics in the Simulink documentation.

Required Products

To complete this tutorial, you must install the following products:

For instructions on installing MathWorks products, refer to the installation documentation. If you have installed MATLAB and want to check which other MathWorks products are installed, enter ver in the MATLAB Command Window. For instructions on installing and setting up a C compiler, see Setting Up the C/C++ Compiler in the MATLAB Coder documentation.

Example: The LMS Filter

Description

A least mean squares (LMS) filter is an adaptive filter that adjusts its transfer function according to an optimizing algorithm. You provide the filter with an example of the desired signal together with the input signal. The filter then calculates the filter weights, or coefficients, that produce the least mean squares of the error between the output signal and the desired signal.

This example uses an LMS filter to remove the noise in a music recording. There are two inputs. The first input is the distorted signal: the music recording plus the filtered noise. The second input is the desired signal: the unfiltered noise. The filter works to eliminate the difference between the output signal and the desired signal and outputs the difference, which, in this case, is the clean music recording. When you start the simulation, you hear both the noise and the music. Over time, the adaptive filter removes the noise so you hear only the music.

Algorithm

This example uses the least mean squares (LMS) algorithm to remove noise from an input signal. The LMS algorithm computes the filtered output, filter error, and filter weights given the distorted and desired signals.

At the start of the tutorial, the LMS algorithm uses a batch process to filter the audio input. This algorithm is suitable for MATLAB, where you are likely to load in the entire signal and process it all at once. However, a batch process is not suitable for processing a signal in real time. As you work through the tutorial, you refine the design of the filter to convert the algorithm from batch-based to stream-based processing.

The baseline function signature for the algorithm is:

function [ signal_out, err, weights ] = ...
    lms_01(signal_in, desired)

The filtering is performed in the following loop:

for n = 1:SignalLength
  % Compute the output sample using convolution:
  signal_out(n,ch) = weights' * signal_in(n:n+FilterLength-1,ch);
  % Update the filter coefficients:
  err(n,ch) = desired(n,ch) - signal_out(n,ch) ;
  weights = weights + mu*err(n,ch)*signal_in(n:n+FilterLength-1,ch);
end

where SignalLength is the length of the input signal, FilterLength is the filter length, and mu is the adaptation step size.

 What Is the Adaptation Step Size?

Filtering Process

The filtering process has three phases:

Reference

Haykin, Simon. Adaptive Filter Theory. Upper Saddle River, NJ: Prentice-Hall, Inc., 1996.

Files for the Tutorial

About the Tutorial Files

The tutorial uses the following files:

Location of Files

The tutorial files are available in the following folder: docroot\toolbox\simulink\examples\lms. To run the tutorial, you must copy these files to a local folder. For instructions, see Copying Files Locally.

Names and Descriptions of Files

TypeNameDescription
MATLAB fileslms_01.mBaseline MATLAB implementation of batch filter. Not suitable for code generation.
lms_02.mFilter modified from batch to streaming.
lms_03.mFrame-based streaming filter with Reset and Adapt controls.
lms_04.mFrame-based streaming filter with Reset and Adapt controls. Suitable for code generation.
lms_05.mDisabled inlining for code generation.
lms_06.mDemonstrates use of coder.nullcopy.
Simulink model filesacoustic_environment.mdlSimulink model that provides an overview of the acoustic environment.
noise_cancel_00.mdlSimulink model without a MATLAB Function block.
noise_cancel_01.mdlComplete noise_cancel_00 model including a MATLAB Function block.
noise_cancel_02.mdlSimulink model for use with lms_02.m.
noise_cancel_03.mdlSimulink model for use with lms_03.m.
noise_cancel_04.mdlSimulink model for use with lms_04.m.
noise_cancel_05.mdlSimulink model for use with lms_05.m.
noise_cancel_06.mdlSimulink model for use with lms_06.m.
design_templates.mdlSimulink model containing Adapt and Reset controls.

Tutorial Steps

Copying Files Locally

Copy the tutorial files to a local folder:

  1. Create a local solutions folder, for example, c:\test\lms\solutions.

  2. Change to the docroot\toolbox\simulink\examples folder. At the MATLAB command line, enter:

    cd(fullfile(docroot, 'toolbox', 'simulink', 'examples')) 
  3. Copy the contents of the lms subfolder to your solutions folder, specifying the full path name of the solutions folder:

    copyfile('lms', 'solutions')

    Your solutions folder now contains a complete set of solutions for the tutorial. If you do not want to perform the steps for each task, you can view the supplied solution to see how the code should look.

  4. Create a local work folder, for example, c:\test\lms\work.

  5. Copy the following files from your solutions folder to your work folder.

    • lms_01.m

    • lms_02.m

    • noise_cancel_00.mdl

    • acoustic_environment.mdl

    • design_templates.mdl

    Your work folder now contains all the files that you need to get started.

    You are now ready to set up your C compiler.

Setting Up Your C Compiler

Before generating code for your Simulink model, you must set up your C compiler. For most platforms, MathWorks supplies a default compiler with MATLAB. If your installation does not include a default compiler, for a list of supported compilers for the current release of MATLAB, see Supported Compilers and install a compiler that is suitable for your platform.

To install a compiler:

  1. At the MATLAB command line, enter:

    mex -setup
  2. Enter y to see the list of installed compilers.

  3. Select a supported compiler.

  4. Enter y to verify your choice.

Running the acoustic_environment Model

Run the acoustic_environment model supplied with the tutorial to understand the problem that you are trying to solve using the LMS filter. This model adds band-limited white noise to an audio signal and outputs the resulting signal to a speaker.

To simulate the model:

  1. Open acoustic_environment.mdl in Simulink:

    1. Set your MATLAB current folder to the folder that contains your working files for this tutorial. At the MATLAB command line, enter:

      cd work

      where work is the full path name of the folder containing your files. See Using the Current Folder Browser in the MATLAB Desktop Tools and Development Environment documentation for more information.

    2. At the MATLAB command line, enter:

      acoustic_environment

      The model opens.

  2. Ensure that your speakers are on.

  3. To simulate the model, from the Simulink model window, select Simulation > Start.

    As Simulink runs the model, you hear the audio signal distorted by noise.

  4. While the simulation is running, double-click the Manual Switch to select the audio source.

    Now you hear the desired audio input without any noise.

The goal of this tutorial is to use a MATLAB LMS filter algorithm to remove the noise from the noisy audio signal. You do this by adding a MATLAB Function block to the model and calling the MATLAB code from this block. To learn how, see Adding a MATLAB Function Block to Your Model.

Adding a MATLAB Function Block to Your Model

To modify the model and code yourself, work through the exercises in this section. Otherwise, open the supplied model noise_cancel_01.mdl in your solutions subfolder to see the modified model.

For the purposes of this tutorial, you add the MATLAB Function block to the noise_cancel_00.mdl model supplied with the tutorial. In practice, you would have to develop your own test bench starting with an empty Simulink model.

To add a MATLAB Function block to the noise_cancel_00 model:

  1. Open noise_cancel_00.mdl in Simulink.

    noise_cancel_00
  2. Add a MATLAB Function block to the model:

    1. At the MATLAB command line, type simulink to open the Simulink Library Browser.

    2. From the list of Simulink libraries, select the User-Defined Functions library.

    3. Click the MATLAB Function block and drag it into the noise_cancel_00 model. Place the block just above the red text annotation Place MATLAB Function Block here.

    4. Delete the red text annotations from the model.

    5. Save the model in the current folder as noise_cancel_01.

       Best Practice — Saving Incremental Code Updates

Calling Your MATLAB Code As an Extrinsic Function for Rapid Prototyping

In this part of the tutorial, you use the coder.extrinsic function to call your MATLAB code from the MATLAB Function block for rapid prototyping.

Why Call MATLAB Code As an Extrinsic Function?.  Calling MATLAB code as an extrinsic function provides these benefits:

How to Call MATLAB Code As an Extrinsic Function.   To call your MATLAB code from the MATLAB Function block:

  1. Double-click the MATLAB Function block to open the MATLAB Function Block Editor.

  2. Delete the default code displayed in the MATLAB Function Block Editor.

  3. Copy the following code to the MATLAB Function block.

    function [ Signal_Out, Weights ] = LMS(Noise_In, Signal_In) %#codegen   
        % Extrinsic:
        coder.extrinsic('lms_01');
        
        % Compute LMS:
        [ ~, Signal_Out, Weights ] = lms_01(Noise_In, Signal_In);
    end

     Why Use the Tilde (~) Operator?

  4. Save the model.

    The lms_01 function inputs Noise_In and Signal_In now appear as input ports to the block and the function outputs Signal_Out and Weights appear as output ports.

Connecting the MATLAB Function Block Inputs and Outputs.  

  1. Connect the MATLAB Function block inputs and outputs so that your model looks like this.

    See Connecting Blocks in the Simulink documentation for more information.

  2. In the MATLAB Function block code, preallocate the outputs by adding the following code after the extrinsic call:

    % Outputs:
    Signal_Out = zeros(size(Signal_In));
    Weights = zeros(32,1);

    The size of Weights is set to match the Numerator coefficients of the Digital Filter in the Acoustic Environment subsystem.

     Why Preallocate the Outputs?

     Modified MATLAB Function Block Code

  3. Save the model.

    You are now ready to check your model for errors.

Checking the noise_cancel_01 Model.  

  1. In the Simulink model window, select Edit > Update Diagram.

    Simulink fails to update diagram.

    Because the Analysis and Visualization block expects to receive a frame-based signal from the LMS filter, you must configure the MATLAB Function block Signal_Out output parameter to be frame-based rather than sample-based.

    1. Double-click the MATLAB Function block to open the MATLAB Function Block Editor.

    2. Select Tools > Edit Data/Ports to open the Ports and Data Manager.

    3. Select the signal called Signal_Out from the list in the left pane.

    4. On the General tab, change the Sampling mode from Sample based to Frame based.

    5. Click the Apply button and close the Ports and Data Manager and the MATLAB Function Block Editor.

    6. Save the model.

  2. Check the model again; select Edit > Update Diagram in the Simulink model window.

    Simulink updates diagram successfully. You are ready for the next task, Simulating the noise_cancel_01 Model

Simulating the noise_cancel_01 Model

To simulate the model:

  1. Ensure that you can see the Time Domain plots.

    To view the plots, in the noise_cancel_01 model, open the Analysis and Visualization block and then open the Time Domain block.

  2. In the Simulink model window, select Simulation > Start.

    As Simulink runs the model, you see and hear outputs. Initially, you hear the audio signal distorted by noise. Then the filter attenuates the noise gradually, until you hear only the music playing with very little noise remaining. After two seconds, you hear the distorted noisy signal again and the filter attenuates the noise again. This cycle repeats continuously.

    MATLAB displays the following plot showing this cycle.

  3. Stop the simulation.

 Why Does the Filter Reset Every 2 Seconds?

Modifying the Filter to Use Streaming

What Is Streaming?.  A streaming filter is called repeatedly to process fixed-size chunks of input data, or frames, until it has processed the entire input signal. The frame size can be as small as a single sample, in which case the filter would be operating in a sample-based mode, or up to a few thousand samples, for frame-based processing.

Why Use Streaming?.  The design of the filter algorithm in lms_01 has the following disadvantages:

In an embedded application, the filter is likely to be processing a continuous input stream. As a result, the input signal can be substantially longer than the maximum length that a filter working in batch mode could possibly handle. To make the filter work for any signal length, it must run in real time. One solution is to convert the filter from batch-based processing to stream-based processing.

Viewing the Modified MATLAB Code.  The conversion to streaming involves:

Open the supplied file lms_02.m in your work subfolder to see the modified algorithm.

 Contents of lms_02.m

Summary of Changes to the Filter Algorithm.  Note the following important changes to the filter algorithm:

Modifying Your Model to Call the Updated Algorithm.  To modify the model yourself, work through the exercises in this section. Otherwise, open the supplied model noise_cancel_02.mdl in your solutions subfolder to see the modified model.

  1. In the noise_cancel_01 model, double-click the MATLAB Function block to open the MATLAB Function Block Editor.

  2. Modify the MATLAB Function block code to call lms_02.

    1. Modify the extrinsic call.

      % Extrinsic:
      coder.extrinsic('lms_02');
    2. Modify the call to the filter algorithm.

      % Compute LMS:
      [ ~, Signal_Out, Weights ] = lms_02(Noise_In, Signal_In);

       Modified MATLAB Function Block Code

  3. Change the frame size from 16384 to 64, which represents a more realistic value.

    1. In the Simulink model window, select File > Model Properties.

      The Model Properties dialog box opens.

    2. Select the Callbacks tab.

    3. In the Model callbacks list, select InitFcn.

    4. Change the value of FrameSize to 64.

    5. Click Apply and close the dialog box.

  4. Save your model as noise_cancel_02.mdl.

Simulating the Streaming Algorithm.  To simulate the model:

  1. Ensure that you can see the Time Domain plots.

  2. Start the simulation.

    As Simulink runs the model, you see and hear outputs. Initially, you hear the audio signal distorted by noise. Then, during the first few seconds, the filter attenuates the noise gradually, until you hear only the music playing with very little noise remaining. MATLAB displays the following plot showing filter convergence after only a few seconds.

  3. Stop the simulation.

The filter algorithm is now suitable for Simulink. You are ready to elaborate your model to use Adapt and Reset controls.

Adding Adapt and Reset Controls

Why Add Adapt and Reset Controls?.  In this part of the tutorial, you add Adapt and Reset controls to your filter. Using these controls, you can turn the filtering on and off. When Adapt is enabled, the filter continuously updates the filter weights. When Adapt is disabled, the filter weights remain at their current values. If Reset is set, the filter resets the filter weights.

Modifying Your MATLAB Code.  To modify the code yourself, work through the exercises in this section. Otherwise, open the supplied file lms_03.m in your solutions subfolder to see the modified algorithm.

To modify your filter code:

  1. Open lms_02.m.

  2. In the Set up section, replace

    if ( isempty(weights) )

    with

    if ( reset || isempty(weights) )
  3. In the filter loop, update the filter coefficients only if Adapt is ON.

    if adapt
      weights = weights + mu*err(n,ch)*fifo(:,ch);
    end
  4. Change the function signature to use the Adapt and Reset inputs and change the function name to lms_03.

    function [ signal_out, err, weights_out ] = ...
      lms_03(signal_in, desired, reset, adapt)
  5. Save the file in the current folder as lms_03.m:

 Contents of lms_03.m

 Summary of Changes to the Filter Algorithm

Modifying Your Model to Use Reset and Adapt Controls.  To modify the model yourself, work through the exercises in this section. Otherwise, open the supplied model noise_cancel_03.mdl in your solutions subfolder to see the modified model.

  1. Open the noise_cancel_02 model.

  2. Double-click the MATLAB Function block to open the MATLAB Function Block Editor.

  3. Modify the MATLAB Function block code:

    1. Update the function declaration.

      function [ Signal_Out, Weights ] = ...
         LMS(Adapt, Reset, Noise_In, Signal_In )
    2. Update the extrinsic call.

      coder.extrinsic('lms_03');
    3. Update the call to the LMS algorithm.

      % Compute LMS:
      [ ~, Signal_Out, Weights ] = ...
         lms_03(Noise_In, Signal_In, Reset, Adapt);
    4. Close the MATLAB Function Block Editor.

      The lms_03 function inputs Reset and Adapt now appear as input ports to the MATLAB Function block.

  4. Open the design_templates model.

  5. Copy the Settings block from this model to your noise_cancel_02 model:

    1. From the design_templates model menu, select Edit > Select All.

    2. Select Edit > Copy.

    3. From the noise_cancel_02 model menu, select Edit > Paste.

  6. Connect the Adapt and Reset outputs of the Settings subsystem to the corresponding inputs on the MATLAB Function block. Your model should now appear as follows.

  7. Save the model as noise_cancel_03.mdl.

Simulating the Model with Adapt and Reset Controls.  To simulate the model and see the effect of the Adapt and Reset controls:

  1. In the noise_cancel_03 model, view the Convergence scope:

    1. Double-click the Analysis and Visualization subsystem.

      The contents of the Analysis and Visualization subsystem appear.

    2. Double-click the Convergence scope.

  2. In the Simulink model window, select Simulation > Start.

    Simulink runs the model as before. While the model is running, toggle the Adapt and Reset controls and view the Convergence scope to see their effect on the filter.

    The filter converges when Adapt is ON and Reset is OFF, then resets when you toggleReset. The results might look something like this:

  3. Stop the simulation.

Generating Code

You have proved that your algorithm works in Simulink. Next you generate code for your model. Before generating code, you must ensure that your MATLAB code is suitable for code generation. For code generation, you must remove the extrinsic call to your code.

Making Your Code Suitable for Code Generation.  To modify the model and code yourself, work through the exercises in this section. Otherwise, open the supplied model noise_cancel_04.mdl and file lms_04.m in your solutions subfolder to see the modifications.

  1. Rename the MATLAB Function block to LMS_Filter. Double-click the annotation MATLAB Function below the MATLAB Function block and replace the text with LMS_Filter.

    When you generate code for the MATLAB Function block, Simulink Coder uses the name of the block in the generated code. It is good practice to use a meaningful name.

  2. In your noise_cancel_03 model, double-click the MATLAB Function block.

    The MATLAB Function Block Editor opens.

  3. Delete the extrinsic declaration.

    % Extrinsic:
    coder.extrinsic('lms_03');
  4. Delete the preallocation of outputs.

    % Outputs:
    Signal_Out = zeros(size(Signal_In));
    Weights = zeros(32,1);
  5. Modify the call to the filter algorithm.

    % Compute LMS:
    [ ~, Signal_Out, Weights ] = ...
       lms_04(Noise_In, Signal_In, Reset, Adapt);
  6. Save the model as noise_cancel_04.

  7. Open lms_03.m

    1. Modify the function name to lms_04.

    2. Turn on error checking specific to code generation by adding the %#codegen compilation directive after the function declaration.

      function [ signal_out, err, weights_out ] = ...
          lms_04(signal_in, desired, reset, adapt) %#codegen

      The code analyzer message indicator in the top right turns red to indicate that the code analyzer has detected code generation issues. The code analyzer underlines the offending code in red and places a red marker to the right of it.

  8. Move your pointer over the first red marker to view the error information.

    The code analyzer detects that code generation requires signal_out to be fully defined before subscripting it and does not support growth of variable size data through indexing.

  9. Move your pointer over the second red marker and note that the code analyzer detects the same errors for err.

  10. To address these errors, preallocate the outputs signal_out and err. Add this code after the filter setup.

     % Output Arguments:
            
     % Pre-allocate output and error signals:
     signal_out = zeros(FrameSize,ChannelCount);
     err = zeros(FrameSize,ChannelCount);

     Why Preallocate the Outputs?

    The red error markers for the two lines of code disappear. The code analyzer message indicator in the top right edge of the code turns green, which indicates that you have fixed all the errors and warnings detected by the code analyzer.

    For more information on using the code analyzer, see Using the MATLAB Code Analyzer Report in the MATLAB Desktop Tools and Development documentation.

     Contents of lms_04.m

  11. Save the file as lms_04.m.

Generating Code for noise_cancel_04.mdl.  

  1. Before generating code, ensure that Simulink Coder creates a code generation report. This HTML report provides easy access to the list of generated files with a summary of the configuration settings used to generate the code.

    1. In the Simulink model window, select Simulation > Configuration Parameters.

      The Configuration Parameters dialog box opens.

    2. In the left pane of the Configuration Parameters dialog box, select Code Generation > Report.

    3. In the right pane, select Create code generation report.

      The Launch report automatically option is also selected.

    4. Click Apply and close the Configuration Parameters dialog box.

    5. Save your model.

  2. To generate code for the LMS Filter subsystem:

    1. In your model, right-click the LMS Filter subsystem to select it and open the context menu.

    2. From the context menu, select Code Generation > Build Subsystem.

      The Build code for subsystem dialog box appears. Click the Build button.

      The Simulink Coder software generates C code for the subsystem and launches the code generation report.

      For more information on using the code generation report, see in the Simulink Coder documentation.

    3. In the left pane of the code generation report, click the LMS_Filter.c link to view the generated C code. Note that the lms_04 function has no code because inlining is enabled by default.

  3. Modify your filter algorithm to disable inlining:

    1. In lms_04.m, after the function declaration, add:

      coder.inline('never')
    2. Change the function name to lms_05 and save the file as lms_05.m in the current folder.

    3. In your noise_cancel_04 model, double-click the MATLAB Function block.

      The MATLAB Function Block Editor opens.

    4. Modify the call to the filter algorithm to call lms_05.

      % Compute LMS:
      [ ~, Signal_Out, Weights ] = ...
         lms_05(Noise_In, Signal_In, Reset, Adapt);
    5. Save the model as noise_cancel_05.mdl.

  4. Generate code for the updated model.

    1. In the model, right-click the LMS Filter subsystem to select it and open the context menu.

    2. From the context menu, select Code Generation > Build Subsystem.

      The Build code for subsystem dialog box appears.

    3. Click the Build button.

      The Simulink Coder software generates C code for the subsystem and launches the code generation report.

    4. In the left pane of the code generation report, click the LMS_Filter.c link to view the generated C code.

      This time the lms_05 function has code because you disabled inlining.

      /* Forward declaration for local functions */
         static void LMS_Filter_lms_05 ...
             (const real_T signal_in[64],const real_T ...
             desired[64], real_T reset, real_T adapt, ...
                   real_T signal_out[64], ...
            real_T err[64], real_T weights_out[32]);
         
      /* Function for MATLAB Function Block: 'root/LMS_Filter' */
         static void LMS_Filter_lms_05 ...
            (const real_T signal_in[64], const real_T ...
               desired[64], real_T reset, real_T adapt, ...
                   real_T signal_out[64], ...
           real_T err[64], real_T weights_out[32])
      

Optimizing the LMS Filter Algorithm

This part of the tutorial demonstrates when and how to preallocate memory for a variable without incurring the overhead of initializing memory in the generated code.

In lms_05.m, the MATLAB code not only declares signal_out and err to be a FrameSize-by-ChannelCount vector of real doubles, but also initializes each element of signal_out and err to zero. These signals are initialized to zero in the generated C code.

MATLAB CodeGenerated C Code
% Pre-allocate output and error signals:
signal_out = zeros(FrameSize,ChannelCount);
err = zeros(FrameSize,ChannelCount);
/* Pre-allocate output and error signals: */
79 for (i = 0; i < 64; i++) {
80 signal_out[i] = 0.0;
81 err[i] = 0.0;
82 }

This forced initialization is unnecessary because both signal_out and err are explicitly initialized in the MATLAB code before they are read.

Use coder.nullcopy in the declaration of signal_out and err to eliminate the unnecessary initialization of memory in the generated code:

  1. In lms_05.m, preallocate signal_out and err using coder.nullcopy:

    % Pre-allocate output and error signals: 
    signal_out = coder.nullcopy(zeros(FrameSize, ChannelCount));
    err = coder.nullcopy(zeros(FrameSize, ChannelCount));

  2. Change the function name to lms_06 and save the file as lms_06.m in the current folder.

  3. In your noise_cancel_05 model, double-click the MATLAB Function block.

    The MATLAB Function Block Editor opens.

  4. Modify the call to the filter algorithm.

    % Compute LMS:
    [ ~, Signal_Out, Weights ] = ...
       lms_06(Noise_In, Signal_In, Reset, Adapt);
  5. Save the model as noise_cancel_06.mdl.

Generate code for the updated model.

  1. Right-click the LMS Filter subsystem to select it and open the context menu.

  2. From the context menu, select Code Generation > Build Subsystem.

    The Build code for subsystem dialog box appears. Click the Build button.

    The Simulink Coder software and generates C code for the subsystem and launches the code generation report.

  3. In the left pane of the code generation report, click the LMS_Filter.c link to view the generated C code.

    In the generated C code, this time there is no initialization to zero of signal_out and err.

  


Related Products & Applications

Learn more about Simulink through this collection of videos, articles, technical literature and the Getting Started with Simulink Guide.

 © 1984-2012- The MathWorks, Inc.    -   Site Help   -   Patents   -   Trademarks   -   Privacy Policy   -   Preventing Piracy   -   RSS