##はじめに
MATLABでMIDI音源が鳴らせるなら、Simulinkでも鳴るはず。ということで、以下その手順を概説します。
##MIDI再生用Cプログラム
Simulinkには、MIDIを再生する機能はありませんので、MIDI再生用Cプログラムを、Simulinkで実行できる形式にコンパイルし、Simulinkブロックを自作します。以下がCプログラムです。使用コマンドの概説は、MATLABでMIDI音源を鳴らすにあります。
#include <stdio.h>
#include "stdafx.h"
#include <Windows.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
int miditest(int pitch, int duration, int velocity, int timbre)
{
HMIDIOUT hmo; // MIDI out handle
// int pitch; // 音程(0~127: C-1~G9)
// int duration; // 音の長さ(msec)
// int velocity; // ベロシティ(音量)
// int timbre; // 音色
midiOutOpen(&hmo, MIDI_MAPPER, 0, 0, 0); // MIDIデバイスオープン
midiOutShortMsg(hmo, 0xC0 | (timbre << 8)); // 0xC*: プログラムチェンジ
midiOutShortMsg(hmo, 0x90 | (velocity << 16) | (pitch << 8)); // 0x90: ノートオン
Sleep(duration);
midiOutShortMsg(hmo, 0x80 | (pitch << 8)); // 0x80: ノートオフ
midiOutClose(hmo); // MIDIデバイスクローズ
return 0;
}
##コンパイル(Simulinkブロックの作成)
以下は、MATLAB環境でSimulink用ブロックを自動生成するためのスクリプトです。Legacy Code Toolという機能を使用し、C言語ベースのプログラムをコンパイルして、Simulinkブロックを作成します。
%% 初期化
s = legacy_code('initialize');
%% S-Function名
s.SFunctionName = 'sfun_slMIDI';
%% 関数の入出力形式
s.OutputFcnSpec = 'int32 y1 = miditest(int32 u1,int32 u2,int32 u3,int32 u4)';
%% ソースファイル名
s.SourceFiles = {'slMIDI.c'};
%% S-Function用Cファイル
legacy_code('sfcn_cmex_generate', s);
%% コンパイル
legacy_code('compile', s);
%% ブロック自動作成
legacy_code('slblock_generate', s);
上記スクリプトの最後の処理(legacy_code('slblock_generate', s);)を実行すると、4入力1出力のSimulinkブロックが自動生成されます。
##Simulinkモデルの作成
自動生成されたブロックを用いて、簡単なモデルを作成しました。第一入力は音程、第二入力は音の長さ、第三引数は音量、第四引数は音色です。ここでは、カウンタブロックを使って、第一引数に60~71までの値を順次入力し、半音ずつオクターブの再生をしています。
##まとめ
Simulink環境でもMIDI音源を鳴らすことができました。Legacy Code Toolを使うと、簡単に既存のCコードをSimulink環境に取り込むことができます。