Main Content

このページは前リリースの情報です。該当の英語のページはこのリリースで削除されています。

MATLAB コードを使ったオーディオ信号へのフィルター適用

学習目的

このチュートリアルでは、以下の方法について説明します。

  • モデル化、シミュレーション、組み込みプロセッサへの配布のために MATLAB® 関数を Simulink® モデルに追加するには MATLAB Function ブロックを使用します。

    この機能は、Simulink のグラフィック言語よりは MATLAB のテキスト言語を使った方が記述しやすいアルゴリズムのコード作成に役立ちます。

  • MATLAB Function ブロックから MATLAB コードを呼び出すには、coder.extrinsic を使用します。

    この機能では、既存の MATLAB コードをコード生成に適したものにせずに Simulink から呼び出すことができるため、ラピッド プロトタイピングが可能になります。

  • 既存の MATLAB コードがコード生成に適しているか確認します。

  • MATLAB アルゴリズムをバッチ処理からストリーミングに変換します。

  • コード生成に適したコードでの永続変数の使用方法

    実行のたびにフィルター アルゴリズムによって値がリセットされないように、フィルターの重みは persistent にしなければなりません。

チュートリアルの必要条件

必要な知識

このチュートリアルをこなすためには、MATLAB ソフトウェアに関する基本的な知識が必要です。さらに、基本的な Simulink モデルの作成方法、およびそのモデルのシミュレーション方法についても理解していなければなりません。詳細については、簡単なモデルの作成を参照してください。

必要な製品

このチュートリアルを実行するには、次の製品をインストールしなければなりません。

  • MATLAB

  • MATLAB Coder™

  • Simulink

  • Simulink Coder

  • DSP System Toolbox™

  • C コンパイラ

    サポートされているコンパイラのリストは、サポートされるコンパイラを参照してください。

MathWorks® 製品のインストール方法の詳細は、インストール ドキュメンテーションを参照してください。MATLAB がインストールされている場合、その他にインストールされている MathWorks 製品を確認するには、MATLAB コマンド ウィンドウに「ver」と入力します。C コンパイラのインストールと設定方法の詳細は、C または C++ コンパイラの設定 (MATLAB Coder)を参照してください。

例: LMS フィルター

説明

最小二乗平均 (LMS) フィルターは、最適化アルゴリズムに従ってその伝達関数を調整する適応フィルターです。フィルターには入力信号と共に目的の信号の例を与えます。フィルターは、出力信号と目的の信号間の誤差の最小二乗平均を生成するフィルターの重み (係数) を計算します。

この例では、LMS フィルターを使用して音楽のレコーディングのノイズを除去します。入力は 2 つあります。1 つ目の入力は歪んだ信号で、音楽のレコーディングにフィルター処理後のノイズが加わったものです。2 つ目の入力は目的の信号で、フィルター処理されていないノイズです。フィルターは、出力信号と目的の信号間の差を解消するように機能し、その差を出力します。ここでは、音楽のクリーンなレコーディングが出力されます。シミュレーションを開始すると、ノイズと音楽の両方が聞こえます。時間の経過と共に、適応フィルターによってノイズが排除されるので、音楽だけが聞こえるようになります。

アルゴリズム

この例では、最小平均二乗 (LMS) アルゴリズムを使用して入力信号からノイズを除去します。LMS アルゴリズムは、歪んだ信号と目的の信号を指定すると、フィルター処理された出力、フィルター誤差、フィルターの重みを計算します。

チュートリアルの冒頭では、LMS アルゴリズムはバッチ処理を使用してオーディオ入力をフィルター処理します。このアルゴリズムは、信号全体を読み込んですべて一度に処理する MATLAB に適しています。ただし、バッチ処理はリアルタイムでの信号の処理には適しません。チュートリアルの実行と共に、フィルターの設計を調整し、アルゴリズムをバッチベースからストリームベースの処理に変換します。

アルゴリズムのベースラインの関数シグネチャは、次のとおりです。

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

フィルター処理は次のループで実行されます。

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
ここで、SignalLength は入力信号の長さ、FilterLength はフィルターの長さ、mu は適応ステップ サイズです。

 適応ステップ サイズとは

