Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

平均化フィルターのコードの生成

この例では、codegen コマンドを使って MATLAB® 関数から C コードを生成する場合の推奨ワークフローを示します。手順は以下のとおりです。

1. コードの生成を意図していることを示すために、MATLAB 関数に %#codegen 命令を付け加えます。この命令によって、さらに MATLAB コード アナライザーがコード生成用の MATLAB に特有の警告とエラーを特定できるようになります。

2. MATLAB コードがコードの生成に適しているかどうかをチェックするために MEX 関数を生成します。エラーが発生した場合は、C コードを生成する前に修正しなければなりません。

3. MATLAB で MEX 関数をテストして、その関数が元の MATLAB コードと機能的に等価であることと実行時エラーが発生しないことを確認します。

4. C コードを生成します。

5. C コードを確認します。

必要条件

この例には必要条件はありません。

関数 averaging_filter について

関数 averaging_filter.m は入力信号に対する平均化フィルターとして働き、入力ベクトルの値を取ってベクトル内のそれぞれの値の平均値を計算します。出力ベクトルは、サイズも形状も入力ベクトルと同じです。

type averaging_filter
% y = averaging_filter(x)
% Take an input vector signal 'x' and produce an output vector signal 'y' with
% same type and shape as 'x' but filtered.
function y = averaging_filter(x) %#codegen
% Use a persistent variable 'buffer' that represents a sliding window of
% 16 samples at a time.
persistent buffer;
if isempty(buffer)
    buffer = zeros(16,1);
end
y = zeros(size(x), class(x));
for i = 1:numel(x)
    % Scroll the buffer
    buffer(2:end) = buffer(1:end-1);
    % Add a new sample value to the buffer
    buffer(1) = x(i);
    % Compute the current average value of the window and
    % write result
    y(i) = sum(buffer)/numel(buffer);
end

コンパイル命令 %#codegen は、当該の MATLAB コードがコード生成用であることを示します。

サンプル データの作成

ノイズを含んだ正弦波を生成して結果をプロットします。

v = 0:0.00614:2*pi;
x = sin(v) + 0.3*rand(1,numel(v));
plot(x, 'red');

Figure contains an axes object. The axes object contains an object of type line.

テスト用の MEX 関数の生成

codegen コマンドを使用して MEX 関数を生成します。codegen コマンドは、MATLAB 関数がコードの生成に適しているかどうかをチェックし、C コード生成の前に MATLAB でテストできる MEX 関数を生成します。

codegen averaging_filter -args {x}
Code generation successful.

C では静的なデータ型が使用されるため、codegen は MATLAB ファイル内のすべての変数のプロパティをコンパイル時に判別しなければなりません。ここでは、codegen が入力されたデータ型に基づいて新しいデータ型を推測できるように、コマンド ライン オプション -args がサンプル入力を提供します。上記で作成されるサンプル信号をサンプル入力として使用することで、MEX 関数が確実に同じ入力を使用するようにします。

既定で、codegen は、現在のフォルダーに averaging_filter_mex という名前の MEX 関数を生成します。これにより、MATLAB コードと MEX 関数をテストして結果を比較することができます。

MATLAB での MEX 関数のテスト

MATLAB で MEX 関数を実行します。

y = averaging_filter_mex(x);
% Plot the result when the MEX function is applied to the noisy sine wave.
% The 'hold on' command ensures that the plot uses the same figure window as
% the previous plot command.
hold on;
plot(y, 'blue');

Figure contains an axes object. The axes object contains 2 objects of type line.

C コードの生成

codegen -config coder.config('lib') averaging_filter -args {x}
Code generation successful.

生成されたコードの確認

-config coder.config('lib') オプションを指定された codegen コマンドは、スタンドアロン C ライブラリとしてパッケージ化された C コードを生成します。生成された C コードは codegen/lib/averaging_filter/ フォルダーにあります。ファイルは、以下のとおりです。

dir codegen/lib/averaging_filter/
.                              ..                             _clang-format                  averaging_filter.a             averaging_filter.c             averaging_filter.h             averaging_filter.o             averaging_filter_data.c        averaging_filter_data.h        averaging_filter_data.o        averaging_filter_initialize.c  averaging_filter_initialize.h  averaging_filter_initialize.o  averaging_filter_rtw.mk        averaging_filter_terminate.c   averaging_filter_terminate.h   averaging_filter_terminate.o   averaging_filter_types.h       buildInfo.mat                  codeInfo.mat                   codedescriptor.dmr             compileInfo.mat                examples                       interface                      rtw_proj.tmw                   rtwtypes.h                     

関数 averaging_filter.c の C コードの検査

type codegen/lib/averaging_filter/averaging_filter.c
/*
 * Prerelease License - for engineering feedback and testing purposes
 * only. Not for sale.
 * File: averaging_filter.c
 *
 * MATLAB Coder version            : 23.2
 * C/C++ source code generated on  : 27-Jul-2023 14:57:01
 */

/* Include Files */
#include "averaging_filter.h"
#include "averaging_filter_data.h"
#include "averaging_filter_initialize.h"
#include <string.h>

/* Variable Definitions */
static double buffer[16];

/* Function Definitions */
/*
 * Use a persistent variable 'buffer' that represents a sliding window of
 *  16 samples at a time.
 *
 * Arguments    : const double x[1024]
 *                double y[1024]
 * Return Type  : void
 */
void averaging_filter(const double x[1024], double y[1024])
{
  double dv[15];
  int i;
  int k;
  if (!isInitialized_averaging_filter) {
    averaging_filter_initialize();
  }
  /*  y = averaging_filter(x) */
  /*  Take an input vector signal 'x' and produce an output vector signal 'y'
   * with */
  /*  same type and shape as 'x' but filtered. */
  for (i = 0; i < 1024; i++) {
    double b_y;
    /*  Scroll the buffer */
    memcpy(&dv[0], &buffer[0], 15U * sizeof(double));
    /*  Add a new sample value to the buffer */
    b_y = x[i];
    buffer[0] = b_y;
    /*  Compute the current average value of the window and */
    /*  write result */
    for (k = 0; k < 15; k++) {
      double d;
      d = dv[k];
      buffer[k + 1] = d;
      b_y += d;
    }
    y[i] = b_y / 16.0;
  }
}

/*
 * Use a persistent variable 'buffer' that represents a sliding window of
 *  16 samples at a time.
 *
 * Arguments    : void
 * Return Type  : void
 */
void averaging_filter_init(void)
{
  memset(&buffer[0], 0, 16U * sizeof(double));
}

/*
 * File trailer for averaging_filter.c
 *
 * [EOF]
 */