/* * 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(); } } } }