フィルター処理

フィルター処理には次の 3 つの段階があります。

  • 畳み込み

    フィルターの畳み込みは、次のようにして実行されます。

    signal_out(n,ch) = weights' * signal_in(n:n+FilterLength-1,ch); 

     畳み込みとは

  • 誤差の計算

    誤差は、次のように目的の信号と出力信号間の差です。

    err(n,ch) = desired(n,ch) - signal_out(n,ch);

  • 適応

    フィルターの重みの新しい値は、フィルターの重みの古い値に、誤差信号、歪んだ信号、および適応ステップ サイズに基づく補正係数を加えたものです。

    weights = weights + mu*err(n,ch)*signal_in(n:n+FilterLength-1,ch);

参考文献

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

チュートリアルのファイル

チュートリアル ファイルについて

チュートリアルでは、以下のファイルを使用します。

  • チュートリアルの各ステップの Simulink モデル ファイル。

  • 例の各ステップの MATLAB コード ファイル。

    このチュートリアルを通して、単純な最小二乗平均 (LMS) フィルター アルゴリズムを含む MATLAB ファイルを呼び出す Simulink モデルを使用して作業します。

ファイルの位置

チュートリアルのファイルは次のフォルダーにあります。docroot\toolbox\simulink\examples\lms。チュートリアルを実行するには、これらのファイルをローカル フォルダーにコピーしなければなりません。詳細は、ファイルの局所的なコピーを参照してください。

ファイルの名前と説明

タイプ名前説明
MATLAB ファイルlms_01バッチ フィルターのベースライン MATLAB 実装。コード生成に適していない。
lms_02バッチからストリーミングに変更したフィルター。
lms_03Reset コントロールと Adapt コントロール付きのフレームベースのストリーミング フィルター。
lms_04Reset コントロールと Adapt コントロール付きのフレームベースのストリーミング フィルター。コード生成に適している。
lms_05コード生成のためにインライン化を無効にする。
lms_06coder.nullcopy の使用を説明する。
Simulink モデル ファイルacoustic_environmentAcoustic Environment の概要を提供する Simulink モデル。
noise_cancel_00MATLAB Function ブロックのない Simulink モデル。
noise_cancel_01MATLAB Function ブロックを含む完全な noise_cancel_00 モデル。
noise_cancel_02lms_02.m と一緒に使用する Simulink モデル。
noise_cancel_03lms_03.m と一緒に使用する Simulink モデル。
noise_cancel_04lms_04.m と一緒に使用する Simulink モデル。
noise_cancel_05lms_05.m と一緒に使用する Simulink モデル。
noise_cancel_06lms_06.m と一緒に使用する Simulink モデル。
design_templatesAdapt コントロールと Reset コントロールを含む Simulink モデル。

チュートリアルのステップ

ファイルの局所的なコピー

次の手順に従って、チュートリアル ファイルをローカル フォルダーにコピーします。

  1. たとえば c:\test\lms\solutions のようなローカル solutions フォルダーを作成します。

  2. docroot\toolbox\simulink\examples フォルダーに変更します。MATLAB コマンド ラインで以下のように入力します。

    cd(fullfile(docroot, 'toolbox', 'simulink', 'examples')) 

  3. solutions フォルダーの絶対パス名を指定して、lms サブフォルダーの内容を solutions フォルダーにコピーします。

    copyfile('lms', 'solutions')
    これで solutions フォルダーには、チュートリアルの解の完全セットが含まれます。各タスクのステップを実行しない場合は、与えられた解を表示して、コードの外観を確認できます。

  4. たとえば c:\test\lms\work のようなローカル work フォルダーを作成します。

  5. 以下のファイルを solutions フォルダーから work フォルダーにコピーします。

    • lms_01

    • lms_02

    • noise_cancel_00

    • acoustic_environment

    • design_templates

    これで work フォルダーにはチュートリアルの開始にあたり必要なすべてのファイルが含まれます。

    これで、C コンパイラの設定の準備ができました。

C コンパイラの設定

