Results 1 to 9 of 9

Thread: Issue with MidiSysex messages

  1. #1

    Thread Starter
    New Member
    Join Date
    Mar 2013
    Posts
    4

    Issue with MidiSysex messages

    Hey

    i've been trying to create a VB program that interfaces with my midi keyboard and i've got stuck
    i'm trying to send a midi sysex message, but it doesn't work. i've confirmed that the actual message is corrected (via a 3rd party program) but i need it to do it within my program.

    any help is GREATLY appreciated, cause i've been working on this for about 2 weeks!

    Code:
        Sub SendLongMsg()
            Dim MyHdr As MIDIHDR
            Dim sysex As String
            sysex = Chr(&HF0) & Chr(&H41) & Chr(&H10) & Chr(&H0) & Chr(&H0) & Chr(&H27) & Chr(&H12) & Chr(&H1) & Chr(&H0) & Chr(&H0) & Chr(&H0) & Chr(&H0) & Chr(&H7E) & Chr(&HF7)
            MyHdr.dwBufferLength = Len(sysex)
            MyHdr.dwBytesRecorded = Len(sysex)
            MyHdr.lpData = sysex
            MyHdr.dwFlags = 0
            MsgBox(sysex(0))
            'Nur zur Info wieviel Bytes die Sysex hat 
    
                midiOutPrepareHeader(hMidiOUT, MyHdr, Len(MyHdr))
                midiOutLongMsg(hMidiOUT, MyHdr, Len(MyHdr))
                midiOutUnprepareHeader(hMidiOUT, MyHdr, Len(MyHdr))
            Exit Sub
    i believe the problem is the Chr(&H0) is sending Null rather then 00

  2. #2
    PowerPoster dunfiddlin's Avatar
    Join Date
    Jun 2012
    Posts
    8,245

    Re: Issue with MidiSysex messages

    lpData is a pointer to a string, not the string itself so you method will always fail. Try ...

    vb.net Code:
    1. Sub SendLongMsg()
    2.         Dim MyHdr As MIDIHDR
    3.         Dim sysex As String
    4.         sysex = Chr(&HF0) & Chr(&H41) & Chr(&H10) & Chr(&H0) & Chr(&H0) & Chr(&H27) & Chr(&H12) & Chr(&H1) & Chr(&H0) & Chr(&H0) & Chr(&H0) & Chr(&H0) & Chr(&H7E) & Chr(&HF7)
    5.         MyHdr.dwBufferLength = Len(sysex)
    6.         MyHdr.dwBytesRecorded = Len(sysex)
    7.         MyHdr.lpData = = Runtime.InteropServices.Marshal.StringToHGlobalAuto(sysex) ' this line should convert to IntPtr
    8.         MyHdr.dwFlags = 0
    9.         MsgBox(sysex(0))
    10.         'Nur zur Info wieviel Bytes die Sysex hat
    11.  
    12.             midiOutPrepareHeader(hMidiOUT, MyHdr, Len(MyHdr))
    13.             midiOutLongMsg(hMidiOUT, MyHdr, Len(MyHdr))
    14.             midiOutUnprepareHeader(hMidiOUT, MyHdr, Len(MyHdr))
    15.         Exit Sub
    As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"

    Reviews: "dunfiddlin likes his DataTables" - jmcilhinney

    Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!

  3. #3

    Thread Starter
    New Member
    Join Date
    Mar 2013
    Posts
    4

    Re: Issue with MidiSysex messages

    Quote Originally Posted by dunfiddlin View Post
    lpData is a pointer to a string, not the string itself so you method will always fail. Try ...

    vb.net Code:
    1. Sub SendLongMsg()
    2.         Dim MyHdr As MIDIHDR
    3.         Dim sysex As String
    4.         sysex = Chr(&HF0) & Chr(&H41) & Chr(&H10) & Chr(&H0) & Chr(&H0) & Chr(&H27) & Chr(&H12) & Chr(&H1) & Chr(&H0) & Chr(&H0) & Chr(&H0) & Chr(&H0) & Chr(&H7E) & Chr(&HF7)
    5.         MyHdr.dwBufferLength = Len(sysex)
    6.         MyHdr.dwBytesRecorded = Len(sysex)
    7.         MyHdr.lpData = = Runtime.InteropServices.Marshal.StringToHGlobalAuto(sysex) ' this line should convert to IntPtr
    8.         MyHdr.dwFlags = 0
    9.         MsgBox(sysex(0))
    10.         'Nur zur Info wieviel Bytes die Sysex hat
    11.  
    12.             midiOutPrepareHeader(hMidiOUT, MyHdr, Len(MyHdr))
    13.             midiOutLongMsg(hMidiOUT, MyHdr, Len(MyHdr))
    14.             midiOutUnprepareHeader(hMidiOUT, MyHdr, Len(MyHdr))
    15.         Exit Sub
    Thanks for your fast reply!
    i gave it ago, and my keyboard did do some stuff. but it was not what i was expecting.
    i still think there is an issue with converting the HEX to Binary for Midi
    ive read in some places that they had issues where vb.net was sending a Null value rather then Hex(00) and also, that wasn't handling the Hex(f0) very well.

    any thoughts?

  4. #4
    PowerPoster dunfiddlin's Avatar
    Join Date
    Jun 2012
    Posts
    8,245

    Re: Issue with MidiSysex messages

    I've just had a look at the function definitions for the last 3 lines and there is a similar problem in all of them in that you are using a value where there should be a pointer. VB.Net has a real problem in that it doesn't do pointers and we have to fake them. Off the top of my head I'm afraid I don't know the syntax for a pointer to a structure so I'll have to do some research.

    In the meantime if you could verify exactly what the message should consist of particularly noting any encoding required that would help with regard to the problem you mention.
    As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"

    Reviews: "dunfiddlin likes his DataTables" - jmcilhinney

    Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!

  5. #5

    Thread Starter
    New Member
    Join Date
    Mar 2013
    Posts
    4

    Re: Issue with MidiSysex messages

    Quote Originally Posted by dunfiddlin View Post
    I've just had a look at the function definitions for the last 3 lines and there is a similar problem in all of them in that you are using a value where there should be a pointer. VB.Net has a real problem in that it doesn't do pointers and we have to fake them. Off the top of my head I'm afraid I don't know the syntax for a pointer to a structure so I'll have to do some research.

    In the meantime if you could verify exactly what the message should consist of particularly noting any encoding required that would help with regard to the problem you mention.
    Thank you.

    http://www.roland.com/support/articl...-G8&id=1810745
    thats the midi Implementation guide for my keyboard. judging by page 14, it says nothing about special encoding or anything. it just wants the byte values of the Hex Values.

  6. #6
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Issue with MidiSysex messages

    Quote Originally Posted by dunfiddlin View Post
    VB.Net has a real problem in that it doesn't do pointers and we have to fake them.
    It's true that VB doesn't have pointers however claiming that that is a problem is a problem. VB do have constructs to fully support pointers when it comes to P/Invoke.
    Quote Originally Posted by megabytemb View Post
    ive read in some places that they had issues where vb.net was sending a Null value rather then Hex(00)
    Well Hex(00) is NULL. The problem is really that you're sending a string where the function really wants a byte array. VB.Net uses Unicode strings which means that Chr(&H0) is two bytes which both contains a null character. You should change the declaration of the MIDIHRD struct to accept an IntPtr instead of a string for the lpData member. It should look something like this:
    Code:
    Structure MIDIHDR
      Dim lpData As IntPtr
      Dim dwBufferLength As Integer
      Dim dwBytesRecorded As Integer
      Dim dwUser As Integer
      Dim dwFlags As Integer
      Dim lpNext As Integer
      Dim Reserved As Integer
      Dim dwOffset As Integer
      Dim dwReserved1 As Integer
      Dim dwReserved2 As Integer
      Dim dwReserved3 As Integer
      Dim dwReserved4 As Integer
    End Structure
    Instead of using an array for the dwReserved I opted to create 4 integers.

    Now if you want to build up your string as you've done, then call this sub to send it.
    Code:
      Public Sub SendMidiMessageLong(hMidi As Integer, msg As String)
        Dim hdr As MIDIHDR
        Dim bArr() As Byte = System.Text.Encoding.ASCII.GetBytes(msg)
        Dim size As Integer = bArr.Length
        hdr.lpData = System.Runtime.InteropServices.Marshal.AllocHGlobal(size)
        For i As Integer = 0 To bArr.Length - 1
          System.Runtime.InteropServices.Marshal.WriteByte(hdr.lpData, i, bArr(i))
        Next
        hdr.dwBufferLength = size
        hdr.dwBytesRecorded = size
        midiOutPrepareHeader(hMidi, hdr, 48)
        midiOutLongMsg(hMidi, hdr, 48)
        midiOutUnprepareHeader(hMidi, hdr, 48)
        System.Runtime.InteropServices.Marshal.FreeHGlobal(hdr.lpData)
      End Sub
    So basically you would call this method like this:
    Code:
    Dim sysex As String = Chr(&HF0) & Chr(&H41) & Chr(&H10) & ...
    SendMidiMessageLong(hMidiOUT, sysex)
    Last edited by Joacim Andersson; Mar 23rd, 2013 at 10:42 PM.

  7. #7
    Frenzied Member
    Join Date
    Jul 2011
    Location
    UK
    Posts
    1,335

    Re: Issue with MidiSysex messages

    I like what Joacim has done there. It's like watching Picasso paint: don't know what the hell is going on, but the way it all fits together is fascinating


    Just as quick note, though. Remember that ASCII encoding is a 7 bit encoding, so any character defined by more than 7 bits will not be encoded properly (it will be encoded to a byte with value 0x3F by default). Your sysex string contains two such characters: Chr(&HF0) and Chr(&HF7).

    On my system there are only three encodings that will encode the string to give the bytes as expected, and they are:
    Windows-1252
    iso-8859-1
    iso-8859-15



    You might want to change this line from Joacim's second block of code:
    Code:
    Dim bArr() As Byte = System.Text.Encoding.ASCII.GetBytes(msg)
    to something along the lines of:
    Code:
     Dim enc As System.Text.Encoding = System.Text.Encoding.GetEncoding("iso-8859-1")
     Dim bArr() As Byte = enc.GetBytes(msg)

  8. #8

    Thread Starter
    New Member
    Join Date
    Mar 2013
    Posts
    4

    Re: Issue with MidiSysex messages

    SUCCESS!!! Thank you so much!!!

    for future generations, so they don't have the same trouble i did (most of the examples i found were for windows 3.1!) here is the useful segments of my final code

    Code:
        Structure MIDIHDR
            Dim lpData As IntPtr
            Dim dwBufferLength As Integer
            Dim dwBytesRecorded As Integer
            Dim dwUser As Integer
            Dim dwFlags As Integer
            Dim lpNext As Integer
            Dim Reserved As Integer
            Dim dwOffset As Integer
            Dim dwReserved1 As Integer
            Dim dwReserved2 As Integer
            Dim dwReserved3 As Integer
            Dim dwReserved4 As Integer
        End Structure
    
        Sub SendMidiMessageLong(msg As String)
            Dim hdr As MIDIHDR
            Dim enc As System.Text.Encoding = System.Text.Encoding.GetEncoding("iso-8859-1")
            Dim bArr() As Byte = enc.GetBytes(msg)
            Dim size As Integer = bArr.Length
            hdr.lpData = System.Runtime.InteropServices.Marshal.AllocHGlobal(size)
            For i As Integer = 0 To bArr.Length - 1
                System.Runtime.InteropServices.Marshal.WriteByte(hdr.lpData, i, bArr(i))
            Next
            hdr.dwBufferLength = size
            hdr.dwBytesRecorded = size
            midiOutPrepareHeader(hMidiOUT, hdr, 48)
            midiOutLongMsg(hMidiOUT, hdr, 48)
            midiOutUnprepareHeader(hMidiOUT, hdr, 48)
            System.Runtime.InteropServices.Marshal.FreeHGlobal(hdr.lpData)
        End Sub
    
    Dim sysmsg = Chr(&HF0) & Chr(&H41) & Chr(&H10) & Chr(&H0) & Chr(&H0) & Chr(&H27) & Chr(&H12) & Chr(&H1) & Chr(&H0) & Chr(&H0) & Chr(&H0) & Chr(&H0) & Chr(&H7E) & Chr(&HF7)
    
    SendMidiMessageLong(sysmsg)

  9. #9
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Issue with MidiSysex messages

    Quote Originally Posted by Inferrd View Post
    Remember that ASCII encoding is a 7 bit encoding, so any character defined by more than 7 bits will not be encoded properly
    Oh yeah, sorry my bad. I wasn't really paying that much attention to the actual string that was sent to it. However since we're now more interested in using a byte array rather than a string you can bypass the whole creation of the string, with all those Chr() calls and skip the encoding part, and instead simply create the byte array directly.
    Code:
      Public Sub SendMidiMessageLong(hMidi As Integer, bArr() As Byte)
        Dim hdr As MIDIHDR
        Dim size As Integer = bArr.Length
        hdr.lpData = System.Runtime.InteropServices.Marshal.AllocHGlobal(size)
        For i As Integer = 0 To size - 1
          System.Runtime.InteropServices.Marshal.WriteByte(hdr.lpData, i, bArr(i))
        Next
        hdr.dwBufferLength = size
        hdr.dwBytesRecorded = size
        midiOutPrepareHeader(hMidi, hdr, 48)
        midiOutLongMsg(hMidi, hdr, 48)
        midiOutUnprepareHeader(hMidi, hdr, 48)
        System.Runtime.InteropServices.Marshal.FreeHGlobal(hdr.lpData)
      End Sub
    Now you can call this method like this:
    Code:
    Dim sysmsg() As Byte = New Byte() {&HF0, &H41, &H10, &H0, &H0, &H27, &H12, &H1, &H0, &H0, &H0, &H0, &H7E, &HF7}
    SendMidiMessageLong(hMidiOUT, sysmsg)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width