scott_bolland
New member
- Joined
- Jun 1, 2010
- Messages
- 1
- Programming Experience
- 10+
Hi guys,
please forgive me if I am writing to the wrong forum, but I am new here. Please feel free to redirect me elsewhere
Anyway, I am currently trying to program an interface with an interactive piano keyboard. That is, when the user clicks on a key, the appropriate note plays. Sounds simple enough. However, using standard midi dll calls (code appended below - I am using "note_on" when mouse button is pressed, and "note_off" when the button is released), there seems to be a variable delay (from nothing, to up to a couple of seconds) from when the interface is clicked and when the note actually plays. This does not seem to be a problem with the interface, as I update the image when these events happen, and the effect is instantaneous.
If anyone has any ideas how I can remedy the problem, or other approaches for playing midi in real time, I would love to hear it. Any assistance would be greatly appreciated.
Cheers,
Scott
---------------------------------------------------
Imports System.Runtime.InteropServices
Module MidiModule
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Structure MIDIOUTCAPS
Dim ManufacturerID As Short
Dim ProductID As Short
Dim DriverVersion As Integer
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=32)> _
Dim Label As String
Dim Technology As Short
Dim Voices As Short
Dim Notes As Short
Dim ChannelMask As Short
Dim Support As Integer
End Structure
Declare Function midiOutGetNumDevs Lib "winmm.dll" () As Integer
Declare Auto Function midiOutGetDevCaps Lib "winmm.dll" (ByVal uDeviceID As Integer, ByRef lpMidiOutCaps As MIDIOUTCAPS, ByVal cbMidiOutCaps As Integer) As Integer
Declare Function midiOutOpen Lib "winmm.dll" (ByRef lphmo As IntPtr, ByVal uDeviceID As Integer, ByVal dwCallback As Integer, ByVal dwCallbackInstance As Integer, ByVal dwFlags As Integer) As Integer
Declare Function midiOutClose Lib "winmm.dll" (ByVal hmo As IntPtr) As Integer
Declare Function midiOutShortMsg Lib "winmm.dll" (ByVal hmo As IntPtr, ByVal dwMsg As Integer) As Integer
Public hmo As IntPtr
Public Caps As MIDIOUTCAPS
Private RetVal As Integer
Public Function MidiOpen(ByVal DevID As Integer) As MIDIOUTCAPS
RetVal = midiOutGetDevCaps(DevID, Caps, Marshal.SizeOf(Caps))
If Not RetVal = 0 Then
MsgBox("GetCaps error " & RetVal.ToString)
Return Caps
End If
RetVal = midiOutOpen(hmo, DevID, 0, 0, 0)
If RetVal = 0 Then Return Caps
MsgBox("MidiOpen error " & RetVal.ToString)
Return Caps
End Function
Public Sub SendMsg(ByVal Channel As Byte, ByVal Note As Byte, ByVal Volume As Byte)
Dim msg As Integer
msg = Volume
msg = (msg << 8) + Note
msg = (msg << 8) + 144 + Channel
RetVal = midiOutShortMsg(hmo, msg)
If RetVal = 0 Then Return
MsgBox("SendMsg error " & RetVal.ToString)
End Sub
Public Sub Note_On(ByVal Channel As Byte, ByVal Note As Byte, ByVal Volume As Byte)
Dim msg As Integer
msg = Volume
msg = (msg << 8) + Note
msg = (msg << 8) + 144 + Channel
RetVal = midiOutShortMsg(hmo, msg)
If RetVal = 0 Then Return
MsgBox("Note_On error " & RetVal.ToString)
End Sub
Public Sub Note_Off(ByVal Channel As Byte, ByVal Note As Byte)
Dim msg As Integer
msg = (msg << 8) + Note
msg = (msg << 8) + 144 + Channel
RetVal = midiOutShortMsg(hmo, msg)
If RetVal = 0 Then Return
MsgBox("Note_Off error " & RetVal.ToString)
End Sub
Public Sub MidiClose()
RetVal = midiOutClose(hmo)
If RetVal = 0 Then Return
MsgBox("Close error " & RetVal.ToString)
End Sub
End Module
please forgive me if I am writing to the wrong forum, but I am new here. Please feel free to redirect me elsewhere
Anyway, I am currently trying to program an interface with an interactive piano keyboard. That is, when the user clicks on a key, the appropriate note plays. Sounds simple enough. However, using standard midi dll calls (code appended below - I am using "note_on" when mouse button is pressed, and "note_off" when the button is released), there seems to be a variable delay (from nothing, to up to a couple of seconds) from when the interface is clicked and when the note actually plays. This does not seem to be a problem with the interface, as I update the image when these events happen, and the effect is instantaneous.
If anyone has any ideas how I can remedy the problem, or other approaches for playing midi in real time, I would love to hear it. Any assistance would be greatly appreciated.
Cheers,
Scott
---------------------------------------------------
Imports System.Runtime.InteropServices
Module MidiModule
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Structure MIDIOUTCAPS
Dim ManufacturerID As Short
Dim ProductID As Short
Dim DriverVersion As Integer
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=32)> _
Dim Label As String
Dim Technology As Short
Dim Voices As Short
Dim Notes As Short
Dim ChannelMask As Short
Dim Support As Integer
End Structure
Declare Function midiOutGetNumDevs Lib "winmm.dll" () As Integer
Declare Auto Function midiOutGetDevCaps Lib "winmm.dll" (ByVal uDeviceID As Integer, ByRef lpMidiOutCaps As MIDIOUTCAPS, ByVal cbMidiOutCaps As Integer) As Integer
Declare Function midiOutOpen Lib "winmm.dll" (ByRef lphmo As IntPtr, ByVal uDeviceID As Integer, ByVal dwCallback As Integer, ByVal dwCallbackInstance As Integer, ByVal dwFlags As Integer) As Integer
Declare Function midiOutClose Lib "winmm.dll" (ByVal hmo As IntPtr) As Integer
Declare Function midiOutShortMsg Lib "winmm.dll" (ByVal hmo As IntPtr, ByVal dwMsg As Integer) As Integer
Public hmo As IntPtr
Public Caps As MIDIOUTCAPS
Private RetVal As Integer
Public Function MidiOpen(ByVal DevID As Integer) As MIDIOUTCAPS
RetVal = midiOutGetDevCaps(DevID, Caps, Marshal.SizeOf(Caps))
If Not RetVal = 0 Then
MsgBox("GetCaps error " & RetVal.ToString)
Return Caps
End If
RetVal = midiOutOpen(hmo, DevID, 0, 0, 0)
If RetVal = 0 Then Return Caps
MsgBox("MidiOpen error " & RetVal.ToString)
Return Caps
End Function
Public Sub SendMsg(ByVal Channel As Byte, ByVal Note As Byte, ByVal Volume As Byte)
Dim msg As Integer
msg = Volume
msg = (msg << 8) + Note
msg = (msg << 8) + 144 + Channel
RetVal = midiOutShortMsg(hmo, msg)
If RetVal = 0 Then Return
MsgBox("SendMsg error " & RetVal.ToString)
End Sub
Public Sub Note_On(ByVal Channel As Byte, ByVal Note As Byte, ByVal Volume As Byte)
Dim msg As Integer
msg = Volume
msg = (msg << 8) + Note
msg = (msg << 8) + 144 + Channel
RetVal = midiOutShortMsg(hmo, msg)
If RetVal = 0 Then Return
MsgBox("Note_On error " & RetVal.ToString)
End Sub
Public Sub Note_Off(ByVal Channel As Byte, ByVal Note As Byte)
Dim msg As Integer
msg = (msg << 8) + Note
msg = (msg << 8) + 144 + Channel
RetVal = midiOutShortMsg(hmo, msg)
If RetVal = 0 Then Return
MsgBox("Note_Off error " & RetVal.ToString)
End Sub
Public Sub MidiClose()
RetVal = midiOutClose(hmo)
If RetVal = 0 Then Return
MsgBox("Close error " & RetVal.ToString)
End Sub
End Module