MATLAB Function ブロックを構築するには、サポートされているコンパイラが必要です。MATLAB では既定のコンパイラとして 1 つのコンパイラが自動的に選択されます。システムに MATLAB でサポートされているコンパイラが複数インストールされている場合は、mex -setup コマンドを使用して既定のコンパイラを変更できます。既定のコンパイラの変更およびサポートされるコンパイラを参照してください。

acoustic_environment モデルの実行

チュートリアルに付属する acoustic_environment モデルを実行し、LMS フィルターを使用して解決しようとしている問題を理解します。このモデルは、帯域幅を制限したホワイト ノイズをオーディオ信号に追加して、結果の信号をスピーカーに出力します。

モデルをシミュレートするには、次の手順に従います。

  1. Simulink で acoustic_environment モデルを開きます。

    1. MATLAB の現在のフォルダーを、このチュートリアルの作業ファイルを含むフォルダーに設定します。MATLAB コマンド ラインで以下のように入力します。

      cd work
      ここで、work はユーザーのファイルを含むフォルダーの絶対パス名です。詳細については、ファイルやフォルダーの検索を参照してください。

    2. MATLAB コマンド ラインで以下のように入力します。

      acoustic_environment

  2. スピーカーがオンになっていることを確認します。

  3. モデルをシミュレートするには、Simulink モデル ウィンドウで [実行] をクリックします。

    Simulink でモデルを実行すると、ノイズによって歪んだオーディオ信号が聞こえます。

  4. シミュレーションの実行中、Manual Switch をダブルクリックしてオーディオ ソースを選択します。

    これで、ノイズなしで目的のオーディオ入力が聞こえます。

このチュートリアルの目標は、MATLAB LMS フィルター アルゴリズムを使用してノイズを含むオーディオ信号からノイズを排除することです。これは、MATLAB Function ブロックをモデルに追加し、このブロックから MATLAB コードを呼び出すことによって行います。

MATLAB Function ブロックのモデルへの追加

モデルとコードを自分で変更するには、このセクションの演習を行ってください。演習を省略する場合は、solutions サブフォルダーの指定のモデル noise_cancel_01 を開いて、変更されたモデルを表示してください。

このチュートリアルの目的上、チュートリアルに付属の noise_cancel_00 モデルに MATLAB Function ブロックを追加します。実際には、空の Simulink モデルから開始して独自のテスト ベンチを開発しなければなりません。

noise_cancel_00 モデルに MATLAB Function ブロックを追加するには、次の手順に従います。

  1. Simulink で noise_cancel_00 を開きます。

    noise_cancel_00

  2. MATLAB Function ブロックをモデルに追加します。

    1. MATLAB コマンド ラインで「slLibraryBrowser」と入力して Simulink ライブラリ ブラウザーを開きます。

    2. Simulink ライブラリのリストから User-Defined Functions ライブラリを選択します。

    3. MATLAB Function ブロックをクリックして noise_cancel_00 モデルにドラッグします。赤い注釈テキスト Place MATLAB Function Block here のすぐ上にブロックを配置します。

    4. 赤い注釈テキストをモデルから削除します。

    5. 現在のフォルダーにモデルを noise_cancel_01 として保存します。

       ベスト プラクティス - インクリメンタルなコード更新の保存

ラピッド プロトタイピングのための外部関数としての MATLAB コードの呼び出し

チュートリアルのこの部分では、関数 coder.extrinsic を使用して、ラピッド プロトタイピングのために MATLAB Function ブロックから MATLAB コードを呼び出します。

MATLAB コードを外部関数として呼び出す理由。-  MATLAB コードを外部関数として呼び出すことには次の利点があります。

  • ラピッド プロトタイピングの場合、MATLAB コードをコード生成に適したものにする必要はありません。

  • coder.extrinsic を使用すると、MATLAB で MATLAB コードをデバッグできます。lms_01.m ファイルで 1 つ以上のブレークポイントを追加した後、Simulink でシミュレーションを開始できます。MATLAB 実行エンジンはブレークポイントに達すると、一時的に実行を停止して、ユーザーが MATLAB ワークスペースを調べてメモリ内のすべての変数の現在の値を確認できるようにします。MATLAB コードのデバッグに関する詳細は、MATLAB プログラムのデバッグを参照してください。

