TNB Library
TnbMidi.h
[詳解]
1#pragma once
11#include "TnbSync.h"
12#include "TnbMciPlayer.h"
13#include <mmsystem.h>
14#pragma comment(lib, "winmm.lib")
15
16
17
18//TNB Library
19namespace TNB
20{
21
22
23
33{
34public:
35
37 CMidiMessage(void) : m_hMidi(NULL), m_lastError(MMSYSERR_NOERROR)
38 {
39 }
40
43 {
44 Close();
45 }
46
51 void Close(void)
52 {
53 if ( m_hMidi != NULL )
54 {
55 ::midiOutClose(m_hMidi);
56 m_hMidi = NULL;
57 }
58 }
59
67 bool Open(UINT dev = MIDI_MAPPER)
68 {
69 Close();
70 return m_Rst(::midiOutOpen(&m_hMidi, dev, NULL, 0, CALLBACK_NULL));
71 }
72
78 bool IsOpened(void) const
79 {
80 return m_hMidi != NULL;
81 }
82
91 bool ProgramChange(BYTE channel, BYTE programNumber)
92 {
93 return m_Rst(channel, TParam(Midi_ProgramChange, channel, programNumber));
94 }
95
106 bool BankSelect(BYTE channel, BYTE msb, BYTE lsb)
107 {
108 CWorkMemT<TParam> vp(2);
109 vp[0] = TParam(CCC_BackSelectMsb, channel, msb);
110 vp[1] = TParam(CCC_BackSelectLsb, channel, lsb);
111 return m_Rst(channel, vp);
112 }
113
122 bool Modulation(BYTE channel, BYTE modulation)
123 {
124 ASSERT ( modulation <= 127 );
125 return m_Rst(channel, TParam(CCC_Modulation, channel, modulation));
126 }
127
137 bool Volume(BYTE channel, int volume)
138 {
139 ASSERT ( volume >= 0 && volume <= 127 );
140 return m_Rst(channel, TParam(CCC_Volume, channel, down_cast<BYTE>(volume)));
141 }
142
151 bool Panpot(BYTE channel, int pan)
152 {
153 if ( pan < -63 )
154 {
155 pan = -63;
156 }
157 else if ( pan > 63 )
158 {
159 pan = 63;
160 }
161 return m_Rst(channel, TParam(CCC_Panpot, channel, down_cast<BYTE>(pan + 64)));
162 }
163
173 bool Expression(BYTE channel, int volume)
174 {
175 ASSERT ( volume >= 0 && volume <= 127 );
176 return m_Rst(channel, TParam(CCC_Expression, channel, down_cast<BYTE>(volume)));
177 }
178
188 bool ReverbSendLevel(BYTE channel, int level)
189 {
190 ASSERT ( level >= 0 && level <= 127 );
191 return m_Rst(channel, TParam(CCC_ReverbSendLevel, channel, down_cast<BYTE>(level)));
192 }
193
203 bool ChorusSendLevel(BYTE channel, int level)
204 {
205 ASSERT ( level >= 0 && level <= 127 );
206 return m_Rst(channel, TParam(CCC_ChorusSendLevel, channel, down_cast<BYTE>(level)));
207 }
208
219 bool ControlSendLevel(BYTE channel, BYTE controlNo, int level)
220 {
221 ASSERT ( level >= 0 && level <= 127 );
222 return m_Rst(channel, TParam(ECtrlChangeCode(controlNo), channel, down_cast<BYTE>(level)));
223 }
224
235 bool NoteOn(BYTE channel, BYTE note, BYTE velocity = 0)
236 {
237 ASSERT ( velocity <= 127 );
238 return m_Rst(channel, TParam(Midi_NoteOn, channel, note, velocity));
239 }
240
250 bool NoteOff(BYTE channel, BYTE note, BYTE velocity = 0)
251 {
252 ASSERT ( velocity <= 127 );
253 return m_Rst(channel, TParam(Midi_NoteOff, channel, note));
254 }
255
264 bool PitchBendChange(BYTE channel, int pitchBend = 0)
265 {
266 if ( pitchBend < -8192 )
267 {
268 pitchBend = -8192;
269 }
270 else if ( pitchBend > 8181 )
271 {
272 pitchBend = 8181;
273 }
274 int b = pitchBend + 8192;
275 BYTE msb = down_cast<BYTE>((b >> 7) & 0x7F);
276 BYTE lsb = down_cast<BYTE>((b ) & 0x7F);
277 return m_Rst(channel, TParam(Midi_PitchBendChange, channel, lsb, msb));
278 }
279
288 bool PitchBendSensitivity(BYTE channel, BYTE v)
289 {
290 ASSERT ( v <= 127 );
291 CWorkMemT<TParam> vp(6);
292 // ピッチベンドセンシビティ
293 vp[0] = TParam(CCC_RpnMsb, channel, 0);
294 vp[1] = TParam(CCC_RpnLsb, channel, 0);
295 // データエントリ
296 vp[2] = TParam(CCC_DataEntryMsb, channel, v);
297 vp[3] = TParam(CCC_DataEntryLsb, channel, 0);
299 vp[4] = TParam(CCC_RpnMsb, channel, 0x7F);
300 vp[5] = TParam(CCC_RpnLsb, channel, 0x7F);
301 return m_Rst(channel, vp);
302 }
303
304#if 0
305 bool OutMessage(size_t len, LPCVOID pMessage)
306 {
307 MIDIHDR hdr = { 0 };
309 mm.Reset(len, static_cast<const char*>(pMessage));
310 hdr.lpData = mm;
311 hdr.dwBufferLength = len;
312 hdr.dwBytesRecorded = len;
313 if ( ! m_Rst(::midiOutPrepareHeader(m_hMidi, &hdr, sizeof(MIDIHDR))) )
314 {
315 return false;
316 }
317 if ( ! m_Rst(::midiOutLongMsg(m_hMidi, &hdr, sizeof(MIDIHDR))) )
318 {
319 return false;
320 }
321 /* GMリセット完了待機 */
322 while ( (hdr.dwFlags & MHDR_DONE) == 0 )
323 {
324 ::Sleep(0);
325 }
326 return m_Rst(::midiOutUnprepareHeader(m_hMidi, &hdr, sizeof(MIDIHDR)));
327 }
328#endif
329
334 DWORD GetLastError(void) const
335 {
336 return m_lastError;
337 }
338
343 void SetLastError(DWORD e)
344 {
345 m_lastError = e;
346 }
347
353 static UINT GetDeviceCount(void)
354 {
355 return ::midiOutGetNumDevs();
356 }
357
363 static CStr GetErrorString(DWORD e)
364 {
365 CStr s;
366 if ( e != MMSYSERR_NOERROR )
367 {
368 ::midiOutGetErrorText(e, s.GetBuffer(1000), 1000);
369 s.ReleaseBuffer();
370 }
371 return s;
372 }
373
374private:
375
377 enum EMidiMessageKind
378 {
379 Midi_NoteOn = 0x9,
380 Midi_NoteOff = 0x8,
381 Midi_KeyPressure = 0xA,
382 Midi_CtrlChange = 0xB,
383 Midi_ProgramChange = 0xC,
384 Midi_ChannelPressure = 0xD,
385 Midi_PitchBendChange = 0xE,
386 };
387
389 enum ECtrlChangeCode
390 {
391 CCC_BackSelectMsb = 0x00,
392 CCC_BackSelectLsb = 0x20,
393 CCC_Modulation = 0x01,
394 CCC_Volume = 0x07,
395 CCC_Panpot = 0x0A,
396 CCC_Expression = 0x0B,
397 CCC_DataEntryMsb = 0x06,
398 CCC_DataEntryLsb = 0x26,
399 CCC_RpnMsb = 0x65,
400 CCC_RpnLsb = 0x64,
401 CCC_ReverbSendLevel = 0x5B,
402 CCC_TremoloDepth = 0x5C,
403 CCC_ChorusSendLevel = 0x5D,
404 CCC_VarSendLevel = 0x5E,
405 };
406
408 struct TParam
409 {
410 union {
411 struct {
412 union {
413 struct {
414 BYTE channel:4;
415 BYTE kind:4;
416 };
417 BYTE state;
418 };
419 BYTE data1;
420 BYTE data2;
421 BYTE padding;
422 };
423 DWORD msg;
424 };
425 TParam(EMidiMessageKind k, BYTE ch = 0, BYTE d1 = 0, BYTE d2 = 0)
426 : padding(0), kind(down_cast<BYTE>(k)), channel(ch), data1(d1), data2(d2)
427 {
428 }
429 TParam(ECtrlChangeCode ccc, BYTE ch = 0, BYTE d = 0)
430 : padding(0), kind(down_cast<BYTE>(Midi_CtrlChange)), channel(ch), data1(down_cast<BYTE>(ccc)), data2(d)
431 {
432 }
433 TParam(void) : msg(0)
434 {
435 }
436 };
437 friend struct CMidiMessage::TParam;
438 C_ASSERT( sizeof(TParam) == sizeof(DWORD) );
441 bool m_RstFx(MMRESULT r)
442 {
443 m_lastError = r;
444 return r == MMSYSERR_NOERROR;
445 }
447 bool m_Rst(MMRESULT r)
448 {
449 m_lastError = r;
450 if ( r != MMSYSERR_NOERROR )
451 {
452 TRACE2("MMRESULT = %d[%s]\n", r, GetErrorString(r));
453 }
454 return r == MMSYSERR_NOERROR;
455 }
457 bool m_Rst(BYTE channel, const TParam& p)
458 {
459 if ( channel > 15 )
460 {
461 return m_RstFx(MMSYSERR_BADERRNUM);
462 }
463 TTRACE3( "MIDI msg = %02X %02X %02X\n", p.state, p.data1, p.data2 );
464 return m_Rst(::midiOutShortMsg(m_hMidi, p.msg));
465 }
467 bool m_Rst(BYTE channel, const CWorkMemT<TParam>& vp)
468 {
469 loop ( i, vp.GetSize() )
470 {
471 if ( ! m_Rst(channel, vp[i]) )
472 {
473 return false;
474 }
475 }
476 return true;
477 }
478 HMIDIOUT m_hMidi;
479 mutable MMRESULT m_lastError;
480};
481
482
483
484}; //TNB
#define loop(VAR, CNT)
loop構文.
Definition: TnbDef.h:343
MCI 関係のヘッダ
同期処理関係のヘッダ
[ETC] コピー不可能スーパークラス.
Definition: TnbDef.h:599
MIDIメッセージクラス
Definition: TnbMidi.h:33
void SetLastError(DWORD e)
[設定] ラストエラーコード設定.
Definition: TnbMidi.h:343
bool ControlSendLevel(BYTE channel, BYTE controlNo, int level)
[設定] コントロールセンドレベル.
Definition: TnbMidi.h:219
static UINT GetDeviceCount(void)
[取得] デバイス数取得.
Definition: TnbMidi.h:353
bool Modulation(BYTE channel, BYTE modulation)
[設定] モジュレーション.
Definition: TnbMidi.h:122
bool BankSelect(BYTE channel, BYTE msb, BYTE lsb)
[設定] バンクセレクト.
Definition: TnbMidi.h:106
bool NoteOff(BYTE channel, BYTE note, BYTE velocity=0)
[設定] ノートオフ.
Definition: TnbMidi.h:250
bool ProgramChange(BYTE channel, BYTE programNumber)
[設定] プログラムチェンジ.
Definition: TnbMidi.h:91
bool ChorusSendLevel(BYTE channel, int level)
[設定] コーラスセンドレベル.
Definition: TnbMidi.h:203
static CStr GetErrorString(DWORD e)
[取得] エラー文字列取得.
Definition: TnbMidi.h:363
~CMidiMessage(void)
デストラクタ
Definition: TnbMidi.h:42
bool NoteOn(BYTE channel, BYTE note, BYTE velocity=0)
[設定] ノートオン.
Definition: TnbMidi.h:235
bool PitchBendSensitivity(BYTE channel, BYTE v)
[設定] ピッチベンドセンシビティ.
Definition: TnbMidi.h:288
bool Panpot(BYTE channel, int pan)
[設定] パンポット.
Definition: TnbMidi.h:151
bool Volume(BYTE channel, int volume)
[設定] ボリューム.
Definition: TnbMidi.h:137
bool IsOpened(void) const
[確認] オープン確認.
Definition: TnbMidi.h:78
void Close(void)
[設定] クローズ.
Definition: TnbMidi.h:51
bool PitchBendChange(BYTE channel, int pitchBend=0)
[設定] ピッチベンドチェンジ.
Definition: TnbMidi.h:264
bool Open(UINT dev=MIDI_MAPPER)
[設定] オープン.
Definition: TnbMidi.h:67
bool ReverbSendLevel(BYTE channel, int level)
[設定] リバーブセンドレベル.
Definition: TnbMidi.h:188
DWORD GetLastError(void) const
[取得] ラストエラーコード取得.
Definition: TnbMidi.h:334
bool Expression(BYTE channel, int volume)
[設定] エクスプレッション.
Definition: TnbMidi.h:173
CMidiMessage(void)
コンストラクタ
Definition: TnbMidi.h:37
void ReleaseBuffer(void)
[操作] 割り当てたバッファを開放.
Definition: TnbStr.h:954
TYP * GetBuffer(size_t iLength=0)
[操作] 書き込みバッファ要求.
Definition: TnbStr.h:914
ワークメモリテンプレート.
Definition: TnbDef.h:633
size_t GetSize(void) const
[取得] サイズ取得
Definition: TnbDef.h:665
void Reset(size_t l, const TYP *P)
[設定] 再設定
Definition: TnbDef.h:690
TNB Library
Definition: TnbDoxyTitle.txt:2