void _SendRaw(byte[] data, int startIndex, int length) { var hdrSize = Marshal.SizeOf(typeof(MIDIHDR)); var hdr = new MIDIHDR(); var handle = GCHandle.Alloc(data, GCHandleType.Pinned); try { hdr.lpData = new IntPtr(handle.AddrOfPinnedObject().ToInt64() + startIndex); hdr.dwBufferLength = hdr.dwBytesRecorded = (uint)(length); hdr.dwFlags = 0; _CheckOutResult(midiOutPrepareHeader(_handle, ref hdr, hdrSize)); while ((hdr.dwFlags & MHDR_PREPARED) != MHDR_PREPARED) { Thread.Sleep(1); } _CheckOutResult(midiOutLongMsg(_handle, ref hdr, hdrSize)); while ((hdr.dwFlags & MHDR_DONE) != MHDR_DONE) { Thread.Sleep(1); } _CheckOutResult(midiOutUnprepareHeader(_handle, ref hdr, hdrSize)); } finally { handle.Free(); } }
public void SendSysEx(byte[] data) { lock (this) { //Win32API.MMRESULT result; IntPtr ptr; var size = (uint)Marshal.SizeOf(typeof(MIDIHDR)); var header = new MIDIHDR { lpData = Marshal.AllocHGlobal(data.Length) }; for (var i = 0; i < data.Length; i++) { Marshal.WriteByte(header.lpData, i, data[i]); } header.dwBufferLength = data.Length; header.dwBytesRecorded = data.Length; header.dwFlags = 0; try { ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MIDIHDR))); } catch (Exception) { Marshal.FreeHGlobal(header.lpData); throw; } try { Marshal.StructureToPtr(header, ptr, false); } catch (Exception) { Marshal.FreeHGlobal(header.lpData); Marshal.FreeHGlobal(ptr); throw; } //result = Win32API.midiOutPrepareHeader(handle, ptr, size); //if (result == 0) result = Win32API.midiOutLongMsg(handle, ptr, size); //if (result == 0) result = Win32API.midiOutUnprepareHeader(handle, ptr, size); CheckReturnCode(Win32API.midiOutPrepareHeader(_handle, ptr, size)); CheckReturnCode(Win32API.midiOutLongMsg(_handle, ptr, size)); CheckReturnCode(Win32API.midiOutUnprepareHeader(_handle, ptr, size)); Marshal.FreeHGlobal(header.lpData); Marshal.FreeHGlobal(ptr); } }
internal MidiStream(int deviceIndex) { if (0 > deviceIndex) { throw new ArgumentOutOfRangeException("deviceIndex"); } _deviceIndex = deviceIndex; _handle = IntPtr.Zero; _sendHeader = default(MIDIHDR); _sendEventBuffer = IntPtr.Zero; _sendQueuePosition = 0; _outCallback = new MidiOutProc(_MidiOutProc); _timerCallback = new TimerProc(_TimerProc); _tempoSyncEnabled = 0; _tempoSyncMessageCount = 100; _tempoSyncMessagesSentCount = 0; }
/*private void SendLong_old( byte[] data ) { * MIDIHDR hdr = new MIDIHDR(); * GCHandle dataHandle = GCHandle.Alloc( data, GCHandleType.Pinned ); // monoでコンパイルできない * uint size = (uint)sizeof( MIDIHDR ); * try { * hdr.lpData = (byte*)dataHandle.AddrOfPinnedObject().ToPointer(); * hdr.dwBufferLength = (uint)data.Length; * hdr.dwFlags = 0; * win32.midiOutPrepareHeader( m_handle, ref hdr, size ); * while ( (hdr.dwFlags & win32.WHDR_PREPARED) != win32.WHDR_PREPARED ) { * Application.DoEvents(); * } * win32.midiOutLongMsg( m_handle, ref hdr, size ); * while ( (hdr.dwFlags & win32.WHDR_DONE) != win32.WHDR_DONE ) { * Application.DoEvents(); * } * win32.midiOutUnprepareHeader( m_handle, ref hdr, size ); * } finally { * dataHandle.Free(); * } * }*/ #endif private void SendLong(byte[] data) { #if !MONO IntPtr ptr = IntPtr.Zero; IntPtr ptrData = IntPtr.Zero; try { uint size = (uint)sizeof(MIDIHDR); ptr = Marshal.AllocHGlobal((int)size); MIDIHDR hdr = (MIDIHDR)Marshal.PtrToStructure(ptr, typeof(MIDIHDR)); ptrData = Marshal.AllocHGlobal(data.Length); byte *pData = (byte *)ptrData.ToPointer(); for (int i = 0; i < data.Length; i++) { pData[i] = data[i]; } hdr.lpData = pData; hdr.dwBufferLength = (uint)data.Length; hdr.dwFlags = 0; win32.midiOutPrepareHeader(m_handle, ref hdr, size); while ((hdr.dwFlags & win32.WHDR_PREPARED) != win32.WHDR_PREPARED) { Application.DoEvents(); } win32.midiOutLongMsg(m_handle, ref hdr, size); while ((hdr.dwFlags & win32.WHDR_DONE) != win32.WHDR_DONE) { Application.DoEvents(); } win32.midiOutUnprepareHeader(m_handle, ref hdr, size); } catch (Exception ex) { serr.println("MidiOutDevice#SendLong; ex=" + ex); } finally { if (ptrData != IntPtr.Zero) { Marshal.FreeHGlobal(ptrData); } if (ptr != IntPtr.Zero) { Marshal.FreeHGlobal(ptr); } } #endif }
public MidiInputLongDataBuffer(HMIDIIN inputHandle, int bufferSize = 4096) { _inputHandle = inputHandle; var header = new MIDIHDR() { lpData = Marshal.AllocHGlobal(bufferSize), dwBufferLength = (uint)bufferSize, }; try { Ptr = Marshal.AllocHGlobal(Marshal.SizeOf <MIDIHDR>()); Marshal.StructureToPtr(header, Ptr, false); } catch { Free(); throw; } }
private IntPtr CreateLongMsgBuffer() { //add a buffer so we can receive SysEx messages IntPtr ptr; var size = (uint)Marshal.SizeOf(typeof(MIDIHDR)); var header = new MIDIHDR { lpData = Marshal.AllocHGlobal(4096), dwBufferLength = 4096, dwFlags = 0 }; try { ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MIDIHDR))); } catch (Exception) { Marshal.FreeHGlobal(header.lpData); throw; } try { Marshal.StructureToPtr(header, ptr, false); } catch (Exception) { Marshal.FreeHGlobal(header.lpData); Marshal.FreeHGlobal(ptr); throw; } CheckReturnCode(Win32API.midiInPrepareHeader(_handle, ptr, size)); CheckReturnCode(Win32API.midiInAddBuffer(_handle, ptr, size)); //CheckReturnCode(Win32API.midiInUnprepareHeader(handle, ptr, size)); return(ptr); }
public static extern MmResult midiStreamOut(IntPtr hMidiStream, [MarshalAs(UnmanagedType.Struct)] ref MIDIHDR pmh, int cbmh);
public static extern MmResult midiOutLongMsg(IntPtr hMidiOut, [MarshalAs(UnmanagedType.Struct)] ref MIDIHDR lpMidiOutHdr, int uSize);
public static extern int midiStreamOut(int hms, ref MIDIHDR pmh, int cbmh);
public static extern int midiOutLongMsg(int hMidiOUT, ref MIDIHDR lpMidiOutHdr, int uSize);
public static extern int midiInAddBuffer(int hMidiIN, ref MIDIHDR lpMidiInHdr, int uSize);
static extern int midiInAddBuffer(IntPtr handle, ref MIDIHDR lpMidiHeader, int wSize);
static extern int midiOutUnprepareHeader(IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, int uSize);
public static extern MmResult midiInPrepareHeader(IntPtr hMidiIn, ref MIDIHDR lpMidiInHdr, int uSize);
public static extern uint UnprepareLongData(ref MIDIHDR IIMidiHdr);
public static extern uint SendDirectLongDataNoBuf(ref MIDIHDR IIMidiHdr);
internal static extern uint midiOutUnprepareHeader(IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, uint uSize);
internal static extern uint midiOutLongMsg(IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, uint uSize);
internal static extern uint midiOutPrepareHeader(IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, uint uSize);
public static extern int midiInUnprepareHeader(int hMidiIN, ref MIDIHDR lpMidiInHdr, int uSize);
public static extern MmResult midiOutLongMsg(IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, int uSize);
static extern int midiOutLongMsg(IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, int uSize);
public static extern MmResult midiOutUnprepareHeader(IntPtr hMidiOut, ref MIDIHDR lpMidiOutHdr, int uSize);
static extern int midiInUnprepareHeader(IntPtr handle, ref MIDIHDR lpMidiHeader, int wSize);
public static extern MmResult midiStreamOut(IntPtr hMidiStream, ref MIDIHDR pmh, int cbmh);
public static extern MmResult midiInAddBuffer(IntPtr hMidiIn, ref MIDIHDR lpMidiInHdr, int uSize);
public static extern int midiOutUnprepareHeader(int hMidiOUT, ref MIDIHDR lpMidiOutHdr, int uSize);
void _SendBlock() { if (null == _sendQueue) { return; } if (IntPtr.Zero == _handle) { throw new InvalidOperationException("The stream is closed."); } if (IntPtr.Zero != Interlocked.CompareExchange(ref _sendHeader.lpData, _sendEventBuffer, IntPtr.Zero)) { throw new InvalidOperationException("The stream is busy playing."); } int baseEventSize = Marshal.SizeOf(typeof(MIDIEVENT)); int blockSize = 0; IntPtr eventPointer = _sendEventBuffer; var ofs = 0; var ptrOfs = 0; for (; _sendQueuePosition < _sendQueue.Count; Interlocked.Exchange(ref _sendQueuePosition, _sendQueuePosition + 1)) { var @event = _sendQueue[_sendQueuePosition]; if (0x00 != @event.Message.Status && 0xF0 != (@event.Message.Status & 0xF0)) { if (_SendBufferSize < blockSize + baseEventSize) { break; } blockSize += baseEventSize; var se = new MIDIEVENT(); se.dwDeltaTime = @event.Position + ofs; se.dwStreamId = 0; se.dwEvent = MidiUtility.PackMessage(@event.Message); var gch = GCHandle.Alloc(se, GCHandleType.Pinned); CopyMemory(new IntPtr(ptrOfs + eventPointer.ToInt64()), gch.AddrOfPinnedObject(), Marshal.SizeOf(typeof(MIDIEVENT))); gch.Free(); ptrOfs += baseEventSize; ofs = 0; } else if (0xFF == @event.Message.Status) { var mm = @event.Message as MidiMessageMeta; if (0x51 == mm.Data1) // tempo { if (_SendBufferSize < blockSize + baseEventSize) { break; } blockSize += baseEventSize; var se = new MIDIEVENT(); se.dwDeltaTime = @event.Position + ofs; se.dwStreamId = 0; se.dwEvent = (mm.Data[0] << 16) | (mm.Data[1] << 8) | mm.Data[2] | (MEVT_TEMPO << 24); var gch = GCHandle.Alloc(se, GCHandleType.Pinned); CopyMemory(new IntPtr(ptrOfs + eventPointer.ToInt64()), gch.AddrOfPinnedObject(), Marshal.SizeOf(typeof(MIDIEVENT))); gch.Free(); ptrOfs += baseEventSize; ofs = 0; } else if (0x2f == mm.Data1) // end track { if (_SendBufferSize < blockSize + baseEventSize) { break; } blockSize += baseEventSize; // add a NOP message to it just to pad our output in case we're looping var se = new MIDIEVENT(); se.dwDeltaTime = @event.Position + ofs; se.dwStreamId = 0; se.dwEvent = (MEVT_NOP << 24); var gch = GCHandle.Alloc(se, GCHandleType.Pinned); CopyMemory(new IntPtr(ptrOfs + eventPointer.ToInt64()), gch.AddrOfPinnedObject(), Marshal.SizeOf(typeof(MIDIEVENT))); gch.Free(); ptrOfs += baseEventSize; ofs = 0; } else { ofs = @event.Position; } } else // sysex or sysex part { byte[] data; if (0 == @event.Message.Status) { data = (@event.Message as MidiMessageSysexPart).Data; } else { data = MidiUtility.ToMessageBytes(@event.Message); } var dl = data.Length; if (0 != (dl % 4)) { dl += 4 - (dl % 4); } if (_SendBufferSize < blockSize + baseEventSize + dl) { break; } blockSize += baseEventSize + dl; var se = new MIDIEVENT(); se.dwDeltaTime = @event.Position + ofs; se.dwStreamId = 0; se.dwEvent = MEVT_F_LONG | data.Length; var gch = GCHandle.Alloc(se, GCHandleType.Pinned); CopyMemory(new IntPtr(ptrOfs + eventPointer.ToInt64()), gch.AddrOfPinnedObject(), Marshal.SizeOf(typeof(MIDIEVENT))); gch.Free(); ptrOfs += baseEventSize; Marshal.Copy(data, 0, new IntPtr(ptrOfs + eventPointer.ToInt64()), data.Length); ptrOfs += dl; ofs = 0; } } _sendHeader = default(MIDIHDR); _sendHeader.dwBufferLength = _sendHeader.dwBytesRecorded = unchecked ((uint)blockSize); _sendHeader.lpData = _sendEventBuffer; int headerSize = Marshal.SizeOf(typeof(MIDIHDR)); _CheckOutResult(midiOutPrepareHeader(_handle, ref _sendHeader, headerSize)); _CheckOutResult(midiStreamOut(_handle, ref _sendHeader, headerSize)); }
/// <summary> /// Sends events directly to the event queue without buffering /// </summary> /// <param name="events">The events to send</param> /// <remarks>The total size of the events must be less than 64kb</remarks> public void SendDirect(IEnumerable <MidiEvent> events) { if (null == events) { throw new ArgumentNullException("events"); } if (IntPtr.Zero == _handle) { throw new InvalidOperationException("The stream is closed."); } if (IntPtr.Zero != _sendHeader.lpData) { throw new InvalidOperationException("The stream is busy playing."); } int baseEventSize = Marshal.SizeOf(typeof(MIDIEVENT)); int blockSize = 0; IntPtr eventPointer = _sendEventBuffer; var ofs = 0; var ptrOfs = 0; var hasEvents = false; foreach (var @event in events) { hasEvents = true; if (0xF0 != (@event.Message.Status & 0xF0)) { blockSize += baseEventSize; if (_SendBufferSize <= blockSize) { throw new ArgumentException("There are too many events in the event buffer - maximum size must be 64k", "events"); } var se = new MIDIEVENT(); se.dwDeltaTime = @event.Position + ofs; se.dwStreamId = 0; se.dwEvent = MidiUtility.PackMessage(@event.Message); Marshal.StructureToPtr(se, new IntPtr(ptrOfs + eventPointer.ToInt64()), false); ptrOfs += baseEventSize; ofs = 0; } else if (0xFF == @event.Message.Status) { var mm = @event.Message as MidiMessageMeta; if (0x51 == mm.Data1) // tempo { blockSize += baseEventSize; if (_SendBufferSize <= blockSize) { throw new ArgumentException("There are too many events in the event buffer - maximum size must be 64k", "events"); } var se = new MIDIEVENT(); se.dwDeltaTime = @event.Position + ofs; se.dwStreamId = 0; se.dwEvent = (mm.Data[0] << 16) | (mm.Data[1] << 8) | mm.Data[2] | (MEVT_TEMPO << 24); Marshal.StructureToPtr(se, new IntPtr(ptrOfs + eventPointer.ToInt64()), false); ptrOfs += baseEventSize; ofs = 0; // TODO: This signal is sent too early. It should really wait until after the // MEVT_TEMPO message is processed by the driver, but i have no easy way to // do that. All we can do is hope, here Interlocked.Exchange(ref _tempoSyncMessagesSentCount, 0); } else if (0x2f == mm.Data1) // end track { blockSize += baseEventSize; if (_SendBufferSize <= blockSize) { throw new ArgumentException("There are too many events in the event buffer - maximum size must be 64k", "events"); } // add a NOP message to it just to pad our output in case we're looping var se = new MIDIEVENT(); se.dwDeltaTime = @event.Position + ofs; se.dwStreamId = 0; se.dwEvent = (MEVT_NOP << 24); Marshal.StructureToPtr(se, new IntPtr(ptrOfs + eventPointer.ToInt64()), false); ptrOfs += baseEventSize; ofs = 0; } else { ofs = @event.Position; } } else // sysex { var msx = @event.Message as MidiMessageSysex; var dl = msx.Data.Length + 1; if (0 != (dl % 4)) { dl += 4 - (dl % 4); } blockSize += baseEventSize + dl; if (_SendBufferSize <= blockSize) { throw new ArgumentException("There are too many events in the event buffer - maximum size must be 64k", "events"); } var se = new MIDIEVENT(); se.dwDeltaTime = @event.Position + ofs; se.dwStreamId = 0; se.dwEvent = MEVT_F_LONG | (msx.Data.Length + 1); Marshal.StructureToPtr(se, new IntPtr(ptrOfs + eventPointer.ToInt64()), false); ptrOfs += baseEventSize; Marshal.WriteByte(new IntPtr(ptrOfs + eventPointer.ToInt64()), msx.Status); Marshal.Copy(msx.Data, 0, new IntPtr(ptrOfs + eventPointer.ToInt64() + 1), msx.Data.Length); ptrOfs += dl; ofs = 0; } } if (hasEvents) { _sendHeader = default(MIDIHDR); Interlocked.Exchange(ref _sendHeader.lpData, eventPointer); _sendHeader.dwBufferLength = _sendHeader.dwBytesRecorded = unchecked ((uint)blockSize); _sendEventBuffer = eventPointer; int headerSize = Marshal.SizeOf(typeof(MIDIHDR)); _CheckOutResult(midiOutPrepareHeader(_handle, ref _sendHeader, headerSize)); _CheckOutResult(midiStreamOut(_handle, ref _sendHeader, headerSize)); } }
public static extern MmResult midiOutUnprepareHeader(IntPtr hMidiOut, [MarshalAs(UnmanagedType.Struct)] ref MIDIHDR lpMidiOutHdr, int uSize);
static extern int midiStreamOut(IntPtr handle, ref MIDIHDR lpMidiOutHdr, int uSize);
public static extern MmResult midiInAddBuffer(IntPtr hMidiIn, [MarshalAs(UnmanagedType.Struct)] ref MIDIHDR lpMidiInHdr, int uSize);