MATLAB コードを外部関数として呼び出す方法-   MATLAB Function ブロックから MATLAB コードを呼び出すには、次の手順に従います。

  1. MATLAB Function ブロックをダブルクリックして MATLAB Function ブロック エディターを開きます。

  2. MATLAB Function ブロック エディターに表示された既定のコードを削除します。

  3. 次のコードを MATLAB Function ブロックにコピーします。

    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

     チルダ (~) 演算子を使用する理由

  4. モデルを保存します。

    関数 lms_01 の入力 Noise_InSignal_In は、ブロックへの入力端子として表示され、Signal_OutWeights は出力端子として表示されるようになります。

MATLAB Function ブロックの入力と出力の接続

  1. モデルが次のようになるように、MATLAB Function ブロックの入力と出力を接続します。

  2. MATLAB Function ブロック コードで、外部呼び出しの後に次のコードを追加することにより、出力をあらかじめ割り当てます。

    % Outputs:
    Signal_Out = zeros(size(Signal_In));
    Weights = zeros(32,1);
    Weights のサイズは、Acoustic Environment サブシステムの Digital Filter の分子係数と一致するように設定されます。

     出力をあらかじめ割り当てる理由

     変更した MATLAB Function ブロック コード

  3. モデルを保存します。

    これで、モデルのエラーを確認する準備ができました。

noise_cancel_01 モデルのシミュレーション

モデルをシミュレートするには、次の手順に従います。

  1. [時間領域] プロットを表示できることを確認します。

    プロットを表示するには、noise_cancel_01 モデルで Analysis and Visualization ブロックを開いてから、Time Domain ブロックを開きます。

  2. Simulink モデル ウィンドウで [実行] をクリックします。

    Simulink でモデルが実行されると、出力が表示され、聞こえます。最初は、ノイズによって歪んだオーディオ信号が聞こえます。次にフィルターによってノイズが徐々に減衰され、残ったノイズはほとんどなくなり、音楽のみが聞こえるようになります。2 秒経つと、ノイズを含む歪んだ信号が再度聞こえますが、ノイズはフィルターによって再度減衰されます。このサイクルは連続的に繰り返されます。

    MATLAB はこのサイクルを表示する次のプロットを表示します。

  3. シミュレーションを停止します。

 フィルターが 2 秒ごとにリセットされる理由

ストリーミングを使用するためのフィルターの変更

ストリーミングとは-  ストリーミング フィルターは、入力データの固定サイズのチャンク、または "フレーム" の処理のため、入力信号全体が処理されるまで繰り返し呼び出されます。フレーム サイズは 1 つの信号サンプルのように小さい場合もあり、その場合、フィルターはサンプルベース モードで実行されます。またフレームベースの処理では、最大数千個のサンプルを処理できます。

ストリーミングを使用する理由-  lms_01 のフィルター アルゴリズムの設計には、次のような欠点があります。

  • アルゴリズムがメモリを効率的に使用しない。

    プログラムの存続期間中、入力信号ごとに固定量のメモリをあらかじめ割り当てる場合、使用中のメモリ量よりも多くのメモリが割り当てられることになります。

  • この関数を呼び出す前に入力信号のサイズがわかっている必要がある。

    入力信号がリアルタイムで受信される場合、またはサンプルのストリームとして受信される場合、信号全体が累積されるのを待ってからそれをバッチとしてフィルターに渡します。

  • 信号サイズが任意の最大サイズに制限される。

組み込みアプリケーションでは、フィルターは連続した入力ストリームを処理している可能性があります。その結果、入力信号はバッチ モードで機能しているフィルターが処理できる最大長よりもはるかに長くなる場合があります。信号長にかかわらずフィルターが機能するためには、リアルタイムで実行しなければなりません。この解決策の 1 つは、フィルターをバッチベースの処理からストリームベースの処理に変換することです。

