〜 メディア 〜
MIDI音源で音を出力 (要WINMM.DLL)

MIDI出力デバイスにメッセージを送信することで音を奏でることが可能です。
まずAPImidiOutOpenでMIDI出力デバイスを開きます。
無事に開けたか否かは戻り値が0かどうかで判断してください。
定数定数値内容
MMSYSERR_NOERROR0x0000処理成功
MMSYSERR_BADDEVICEID0x0002デバイス識別子は範囲外
MMSYSERR_ALLOCATED0x0004リソースは既に割り当てられている
MMSYSERR_NOMEM0x0007メモリを割り当てられないか、ロックできない
MMSYSERR_INVALPARAM0x000B指定されたポインタまたは構造体は無効
MIDIERR_NODEVICE0x0044MIDIポートが見つからない
開けたら、APImidiOutShortMsgで以下に示すメッセージ内容を指定します。 メッセージ内容はステータスバイト(メッセージ値、チャンネル番号)とデータバイトの 3バイト長ショートメッセージとなっており、MCIの文字列コマンドのように 数値コマンドで「鍵盤を押す」「鍵盤を離す」「音色を変える」等の処理を行います。 音の出力時のメッセージは「[V][V][N][N][9][C](16)」形式で、 上位1バイト[V]は音の強度(ベロシティ)で128段階、次の1バイト[N]は鍵盤(ノート)で128段階、 下位1バイトの上位4ビットは音発生時[9]になり、下位4ビット[C]はチャンネル16和音となっています。 「鍵盤を押す」コマンド1つにしても、文字列コマンドよりもわかりにくいので、 下記サンプルでは簡単に指定できるMIDI共通モジュールとしました。 下記サンプルではピアノ音源を使用しているため、鍵盤を押しただけでも徐々に消音しますが、 音色によっては、鍵盤を離す処理をしなければいつまでも鳴り続けてしまうものがあります。 ピアノの場合でも自然消音音ではなく確実に消すは強度パラメータに0を送りましょう。 尚、強さ0による強制消音で効果のあるのは「指定チャンネル」の「指定鍵盤」だけです。 複数チャンネルを使用している場合、または同一チャンネルで複数音が鳴っているのを全て消音したい時、 コチラのサンプルを併せて利用してみてください。 チャンネルは既に書いたように0〜15の16個を同時に使用できるのですが、 チャンネル9だけはパーカッション(リズム)専用チャンネルとなっています。 リズム用チャンネルには音階はなく、他チャンネルで言うところの音階変更を行うと、 使用するリズム用の打楽器(音色)が別のものとなります。いろいろと変更してみてください。 APImidiOutShortMsgが成功したか否かは戻り値が0かどうかで判断してください。
定数定数値内容
MMSYSERR_NOERROR0x0000処理成功
MMSYSERR_INVALHANDLE0x0005デバイスハンドルは無効
MIDIERR_NOTREADY0x0043他のデータを処理中
MIDIERR_BADOPENMODE0x0046状態バイトのないメッセージがストリームハンドルに送信された
使用後はAPImidiOutCloseでデバイスを解放してください。 無事に解放できたか否かは戻り値が0かどうかで判断してください。
定数定数値内容
MMSYSERR_NOERROR0x0000処理成功
MMSYSERR_INVALHANDLE0x0005デバイスハンドルは無効
MMSYSERR_NOMEM0x0007マッパー文字列記述をロードできない
MMSYSERR_NOTSUPPORTED0x0041バッファはまだキューにあります

midiopen
[パラメータなし]MIDIデバイスを使用可能状態にするだけのため、パラメータは必要ない。
尚、下記midisetkey命令内でデバイスチェックしているので命令を実行する必要はない。

midisetkey 鍵盤, 強さ, チャンネル
鍵盤使用する鍵盤(但し、チャンネル9だけはリズム楽器)を指定する。
尚、低い「ド」を0としており、指定可能値は−60〜67である。
強さ鍵盤を押す強さを0〜127で指定する。尚、強さ0は無音を指す。
チャンネル使用チャンネルを0〜15のいずれかで指定する。

midiclose
[パラメータなし]MIDIデバイスを解放するだけのため、パラメータは必要ない。
尚、終了時に自動的に呼び出されるので命令を実行する必要はない。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
	ll_libload winmm, "winmm.dll"
	ll_getproc midiOutOpen, "midiOutOpen", winmm
	ll_getproc midiOutShortMsg, "midiOutShortMsg", winmm
	ll_getproc midiOutClose, "midiOutClose", winmm

#module
#deffunc midiopen
	ll_getptr midh : ll_ret ptr
	prm = ptr, -1, 0, 0, 0
	ll_callfunc prm, 4, midiOutOpen@ // MIDIデバイスオープン
	return

#deffunc midisetkey int, int, int
	mref key, 0 : mref velocity, 1 : mref channel, 2
	if midh = 0 : midiopen
	prm = midh, velocity * 0x10000 + 0x3C90 + (key * 0x100) + channel
	ll_callfunc prm, 2, midiOutShortMsg@ // 音を鳴らす
	return

#deffunc midiclose onexit
	if midh : ll_callfunc midh, 1, midiOutClose@ // MIDIデバイスクローズ
	return
#global

	sdim key, 8, 13
	key = "ド", "ド#", "レ", "レ#", "ミ", "ファ", "ファ#", "ソ", "ソ#", "ラ", "ラ#", "シ", "ド"
	push = 0, 2, 4, 5, 7, 9, 11, 12
	repeat 8
		tmp = push.cnt
		midisetkey tmp, 0x7F
		mes key.tmp
		wait 100
	loop
	stop

midiopen
[パラメータなし]MIDIデバイスを使用可能状態にするだけのため、パラメータは必要ない。
尚、下記midisetkey命令内でデバイスチェックしているので命令を実行する必要はない。

midisetkey 鍵盤, 強さ, チャンネル
鍵盤使用する鍵盤(但し、チャンネル9だけはリズム楽器)を指定する。
尚、低い「ド」を0としており、指定可能値は−60〜67である。
強さ鍵盤を押す強さを0〜127で指定する。尚、強さ0は無音を指す。
チャンネル使用チャンネルを0〜15のいずれかで指定する。

midiclose
[パラメータなし]MIDIデバイスを解放するだけのため、パラメータは必要ない。
尚、終了時に自動的に呼び出されるので命令を実行する必要はない。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#uselib "winmm.dll"
#func  global midiOutOpen "midiOutOpen" var, int, int, int, int
#func  global midiOutShortMsg "midiOutShortMsg" int, int
#func  global midiOutClose "midiOutClose" int

#module
#deffunc midiopen
	midiOutOpen midh, -1, 0, 0, 0 // MIDIデバイスオープン
	return

#deffunc midisetkey int key, int velocity, int channel
	if midh = 0 : midiopen
	midiOutShortMsg midh, velocity * 0x10000 + 0x3C90 + key * 0x100 + channel // 音を鳴らす
	return

#deffunc midiclose onexit
	if midh : midiOutClose midh // MIDIデバイスクローズ
	return
#global

	key = "ド", "ド#", "レ", "レ#", "ミ", "ファ", "ファ#", "ソ", "ソ#", "ラ", "ラ#", "シ", "ド"
	push = 0, 2, 4, 5, 7, 9, 11, 12
	foreach push
		midisetkey push.cnt, 0x7F
		mes key(push.cnt)
		wait 100
	loop