lipsync/trunk/Boare.Lib.Media/MidiOutDevice.cs

85 lines
2.8 KiB
C#

/*
* MidiOutDevice.cs
* Copyright (c) 2009 kbinani
*
* This file is part of Boare.Lib.Media.
*
* Boare.Lib.Media is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.Media is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using bocoree;
namespace Boare.Lib.Media {
public unsafe class MidiOutDevice {
private IntPtr m_handle;
private uint m_device_id;
public MidiOutDevice( uint device_id ) {
m_device_id = device_id;
windows.midiOutOpen( ref m_handle, m_device_id, null, 0, windows.CALLBACK_NULL );
}
public void Close() {
if ( !m_handle.Equals( IntPtr.Zero ) ) {
windows.midiOutClose( m_handle );
}
}
public void ProgramChange( byte channel, byte program ) {
SendShort( new byte[] { (byte)(0xc0 | (channel & 0x0f)) , program, 0x0 } );
}
public void Play( byte channel, byte note, byte velocity ) {
SendShort( new byte[] { (byte)(0x90 | (channel & 0x0f)), note, velocity } );
}
public void SendData( byte[] data ) {
if ( 0 < data.Length && data.Length <= 4 ) {
SendShort( data );
} else {
SendLong( data );
}
}
private void SendShort( byte[] data ) {
uint message = 0;
for ( int i = 0; i < data.Length; i++ ) {
message |= ((uint)data[i]) << (i * 8);
}
windows.midiOutShortMsg( m_handle, message );
}
private void SendLong( byte[] data ) {
MIDIHDR hdr = new MIDIHDR();
GCHandle dataHandle = GCHandle.Alloc( data, GCHandleType.Pinned );
uint size = (uint)sizeof( MIDIHDR );
try {
hdr.lpData = (byte*)dataHandle.AddrOfPinnedObject().ToPointer();
hdr.dwBufferLength = (uint)data.Length;
hdr.dwFlags = 0;
windows.midiOutPrepareHeader( m_handle, ref hdr, size );
while ( (hdr.dwFlags & windows.WHDR_PREPARED) != windows.WHDR_PREPARED ) {
Application.DoEvents();
}
windows.midiOutLongMsg( m_handle, ref hdr, size );
while ( (hdr.dwFlags & windows.WHDR_DONE) != windows.WHDR_DONE ) {
Application.DoEvents();
}
windows.midiOutUnprepareHeader( m_handle, ref hdr, size );
} finally {
dataHandle.Free();
}
}
}
}