変更された MATLAB コードの表示-  ストリーミングへの変換には以下が必要です。

  • 先入れ先出し (FIFO) キューの導入

    FIFO キューは、入力データ ストリームからの少数のサンプルを保管する一時的なストレージ バッファーとして機能します。関数がフィルター係数と入力信号間で畳み込み操作を実行できるように、FIFO キューに保管するサンプル数はフィルターのインパルス応答のサンプル数と同じでなければなりません。

  • FIFO キューとフィルターの重みを persistent に指定

    フィルターは、入力信号全体を処理するまで、繰り返し呼び出されます。したがって、その後関数が呼び出されるたびに適応プロセスが最初から開始されることがないように、FIFO キューとフィルターの重みは persistent にしなければなりません。

work サブフォルダーの指定のファイル lms_02.m を開いて、変更されたアルゴリズムを表示してください。

 lms_02.m の内容

フィルター アルゴリズムへの変更内容のまとめ-  フィルター アルゴリズムについて次の重要な変更事項に注意してください。

  • フィルターの重みと FIFO キューは persistent として宣言されます。

    persistent weights;
    persistent fifo;

  • FIFO キューが初期化されます。

    fifo = zeros(FilterLength,ChannelCount);

  • FIFO キューはフィルター更新ループで使用されます。

    % For each channel:
    for ch = 1:ChannelCount
                
       % For each sample time:
       for n = 1:FrameSize
                    
         % Update the FIFO shift register:
         fifo(1:FilterLength-1,ch) = fifo(2:FilterLength,ch);
         fifo(FilterLength,ch) = signal_in(n,ch);
                    
         % Compute the output sample using convolution:
         signal_out(n,ch) = weights' * fifo(:,ch);
    
         % Update the filter coefficients:
         err(n,ch) = desired(n,ch) - signal_out(n,ch) ;
         weights = weights + mu*err(n,ch)*fifo(:,ch);
                    
       end
    end

  • 永続変数は出力できません。そのため、フィルターの重みの出力には新しい変数 weights_out が使用されます。

    function [ signal_out, err, weights_out ] = ...
      lms_02(distorted, desired)
    weights_out = weights;

更新されたアルゴリズムを呼び出すためのモデルの変更-  モデルを自分で変更するには、このセクションの演習を行ってください。演習を省略する場合は、solutions サブフォルダーの指定のモデル noise_cancel_02 を開いて、変更されたモデルを表示してください。

  1. noise_cancel_01 モデルで、MATLAB Function ブロックをダブルクリックして、MATLAB Function ブロック エディターを開きます。

  2. lms_02 を呼び出すように MATLAB Function ブロック コードを変更します。

    1. 外部呼出しを変更します。

      % Extrinsic:
      coder.extrinsic('lms_02');

    2. フィルター アルゴリズムの呼び出しを変更します。

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

       変更した MATLAB Function ブロック コード

  3. フレーム サイズを 16384 から、より現実的な値を表す 64 に変更します。

    1. モデル ウィンドウ内で右クリックし、[モデル プロパティ] を選択します。

    2. [コールバック] タブを選択します。

    3. [モデルのコールバック] リストから InitFcn を選択します。

    4. FrameSize の値を 64 に変更します。

    5. [適用] をクリックしてダイアログ ボックスを閉じます。

  4. モデルを noise_cancel_02 として保存してください。

ストリーミング アルゴリズムのシミュレーション-  モデルをシミュレートするには、次の手順に従います。

  1. [時間領域] プロットを表示できることを確認します。

  2. シミュレーションを開始します。

    Simulink でモデルが実行されると、出力が表示され、聞こえます。最初は、ノイズによって歪んだオーディオ信号が聞こえます。その後、最初の数秒はフィルターによってノイズが徐々に減衰され、残ったノイズはほとんどなくなり、音楽のみが聞こえるようになります。MATLAB によって、わずか数秒後のフィルターの収束を示す次のプロットが表示されます。

  3. シミュレーションを停止します。

これで、フィルター アルゴリズムは Simulink にも適するようになります。Adapt コントロールと Reset コントロールを使用するように、モデルを詳しく設定できます。

Adapt コントロールと Reset コントロールの追加

