Main Site Documentation

USBHost to MIDI device


#1

According to WikiPedia the “MIDI standard consists of a communications messaging protocol designed for use with musical instruments, as well as a physical interface standard. It consists physically of a one-way (simplex) digital current loop electrical connection sending asynchronous serial communication data at 31,250 bits per second. 8-N-1 format, i.e. one start bit (must be 0), eight data bits, no parity bit and one stop bit (must be 1).”

So, I’m trying to send data to a MIDI device using the USBH_SerialUSB class. It seems like I might be able to instantiate the serial device as follows:

    void USBHostController_DeviceConnectedEvent(GHIElectronics.NETMF.USBHost.USBH_Device device)
    {

        if (index == 0)
        {
            deviceVar = new USBH_SerialUSB(device, 31250, System.IO.Ports.Parity.None, 10, System.IO.Ports.StopBits.One);

        }

But it throws an exception without much info:

#### Exception System.Exception - 0xffffffff (3) ####
#### Message: 
#### GHIElectronics.NETMF.USBHost.USBH_SerialUSB::Init [IP: 0000] ####
#### GHIElectronics.NETMF.USBHost.USBH_SerialUSB::.ctor [IP: 0039] ####
#### USBHost.Program::USBHostController_DeviceConnectedEvent [IP: 004f] ####
#### GHIElectronics.NETMF.USBHost.USBH_DeviceConnectionEventHandler::Invoke [IP: 0000] ####
#### GHIElectronics.NETMF.USBHost.USBHostController::nativeEventDispatcher_OnInterrupt [IP: 0037] ####
#### GHIElectronics.NETMF.System.InternalEvent::nativeEventDispatcher_OnInterrupt [IP: 0054] ####

A first chance exception of type ‘System.Exception’ occurred in GHIElectronics.NETMF.USBHost.dll
Message: Exception was thrown: System.Exception Inner Exception:

Any suggestions?


#2

You are reading about the original midi that uses serial ports. The new USB midi is totally different. Unfortunately, the USB midi uses an ugly way to handle descriptors that we do not support.


#3

At least this is what I recall from old discussions.


#4

Thanks, Gus.


#5

This sounds like an opportunity for Pete Brown to flex his module-building muscles. After all, he’s already built his own custom PCB for a MIDI thru box:

http://10rem.net/blog/2011/05/25/building-a-midi-thru-box-part-1

How hard could it be for him to build a MIDI module for Gadgeteer? :slight_smile:


#6

It was already built LONG time ago by MSR. We now need them to publish the files :slight_smile:


#7

But do not worry, just get this http://www.sparkfun.com/products/9595 and http://www.ghielectronics.com/catalog/product/319 then you have MIDI :wink:


#8

I just had a second thought. I have an old ProteusFX from the mid 1990s. Would that use the old serial protocol?

I already have the GHI Music Module for Marco Minerva’s text to speech library. I want to try changing tempo’s on midi stream in real time.


#9

Actually, my MIDI module is why I had downloaded and learned Eagle. It’s fairly far along.

Even if it was done before (there are tons of shields), that’s fine. :slight_smile:

On Gadgeteer (and other NETMF boards), the complication comes from 3.3v vs. 5v. That’s why so many MIDI modules won’t work, especially if you have older equipment that really needs the full 5v.

Pete


#10

Actually, that one really only works (well?) with 5v data signals from the mcu

Pete


#11

Oh, and MIDI :slight_smile:

(and a huge mess, there’s room for me to work in there, somewhere)


#12

ha ha awesome!


#13

The Sanford MIDI libraries work great with the full .NET Framework: http://www.codeproject.com/Articles/6228/C-MIDI-Toolkit

Real time MIDI changes are no problem using this toolkit and the .NET Framework.
I think they could be adapted to run on NETMF and Gadgeteer, and that would be fine!


#14

parsing MIDI isn’t hard, but on an MCU running NETMF really needs efficient code to help avoid lag. I haven’t checked the desktop library there, but really, working with MIDI isn’t difficult :slight_smile:

http://10rem.net/blog/2011/01/20/accepting-midi-serial-input-with-the-netduino
http://10rem.net/blog/2011/01/20/parsing-serial-midi-messages-with-the-netduino

Pete


#15

It’s starting to seem more feasible. Here’s the kind of thing I want to do:

            switch(key)
            {
                case ConsoleKey.LeftArrow:
                {
                    int oldTempo = tempo;
                    tempo += 10000;
                    int result = sequencer.ChangeTempo(oldTempo, tempo);
                    Console.WriteLine("Slower... ." + " New tempo: " + result);
                    break;
                
                }
                case ConsoleKey.RightArrow:
                {
                    int oldTempo = tempo;
                    tempo -= 10000;
                    int result = sequencer.ChangeTempo(oldTempo, tempo);
                    Console.WriteLine("Faster... ." + " New tempo: " + result);
                    break;

                }
                case ConsoleKey.S:
                {
                    sequencer.Stop();
                    timer.Stop();
                    outDevice.Reset();
                    Console.WriteLine("Stopped.");
                    Console.WriteLine("Press C to continue, R to rewind, X to exit... ");
                    break;
                }

            
                case ConsoleKey.C:
                {
                    sequencer.Continue();
                    timer.Start();
                    Console.WriteLine("Playing... ");                        
                    break;
                }

                case ConsoleKey.X:
                {
                    sequencer.Dispose();
                    timer.Dispose();
                    outDevice.Dispose();
                    ended = true;
                    break;
                }

                case ConsoleKey.R:
                {
                    sequencer.Position = 0;
                    Console.WriteLine("Playing from start... ");
                    break;
                }

                case ConsoleKey.UpArrow:
                {
                    pitch++;
                    break;
                }

                case ConsoleKey.DownArrow:
                {
                    pitch--;
                    break;
                }
                default:
                {
                    break;
                }
            }

#16

Mike,

Can you try wrapping your code with the code tags? Just edit your post, and highlight the code section, then click the icon with the 1s and 0s. Will make it MUCH easier to read code in your posts. :slight_smile:


#17

Much better, yes!

                
                ConsoleKey key = Console.ReadKey().Key;
                
                switch(key)
                {
                    case ConsoleKey.LeftArrow:
                    {
                        int oldTempo = tempo;
                        tempo += 10000;
                        int result = sequencer.ChangeTempo(oldTempo, tempo);
                        Console.WriteLine("Slower... ." + " New tempo: " + result);
                        break;
                    
                    }
                    case ConsoleKey.RightArrow:
                    {
                        int oldTempo = tempo;
                        tempo -= 10000;
                        int result = sequencer.ChangeTempo(oldTempo, tempo);
                        Console.WriteLine("Faster... ." + " New tempo: " + result);
                        break;

                    }
                    case ConsoleKey.S:
                    {
                        sequencer.Stop();
                        timer.Stop();
                        outDevice.Reset();
                        Console.WriteLine("Stopped.");
                        Console.WriteLine("Press C to continue, R to rewind, X to exit... ");
                        break;
                    }

                
                    case ConsoleKey.C:
                    {
                        sequencer.Continue();
                        timer.Start();
                        Console.WriteLine("Playing... ");                        
                        break;
                    }

                    case ConsoleKey.X:
                    {
                        sequencer.Dispose();
                        timer.Dispose();
                        outDevice.Dispose();
                        ended = true;
                        break;
                    }

                    case ConsoleKey.R:
                    {
                        sequencer.Position = 0;
                        Console.WriteLine("Playing from start... ");
                        break;
                    }

                    case ConsoleKey.UpArrow:
                    {
                        pitch++;
                        break;
                    }

                    case ConsoleKey.DownArrow:
                    {
                        pitch--;
                        break;
                    }
                    default:
                    {
                        break;
                    }
                }



#18

Is the sequencer just a MIDI device? If so, I assume the ChangeTempo and other methods just send out MIDI CC?

Pete


#19

In this case the sequencer is an instance of a .net class. The MIDI device is represented by an OutputDevice. The ChangeTempo method changes the bpm rate to slow down or speed up the tempo, so it affects every MIDI event the sequencer processes.

I tried to do this with other libraries long ago, but the new tempo tended to be overridden by a tempo change event in the sequence and was gone.