Adapt コントロールと Reset コントロールを追加する理由-  チュートリアルのこの部分では、フィルターに Adapt コントロールと Reset コントロールを追加します。これらのコントロールを使用すると、フィルター処理のオン/オフを切り替えることができます。Adapt が有効な場合、フィルターはフィルターの重みを連続的に更新します。Adapt が無効な場合、フィルターの重みは現在の値のままになります。Reset が設定されている場合、フィルターはフィルターの重みをリセットします。

MATLAB コードの変更-  コードを自分で変更するには、このセクションの演習を行ってください。演習を省略する場合は、solutions サブフォルダーの指定のファイル lms_03.m を開いて、変更されたアルゴリズムを表示してください。

フィルター コードを変更するには、次の手順に従います。

  1. lms_02.m を開きます。

  2. Set up セクションで、次のコードを、

    if ( isempty(weights) )
    次に置き換えます。
    if ( reset || isempty(weights) )

  3. フィルター ループでは、AdaptON の場合にのみフィルター係数を更新します。

    if adapt
      weights = weights + mu*err(n,ch)*fifo(:,ch);
    end

  4. Adapt 入力および Reset 入力を使用するように関数シグネチャを変更し、関数名を lms_03 に変更します。

    function [ signal_out, err, weights_out ] = ...
      lms_03(signal_in, desired, reset, adapt)

  5. 現在のフォルダーにファイルを lms_03.m として保存します。

 lms_03.m の内容

 フィルター アルゴリズムへの変更内容のまとめ

Reset コントロールと Adapt コントロールを使用するためのモデルの変更-  モデルを自分で変更するには、このセクションの演習を行ってください。演習を省略する場合は、solutions サブフォルダーの指定のモデル noise_cancel_03 を開いて、変更されたモデルを表示してください。

  1. noise_cancel_02 モデルを開きます。

  2. MATLAB Function ブロックをダブルクリックして MATLAB Function ブロック エディターを開きます。

  3. MATLAB Function ブロック コードを変更します。

    1. 関数宣言を更新します。

      function [ Signal_Out, Weights ] = ...
         LMS(Adapt, Reset, Noise_In, Signal_In )
    2. 外部呼出しを更新します。

      coder.extrinsic('lms_03');

    3. LMS アルゴリズムの呼び出しを更新します。

      % Compute LMS:
      [ ~, Signal_Out, Weights ] = ...
         lms_03(Noise_In, Signal_In, Reset, Adapt);

    4. MATLAB Function ブロック エディターの終了

      関数 lms_03 の入力 ResetAdaptMATLAB Function ブロックの入力端子として表示されるようになります。

  4. design_templates モデルを開きます。

  5. Settings ブロックをこのモデルから noise_cancel_02 モデルにコピーします。

    1. design_templates モデル メニューで [エディット][すべて選択] を選択します。

    2. [編集][コピー] を選択します。

    3. noise_cancel_02 モデル メニューで [エディット][貼り付け] を選択します。

  6. Settings サブシステムの Adapt および Reset の出力を MATLAB Function ブロックの対応する入力に接続します。これでモデルは次のようになります。

  7. モデルを noise_cancel_03 という名前で保存します。

Adapt コントロールと Reset コントロールを使用したモデルのシミュレーション-  モデルをシミュレートして Adapt コントロールおよび Reset コントロールの影響を確認するには、次の手順に従います。

  1. noise_cancel_03 モデルで収束範囲を表示します。

    1. Analysis and Visualization サブシステムをダブルクリックします。

    2. 収束範囲をダブルクリックします。

  2. Simulink モデル ウィンドウで [実行] をクリックします。

    Simulink によりモデルが以前のように実行されます。モデルの実行中、Adapt コントロールと Reset コントロールを切り替え、収束範囲を表示してフィルターへの影響を確認します。

    フィルターは AdaptONResetOFF のときに収束し、Reset を切り替えるときにリセットします。この結果は、次のようになります。

  3. シミュレーションを停止します。

コードの生成

アルゴリズムが Simulink で機能することが実証されました。次に、モデルのコードを生成します。コードを生成する前に、MATLAB コードがコード生成に適していることを確認しなければなりません。コード生成のためには、コードの外部呼出しを削除しなければなりません。

コードをコード生成に適したものにする-  モデルとコードを自分で変更するには、このセクションの演習を行ってください。演習を省略する場合は、solutions サブフォルダーの指定のモデル noise_cancel_04lms_04.m ファイルを開いて、変更内容を表示してください。

  1. MATLAB Function ブロックの名前を LMS_Filter に変更します。MATLAB Function ブロックの下にある注釈 MATLAB Function を選択し、テキストを LMS_Filter に置き換えます。

    MATLAB Function ブロックに対してコードを生成する場合、Simulink Coder では生成コードでブロックの名前を使用します。意味のある名前を使用することを実践してください。

  2. noise_cancel_03 モデルで、MATLAB Function ブロックをダブルクリックします。

    MATLAB Function ブロック エディターが開きます。

  3. 外部宣言を削除します。

    % Extrinsic:
    coder.extrinsic('lms_03');

  4. 出力の事前割り当てを削除します。

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

  5. フィルター アルゴリズムの呼び出しを変更します。

    % Compute LMS:
    [ ~, Signal_Out, Weights ] = ...
       lms_04(Noise_In, Signal_In, Reset, Adapt);

  6. モデルを noise_cancel_04 という名前で保存します。

  7. lms_03.m を開きます。

    1. 関数名を lms_04 に変更します。

    2. 関数の宣言の後に %#codegen コンパイル命令を追加して、コード生成固有のエラー チェックをオンにします。

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

      右上のコード アナライザーのメッセージ インジケーターが赤になり、コード アナライザーでコード生成の問題が検出されたことを示します。コード アナライザーは、問題のあるコードに赤でアンダースコアを引き、その右側に赤のマーカーを表示します。

  8. エラー情報を表示するには、ポインターを最初の赤いマーカーに移動します。

    コード アナライザーは、コード生成には添字をつける前に signal_out が完全に定義されていることが必要であること、およびインデックスによる可変サイズ データの増加がサポートされていないことを検知します。

  9. ポインターを 2 番目の赤いマーカーに移動し、コード アナライザーが err についても同じエラーを検出することを確認します。

  10. これらのエラーに対処するには、出力 signal_outerr をあらかじめ割り当てます。フィルター設定の後に次のコードを追加します。

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

     出力をあらかじめ割り当てる理由

    コードの 2 行の赤のエラー マーカーが消えます。コードの右上縁のコード アナライザー メッセージ インジケーターが緑色になります。これは、コード アナライザーで検出されたすべてのエラーと警告が修正されたことを意味します。

     lms_04.m の内容

  11. ファイルを lms_04.m として保存します。

noise_cancel_04 のコードの生成

  1. コードを生成する前に、Simulink Coder でコード生成レポートが作成されることを確認してください。この HTML レポートでは、コードの生成に使用したコンフィギュレーション設定のまとめを含む生成ファイルのリストに簡単にアクセスできます。

    1. Simulink モデル ウィンドウの [モデル化] タブで、[モデル設定] をクリックします。

    2. [コンフィギュレーション パラメーター] ダイアログ ボックスの左ペインで、[コード生成][レポート] を選択します。

    3. 右側のペインで、[コード生成レポートを作成][レポートを自動的に開く] を選択します。

    4. [適用] をクリックして [コンフィギュレーション パラメーター] ダイアログ ボックスを閉じます。

    5. モデルを保存します。

  2. LMS Filter サブシステムに対するコードを生成するには、次の手順に従います。

    1. モデルで、LMS Filter サブシステムを選択します。

    2. [モデルのビルド] ツール メニューから、[Build Selected Subsystem] を選択します。

      [サブシステムに対するコードをビルド] ダイアログ ボックスが表示されます。[ビルド] ボタンをクリックします。

      Simulink Coder ソフトウェアにより、サブシステムに対する C コードが生成され、コード生成レポートが開きます。

      コード生成レポートの使用方法の詳細については、コード生成レポートの生成 (Simulink Coder)を参照してください。

    3. コード生成レポートの左ペインで、LMS_Filter.c リンクをクリックして、生成された C コードを表示します。既定の設定ではインライン化が有効になっているため、関数 lms_04 にはコードがないことに注意してください。

  3. フィルター アルゴリズムを変更してインライン化を無効にします。

    1. lms_04.m で、関数宣言の後に次のコードを追加します。

      coder.inline('never')

    2. 関数名を lms_05 に変更し、現在のフォルダーにファイルを lms_05.m として保存します。

    3. noise_cancel_04 モデルで、MATLAB Function ブロックをダブルクリックします。

      MATLAB Function ブロック エディターが開きます。

    4. lms_05 を呼び出すようにフィルター アルゴリズムの呼び出しを変更します。

      % Compute LMS:
      [ ~, Signal_Out, Weights ] = ...
         lms_05(Noise_In, Signal_In, Reset, Adapt);

    5. モデルを noise_cancel_05 という名前で保存します。

  4. 更新されたモデルのコードを生成します。

    1. モデルで、LMS Filter サブシステムを選択します。

    2. [モデルのビルド] ツール メニューから、[Build Selected Subsystem] を選択します。

      [サブシステムに対するコードをビルド] ダイアログ ボックスが表示されます。

    3. [ビルド] ボタンをクリックします。

      Simulink Coder ソフトウェアにより、サブシステムに対する C コードが生成され、コード生成レポートが開きます。

    4. コード生成レポートの左ペインで、LMS_Filter.c リンクをクリックして、生成された C コードを表示します。

      今度は、インライン化を無効にしてあるので lms_05 関数にはコードがあります。

      /* 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])
      

LMS フィルター アルゴリズムの最適化

チュートリアルのこの部分では、生成コードでのメモリの初期化時にオーバーヘッドを発生させることなく、変数のメモリの事前割り当てをいつどのように行うかを説明します。

lms_05.m では、MATLAB コードは signal_outerr を 実数の double の FrameSizeChannelCount 列のベクトルとして宣言するだけではなく、signal_outerr の各要素を 0 に初期化します。これらの信号は、生成された C コードでは 0 に初期化されます。

MATLAB コード生成した C コード
% 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 }

signal_outerr はどちらも、読み込み前に MATLAB コードで明示的に初期化されるため、この強制初期化は不要です。

メモ

変数 weightsfifo を宣言する場合は、coder.nullcopy を使用しないでください。これらの変数は生成コードで初期化されなければなりません。どちらの変数も読み込み前に MATLAB コードで明示的に初期化されません。

coder.nullcopy は、signal_outerr の宣言で使用して、生成コードでのメモリの不要な初期化を排除します。

  1. lms_05.m で、coder.nullcopy を使用して signal_outerr を事前に割り当てます。

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

    注意

    coder.nullcopy で変数を宣言したら、それを読み込む前に MATLAB コードでこの変数を明示的に初期化しなければなりません。これをしないと、予期しない結果が発生する場合があります。

  2. 関数名を lms_06 に変更し、現在のフォルダーにファイルを lms_06.m として保存します。

  3. noise_cancel_05 モデルで、MATLAB Function ブロックをダブルクリックします。

    MATLAB Function Block エディターが開きます。

  4. フィルター アルゴリズムの呼び出しを変更します。

    % Compute LMS:
    [ ~, Signal_Out, Weights ] = ...
       lms_06(Noise_In, Signal_In, Reset, Adapt);

  5. モデルを noise_cancel_06 という名前で保存します。

更新されたモデルのコードを生成します。

  1. LMS Filter サブシステムを選択します。

  2. [モデルのビルド] ツール メニューから、[Build Selected Subsystem] を選択します。

    [サブシステムに対するコードをビルド] ダイアログ ボックスが表示されます。[ビルド] ボタンをクリックします。

    Simulink Coder ソフトウェアにより、サブシステムに対する C コードが生成され、コード生成レポートが開きます。

  3. コード生成レポートの左ペインで、LMS_Filter.c リンクをクリックして、生成された C コードを表示します。

    今度は、生成した C コードに signal_outerr の 0 への初期化はありません。

参考

関連する例

詳細