All of lore.kernel.org
 help / color / mirror / Atom feed
* RawMIDI behaviour with MidiFace 4x4
@ 2015-03-07 17:26 Kalvas, Taneli
  2015-03-09  8:38 ` Ricard Wanderlof
  2015-03-09  8:43 ` Clemens Ladisch
  0 siblings, 2 replies; 13+ messages in thread
From: Kalvas, Taneli @ 2015-03-07 17:26 UTC (permalink / raw)
  To: alsa-devel

Dear All,

I am developing a patch librarian for a synthesizer. Because the communication happens with Midi sysex and timing is not relevant I chose RawMIDI interface and not the alsa sequencer. The problem I have encountered is that writing to the midi port with snd_rawmidi_write() seems to broken. The function accepts any size of data block and claims to have sent everything. In reality only a part of the message is sent. For a large block size I can see the activity light blinking for fraction of a second. This happens both in blocking and non-blocking mode. I would expect the snd_rawmidi_write() to accept only a part of the message. 

My hardware is Miditech Midiface 4x4, a USB midi interface:
$ cat /proc/asound/cards
 0 [PCH            ]: HDA-Intel - HDA Intel PCH
                      HDA Intel PCH at 0xe0610000 irq 45
 1 [MIDI4x4        ]: USB-Audio - MIDI4x4
                      MIDIPLUS MIDI4x4 at usb-0000:00:14.0-1, full speed
usbid: 1acc:1a0b

My alsa is quite recent (aplay shows version 1.0.27.2), I am running Ubuntu with 3.13.0-39-generic kernel.

I have tested the system by connecting the output port to an input port on the hardware and having another program output the received bytes on stdout. My observations:
- As long as the buffer size is 276 bytes or less it gets sent ok
- Larger buffer sizes cause corruption and roughly 300 bytes of received.
- Alsa reports midi ring buffer size of 4096.
- snd_rawmidi_status_get_xruns() on both ends reports 0 errors.
- If I write N=128 byte blocks and usleep for 352*N after each write, everything works ok.

Is this due to hardware incompatibility with alsa driver or what is going on? Is there a way to connect two programs via a virtual RawMIDI port so that I could test without using the hardware? Any other diagnostics that I could do?

My test programs:

write.cpp:
int main( void )
{
    int intstatus;
    snd_rawmidi_t *midiout;

    if( (intstatus = snd_rawmidi_open(NULL, &midiout, "hw:1,0,1", 0)) ) {
	std::cerr << "unable to open MIDI out port: " << snd_strerror(intstatus) << "\n";
	exit( 1 );
    }

    int N = 3000; // 276 bytes gets through ok.
    unsigned char msg[N];
    for( int a = 0; a < N; a++ ) {
	msg[a] = a % 0x80;
    }
    msg[0] = 0xF0;
    msg[N-1] = 0xF7;

    ssize_t wrstatus;
    if( (wrstatus = snd_rawmidi_write(midiout, msg, N)) < 0 ) {
	std::cerr << "unable to write MIDI port: " << snd_strerror(wrstatus) << "\n";
	return( -1 );
    }
    std::cout << "write status = " << wrstatus << "\n";
    if( (intstatus = snd_rawmidi_drain( midiout )) ) {
	std::cerr << "unable to drain: " << snd_strerror(intstatus) << "\n";
	exit( 1 );
    }

    // Sleep for the amount of time needed for transfer + 10 % extra + 100 ms
    usleep( 352*N + 100000 );

    snd_rawmidi_status_t *stat;
    snd_rawmidi_status_malloc( &stat );
    snd_rawmidi_status( midiout, stat );
    int err = snd_rawmidi_status_get_xruns( stat );
    std::cout << "xruns = " << err << "\n";

    snd_rawmidi_close( midiout );

    return( 0 );
}

--------------------
read.cpp:
bool quit = false;

void signal_int( int )
{
    quit = true;
}

int main( void )
{
    int mode = SND_RAWMIDI_NONBLOCK;
    int intstat;
    std::string portname = "hw:1,0,0";
    //std::string portname = "virtual";
    snd_rawmidi_t* midiin;

    if( (intstat = snd_rawmidi_open(&midiin, NULL, portname.c_str(), mode)) < 0 ) {
	std::cerr << "unable to open MIDI port " << portname << ": " << snd_strerror(intstat) << "\n";
	exit( 1 );
    }

    int count = 0;
    unsigned char buf[1];

    std::cout << std::dec << std::setfill(' ') << std::setw(6) << count << "   ";

    signal( SIGINT, signal_int );

    while( !quit ) {
	int read = snd_rawmidi_read( midiin, buf, 1 );
	if( read == 0 || read == -EBUSY || read == -EAGAIN ) {
	    usleep( 320 );
	    continue;
	}
	else if( read < 0 ) {
	    std::cerr << "unable to read MIDI port" << portname << ": " << snd_strerror(read) << "\n";
	    exit( 1 );
	}

	std::cout << std::hex << std::setfill('0') 
		  << "0x" << std::setw(2) << (int)buf[0] << " "
		  << std::flush;
	count++;
	if( count % 8 == 0 ) {
	    std::cout << "\n";
	    std::cout << std::dec << std::setfill(' ') << std::setw(6) << count << "   "
		      << std::flush;	    
	}
    }

    snd_rawmidi_status_t *stat;
    snd_rawmidi_status_malloc( &stat );
    snd_rawmidi_status( midiin, stat );
    int err = snd_rawmidi_status_get_xruns( stat );
    std::cout << "\nxruns = " << err << "\n";
	
    snd_rawmidi_close( midiin );

    return( 0 );
}

Thanks.
Taneli

-- 
Taneli Kalvas
Ph.D., Researcher
Department of Physics, room FL114
P.O. Box 35 (YFL)
40014 University of Jyväskylä, Finland
Mobile: +358-44-314-1602
Fax:    +358-14-617-411
Email:  taneli.kalvas@jyu.fi 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RawMIDI behaviour with MidiFace 4x4
  2015-03-07 17:26 RawMIDI behaviour with MidiFace 4x4 Kalvas, Taneli
@ 2015-03-09  8:38 ` Ricard Wanderlof
  2015-03-09  8:47   ` Clemens Ladisch
  2015-03-09  8:43 ` Clemens Ladisch
  1 sibling, 1 reply; 13+ messages in thread
From: Ricard Wanderlof @ 2015-03-09  8:38 UTC (permalink / raw)
  To: Kalvas, Taneli; +Cc: alsa-devel


On Sat, 7 Mar 2015, Kalvas, Taneli wrote:

> I am developing a patch librarian for a synthesizer. Because the 
> communication happens with Midi sysex and timing is not relevant I chose 
> RawMIDI interface and not the alsa sequencer. The problem I have 
> encountered is that writing to the midi port with snd_rawmidi_write() 
> seems to broken. The function accepts any size of data block and claims 
> to have sent everything. In reality only a part of the message is sent. 
> For a large block size I can see the activity light blinking for 
> fraction of a second. This happens both in blocking and non-blocking 
> mode. I would expect the snd_rawmidi_write() to accept only a part of 
> the message.

Can't help with rawmidi, but I can at least report that my experience 
using the sequencer interface has been that it is rather straightforward 
to use, even if just using it to send and transmit sysex data, even when 
the data is longer than 300 bytes. (See for instance 
https://github.com/polluxsynth/xtor/blob/master/midi.c ( midi_send_sysex() 
and midi_input() functions).

/Ricard
-- 
Ricard Wolf Wanderlöf                           ricardw(at)axis.com
Axis Communications AB, Lund, Sweden            www.axis.com
Phone +46 46 272 2016                           Fax +46 46 13 61 30

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RawMIDI behaviour with MidiFace 4x4
  2015-03-07 17:26 RawMIDI behaviour with MidiFace 4x4 Kalvas, Taneli
  2015-03-09  8:38 ` Ricard Wanderlof
@ 2015-03-09  8:43 ` Clemens Ladisch
  2015-03-09 19:22   ` Kalvas, Taneli
  1 sibling, 1 reply; 13+ messages in thread
From: Clemens Ladisch @ 2015-03-09  8:43 UTC (permalink / raw)
  To: Kalvas, Taneli, alsa-devel

Kalvas, Taneli wrote:
> writing to the midi port with snd_rawmidi_write() seems to broken. The
> function accepts any size of data block and claims to have sent
> everything. In reality only a part of the message is sent.
>
> My hardware is Miditech Midiface 4x4, a USB midi interface:
>  1 [MIDI4x4        ]: USB-Audio - MIDI4x4
>                       MIDIPLUS MIDI4x4 at usb-0000:00:14.0-1, full speed

snd_rawmidi_write() never accepts more data than it can handle (in
blocking mode, it waits until the buffer is empty enough).  The
snd-usb-audio driver waits until the device has accepted the data.

Are there any messages in the system log when this happens?

Please show the output of "lsusb -d 1acc:1a0b -v".

> I have tested the system by connecting the output port to an input
> port on the hardware and having another program output the received
> bytes on stdout. My observations:
> - As long as the buffer size is 276 bytes or less it gets sent ok
> - Larger buffer sizes cause corruption and roughly 300 bytes of received.

This sounds as if the device has a buffer size of 256 bytes, but does
not actually check if the buffer is full, and always accepts more data.

Does later data overwrite data that should have been sent earlier?

> Is there a way to connect two programs via a virtual RawMIDI port so
> that I could test without using the hardware?

Load the snd-virmidi module, and connect two of its ports with aconnect.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RawMIDI behaviour with MidiFace 4x4
  2015-03-09  8:38 ` Ricard Wanderlof
@ 2015-03-09  8:47   ` Clemens Ladisch
  2015-03-09 11:37     ` Kalvas, Taneli
  2015-03-09 14:29     ` Ricard Wanderlof
  0 siblings, 2 replies; 13+ messages in thread
From: Clemens Ladisch @ 2015-03-09  8:47 UTC (permalink / raw)
  To: Ricard Wanderlof; +Cc: alsa-devel, Kalvas, Taneli

Ricard Wanderlof wrote:
> On Sat, 7 Mar 2015, Kalvas, Taneli wrote:
>> I am developing a patch librarian for a synthesizer. Because the
>> communication happens with Midi sysex and timing is not relevant I chose
>> RawMIDI interface and not the alsa sequencer. The problem I have
>> encountered is that writing to the midi port with snd_rawmidi_write()
>> seems to broken. The function accepts any size of data block and claims
>> to have sent everything. In reality only a part of the message is sent.
>> For a large block size I can see the activity light blinking for
>> fraction of a second. This happens both in blocking and non-blocking
>> mode. I would expect the snd_rawmidi_write() to accept only a part of
>> the message.
>
> Can't help with rawmidi, but I can at least report that my experience
> using the sequencer interface has been that it is rather straightforward
> to use, even if just using it to send and transmit sysex data, even when
> the data is longer than 300 bytes.

If the data is larger than the RawMIDI buffer size (4096 bytes), the
sequencer does not wait (like snd_rawmidi_write() would do), but just
drops data.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RawMIDI behaviour with MidiFace 4x4
  2015-03-09  8:47   ` Clemens Ladisch
@ 2015-03-09 11:37     ` Kalvas, Taneli
  2015-03-09 14:29     ` Ricard Wanderlof
  1 sibling, 0 replies; 13+ messages in thread
From: Kalvas, Taneli @ 2015-03-09 11:37 UTC (permalink / raw)
  To: alsa-devel

>>> I am developing a patch librarian for a synthesizer. Because the
>>> communication happens with Midi sysex and timing is not relevant I chose
>>> RawMIDI interface and not the alsa sequencer. The problem I have
>>> encountered is that writing to the midi port with snd_rawmidi_write()
>>> seems to broken. The function accepts any size of data block and claims
>>> to have sent everything. In reality only a part of the message is sent.
>>> For a large block size I can see the activity light blinking for
>>> fraction of a second. This happens both in blocking and non-blocking
>>> mode. I would expect the snd_rawmidi_write() to accept only a part of
>>> the message.
>>
>> Can't help with rawmidi, but I can at least report that my experience
>> using the sequencer interface has been that it is rather straightforward
>> to use, even if just using it to send and transmit sysex data, even when
>> the data is longer than 300 bytes.
>
>If the data is larger than the RawMIDI buffer size (4096 bytes), the
>sequencer does not wait (like snd_rawmidi_write() would do), but just
>drops data.

This is just my question. You say snd_rawmidi_write() SHOULD cause a wait, but in my case it does not. Do you have any idea why this happens and how I could further diagnose the problem, possibly finding a fix?

Taneli

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RawMIDI behaviour with MidiFace 4x4
  2015-03-09  8:47   ` Clemens Ladisch
  2015-03-09 11:37     ` Kalvas, Taneli
@ 2015-03-09 14:29     ` Ricard Wanderlof
  2015-03-09 18:40       ` Clemens Ladisch
  1 sibling, 1 reply; 13+ messages in thread
From: Ricard Wanderlof @ 2015-03-09 14:29 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: alsa-devel, Kalvas, Taneli


On Mon, 9 Mar 2015, Clemens Ladisch wrote:

> Ricard Wanderlof wrote:
> > On Sat, 7 Mar 2015, Kalvas, Taneli wrote:
> >> I am developing a patch librarian for a synthesizer. Because the
> >> communication happens with Midi sysex and timing is not relevant I chose
> >> RawMIDI interface and not the alsa sequencer. The problem I have
> >> encountered is that writing to the midi port with snd_rawmidi_write()
> >> seems to broken. The function accepts any size of data block and claims
> >> to have sent everything. In reality only a part of the message is sent.
> >> For a large block size I can see the activity light blinking for
> >> fraction of a second. This happens both in blocking and non-blocking
> >> mode. I would expect the snd_rawmidi_write() to accept only a part of
> >> the message.
> >
> > Can't help with rawmidi, but I can at least report that my experience
> > using the sequencer interface has been that it is rather straightforward
> > to use, even if just using it to send and transmit sysex data, even when
> > the data is longer than 300 bytes.
> 
> If the data is larger than the RawMIDI buffer size (4096 bytes), the
> sequencer does not wait (like snd_rawmidi_write() would do), but just
> drops data.

Interesting. Thanks for the info. I've only tried sending patch dumps for 
single synthesizer patches, in the region of 400 bytes, which are more 
than 300 but far less than 4096 obviously.

I have noted though, that when sending data with snd_seq_ev_set_sysex() 
that the ALSA lib internally copies the data to an internal, malloced 
buffer, so I always thought that it would take care of any amount of data 
from there, but apparently not then?

/Ricard
-- 
Ricard Wolf Wanderlöf                           ricardw(at)axis.com
Axis Communications AB, Lund, Sweden            www.axis.com
Phone +46 46 272 2016                           Fax +46 46 13 61 30

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RawMIDI behaviour with MidiFace 4x4
  2015-03-09 14:29     ` Ricard Wanderlof
@ 2015-03-09 18:40       ` Clemens Ladisch
  0 siblings, 0 replies; 13+ messages in thread
From: Clemens Ladisch @ 2015-03-09 18:40 UTC (permalink / raw)
  To: Ricard Wanderlof; +Cc: alsa-devel, Kalvas, Taneli

Ricard Wanderlof wrote:
> On Mon, 9 Mar 2015, Clemens Ladisch wrote:
>> If the data is larger than the RawMIDI buffer size (4096 bytes), the
>> sequencer does not wait (like snd_rawmidi_write() would do), but just
>> drops data.
>
> I have noted though, that when sending data with snd_seq_ev_set_sysex()
> that the ALSA lib internally copies the data to an internal, malloced
> buffer, so I always thought that it would take care of any amount of data
> from there, but apparently not then?

The sequencer was designed for real-time events.  When events are scheduled
to be sent later, there is no good mechanism to let the current buffer fill
level influence the timing of events, or to report errors back.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RawMIDI behaviour with MidiFace 4x4
  2015-03-09  8:43 ` Clemens Ladisch
@ 2015-03-09 19:22   ` Kalvas, Taneli
  2015-03-09 21:47     ` Clemens Ladisch
  0 siblings, 1 reply; 13+ messages in thread
From: Kalvas, Taneli @ 2015-03-09 19:22 UTC (permalink / raw)
  To: Clemens Ladisch, alsa-devel

>> writing to the midi port with snd_rawmidi_write() seems to broken. The
>> function accepts any size of data block and claims to have sent
>> everything. In reality only a part of the message is sent.
>>
>> My hardware is Miditech Midiface 4x4, a USB midi interface:
>>  1 [MIDI4x4        ]: USB-Audio - MIDI4x4
>>                       MIDIPLUS MIDI4x4 at usb-0000:00:14.0-1, full speed
>
> snd_rawmidi_write() never accepts more data than it can handle (in
> blocking mode, it waits until the buffer is empty enough).  The
> snd-usb-audio driver waits until the device has accepted the data.
> 
> Are there any messages in the system log when this happens?

There is nothing in the logs.

> Please show the output of "lsusb -d 1acc:1a0b -v".

$ sudo lsusb -d 1acc:1a0b -v

Bus 003 Device 003: ID 1acc:1a0b  
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        16
  idVendor           0x1acc 
  idProduct          0x1a0b 
  bcdDevice            1.01
  iManufacturer           1 MIDIPLUS
  iProduct                2 MIDI4x4
  iSerial                 3 MIDIPLUS-BC-1A0B-07DA0908-MIDI4x4
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength          197
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      1 Control Device
      bInterfaceProtocol      0 
      iInterface              0 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength            9
        bInCollection           1
        baInterfaceNr( 0)       1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         1 Audio
      bInterfaceSubClass      3 MIDI Streaming
      bInterfaceProtocol      0 
      iInterface              0 
      MIDIStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength          155
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               1 Embedded
        bJackID                 1
        iJack                   4 Midi Out 1
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               2 External
        bJackID                 2
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               1 Embedded
        bJackID                 5
        iJack                   6 Midi Out 2
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               2 External
        bJackID                 6
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               1 Embedded
        bJackID                 9
        iJack                   8 Midi Out 3
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               2 External
        bJackID                10
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               1 Embedded
        bJackID                13
        iJack                  10 Midi Out 4
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               2 External
        bJackID                14
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               1 Embedded
        bJackID                 3
        bNrInputPins            1
        baSourceID( 0)          2
        BaSourcePin( 0)         1
        iJack                   5 Midi In 1
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               2 External
        bJackID                 4
        bNrInputPins            1
        baSourceID( 0)          1
        BaSourcePin( 0)         1
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               1 Embedded
        bJackID                 7
        bNrInputPins            1
        baSourceID( 0)          6
        BaSourcePin( 0)         1
        iJack                   7 Midi In 2
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               2 External
        bJackID                 8
        bNrInputPins            1
        baSourceID( 0)          5
        BaSourcePin( 0)         1
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               1 Embedded
        bJackID                11
        bNrInputPins            1
        baSourceID( 0)         10
        BaSourcePin( 0)         1
        iJack                   9 Midi In 3
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               2 External
        bJackID                12
        bNrInputPins            1
        baSourceID( 0)          9
        BaSourcePin( 0)         1
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               1 Embedded
        bJackID                15
        bNrInputPins            1
        baSourceID( 0)         14
        BaSourcePin( 0)         1
        iJack                  11 Midi In 4
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               2 External
        bJackID                16
        bNrInputPins            1
        baSourceID( 0)         13
        BaSourcePin( 0)         1
        iJack                   0 
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0010  1x 16 bytes
        bInterval               0
        bRefresh                0
        bSynchAddress           0
        MIDIStreaming Endpoint Descriptor:
          bLength                 8
          bDescriptorType        37
          bDescriptorSubtype      1 (GENERAL)
          bNumEmbMIDIJack         4
          baAssocJackID( 0)       1
          baAssocJackID( 1)       5
          baAssocJackID( 2)       9
          baAssocJackID( 3)      13
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0010  1x 16 bytes
        bInterval               0
        bRefresh                0
        bSynchAddress           0
        MIDIStreaming Endpoint Descriptor:
          bLength                 8
          bDescriptorType        37
          bDescriptorSubtype      1 (GENERAL)
          bNumEmbMIDIJack         4
          baAssocJackID( 0)       3
          baAssocJackID( 1)       7
          baAssocJackID( 2)      11
          baAssocJackID( 3)      15
Device Status:     0x0002
  (Bus Powered)
  Remote Wakeup Enabled

>> I have tested the system by connecting the output port to an input
>> port on the hardware and having another program output the received
>> bytes on stdout. My observations:
>> - As long as the buffer size is 276 bytes or less it gets sent ok
>> - Larger buffer sizes cause corruption and roughly 300 bytes of received.
> 
> This sounds as if the device has a buffer size of 256 bytes, but does
> not actually check if the buffer is full, and always accepts more data.
> 
> Does later data overwrite data that should have been sent earlier?

By looking at the receiving end bytes it looks exactly like that has happened.

>> Is there a way to connect two programs via a virtual RawMIDI port so
>> that I could test without using the hardware?
> 
> Load the snd-virmidi module, and connect two of its ports with aconnect.

I did this and by using the virtual ports the behaviour is more reasonable, but still not as expected. Everything works ok as long as the message length is less than or equal to the buffer size (4096). With message sizes larger than that the writing end still claims it has sent everything, as it should do because the port is opened in blocking mode. On the reading end I can see that some data is missing and xruns are reported.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RawMIDI behaviour with MidiFace 4x4
  2015-03-09 19:22   ` Kalvas, Taneli
@ 2015-03-09 21:47     ` Clemens Ladisch
  2015-03-10  7:32       ` Kalvas, Taneli
  0 siblings, 1 reply; 13+ messages in thread
From: Clemens Ladisch @ 2015-03-09 21:47 UTC (permalink / raw)
  To: Kalvas, Taneli, alsa-devel

Kalvas, Taneli wrote:
>>> I have tested the system by connecting the output port to an input
>>> port on the hardware and having another program output the received
>>> bytes on stdout. My observations:
>>> - As long as the buffer size is 276 bytes or less it gets sent ok
>>> - Larger buffer sizes cause corruption and roughly 300 bytes of received.
>>
>> This sounds as if the device has a buffer size of 256 bytes, but does
>> not actually check if the buffer is full, and always accepts more data.
>>
>> Does later data overwrite data that should have been sent earlier?
>
> By looking at the receiving end bytes it looks exactly like that has happened.

This pretty much proves that this is a bug in the device firmware.

You might try contacting Miditech ...

>>> Is there a way to connect two programs via a virtual RawMIDI port so
>>> that I could test without using the hardware?
>>
>> Load the snd-virmidi module, and connect two of its ports with aconnect.
>
> I did this and by using the virtual ports the behaviour is more
> reasonable, but still not as expected. Everything works ok as long as
> the message length is less than or equal to the buffer size (4096).
> With message sizes larger than that the writing end still claims it
> has sent everything, as it should do because the port is opened in
> blocking mode. On the reading end I can see that some data is missing
> and xruns are reported.

Oops, using snd-virmidi this way also goes through the sequencer, which
does not do blocking.

There is no other way to get a virtual RawMIDI port.

However, the driver was tested with lots of other devices, and huge
SysEx messages have this problem only with your device.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RawMIDI behaviour with MidiFace 4x4
  2015-03-09 21:47     ` Clemens Ladisch
@ 2015-03-10  7:32       ` Kalvas, Taneli
  2015-03-10  8:02         ` Clemens Ladisch
  0 siblings, 1 reply; 13+ messages in thread
From: Kalvas, Taneli @ 2015-03-10  7:32 UTC (permalink / raw)
  To: alsa-devel

>> By looking at the receiving end bytes it looks exactly like that has happened.
>
> This pretty much proves that this is a bug in the device firmware.
> 
> You might try contacting Miditech ...

I have sent an email to them, but as we all know, most probably they are not going to even answer me. 

This is a common problem with many devices across several brands of devices and influences not only Linux but also other systems (see for example a  list by wabbiguy at http://forum.highlyliquid.com/archive/index.php/t-500.html). There seems to be some user space software, which provide the same type of delay that I used to work around this problem. In my opinion this should not be done in user space, even though I tested that it works. I am going to propose something wild: What do you think about a possibility for a customized driver for this class of hardware (I mean usb compliant midi interfaces with broken output ring buffer)? If the kernel driver would use timing utilities to regulate the speed of data written to the device, this could provide a dirty fix for this type of hardware. It
  wouldn't be the first driver workaround for broken hardware. Does this sound doable? I think a relatively small amount of code could provide a fix for several different devices and therefore increa
 se their value for their users.

>>>> Is there a way to connect two programs via a virtual RawMIDI port so
>>>> that I could test without using the hardware?
>>>
>>> Load the snd-virmidi module, and connect two of its ports with aconnect.
>>
>> I did this and by using the virtual ports the behaviour is more
>> reasonable, but still not as expected. Everything works ok as long as
>> the message length is less than or equal to the buffer size (4096).
>> With message sizes larger than that the writing end still claims it
>> has sent everything, as it should do because the port is opened in
>> blocking mode. On the reading end I can see that some data is missing
>> and xruns are reported.
>
> Oops, using snd-virmidi this way also goes through the sequencer, which
> does not do blocking.
> 
> There is no other way to get a virtual RawMIDI port.
> 
> However, the driver was tested with lots of other devices, and huge
> SysEx messages have this problem only with your device.

Ok. You have me convinced.

Taneli

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RawMIDI behaviour with MidiFace 4x4
  2015-03-10  7:32       ` Kalvas, Taneli
@ 2015-03-10  8:02         ` Clemens Ladisch
  2015-03-24  6:42           ` Kalvas, Taneli
  0 siblings, 1 reply; 13+ messages in thread
From: Clemens Ladisch @ 2015-03-10  8:02 UTC (permalink / raw)
  To: Kalvas, Taneli, alsa-devel

Kalvas, Taneli wrote:
> This is a common problem with many devices across several brands of
> devices and influences not only Linux but also other systems (see for
> example a list by wabbiguy at http://forum.highlyliquid.com/archive/index.php/t-500.html).

These devices use different firmwares and drivers, and as far as I know,
work flawlessly in Linux.  This appears to be a problem with the Windows
MIDI framework.  (Apparently, it behaves like the ALSA sequencer, i.e.,
drops data when its internal buffer overflows; there is no blocking API
like snd_rawmidi_*.)

> What do you think about a possibility for a customized driver for this
> class of hardware (I mean usb compliant midi interfaces with broken
> output ring buffer)?

Such a customization would be possible.  But it's unlikely that I will
find time in the near future.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RawMIDI behaviour with MidiFace 4x4
  2015-03-10  8:02         ` Clemens Ladisch
@ 2015-03-24  6:42           ` Kalvas, Taneli
  2015-03-25 21:45             ` Clemens Ladisch
  0 siblings, 1 reply; 13+ messages in thread
From: Kalvas, Taneli @ 2015-03-24  6:42 UTC (permalink / raw)
  To: Clemens Ladisch, alsa-devel

I am back with the Miditech MidiFace 4x4 issue. I communicated back and forth for the last two weeks with the customer support of Miditech The full communication is attached below. The long story made short:

1. I showed them that the device fails long SysEx transfers both in Linux and in Windows (using MIDI-OX software) if the writing to device isn't delayed.
2. I told them that the MicroKORG synthesizer patch editor is unable to communicate through their device.
3. They are blaming the MicroKORG software and/or the Windows MIDI driver. No explanation was given for the results achieved with MIDI-OX or for the results in Linux.
4. They say there is no problems in the hardware, but still they say that to fix the problem they should make a separate Windows driver for their hardware.

>From the last email I got the impression that they are not going to do anything ("Here is the final answer..."). I will still try to push them a bit, but I believe making a customized Linux kernel driver is the only way.

What is the policy with external contributions for the snd-usb-audio/midi? I haven't fiddled with linux kernel before, but I might try to produce something. Do you have any pointers on where to start or should I just start reading through the code. From my first session with the usb documents ("USB MIDI Devices 1.0") and the kernel code I could not find the flow-control for the midi interface buffer in either one. Is the flow control described somewhere in the code and/or documents in a more general level? General purpose usb driver?

Taneli



The communication with Miditech:
----------------

Miditech Support GMX [miditech@gmx.net]
[Reply All]
 
Monday, March 23, 2015 9:30 PM
Hi again,
here is the final answer from our taiwanese engineer:

It is not the problem of Midiface 4x4.
It is problem of windows driver's buffer size setting.
There is not any buffer size setting in Midiface 4x4 hardware.
It is the windows driver's problem, it needs to set the buffer size or use
the default size to the windows driver first.
MicroKORG uses his own driver, it may set the buffer size to 1024 or above
before.
So we have nothing to do with the Midiface 4x4 now.
To fix the problem, we need to design our own driver for Midiface 4x4, which
we don't have it yet, instead of using the common windows driver.

Hope this will help you,
Best regards,
Miditech Support
Miditech Support GMX [miditech@gmx.net]
[Reply All]
 
Thursday, March 19, 2015 9:14 PM
Hello again,
thanks for your information. Now i can visualise more, what you are doing
:-)

Maybe this problem has something to do with the transmission speed. I know
that Sysex problems are mostly caused by the transfer speed.
Also I know, that the Midisport series interfaces are perfect for Sysex
transfers and nearly work everytime well. But they are much more expensive than our interfaces.

But do you know another "class compliant" interface, which works for this?

Maybe the Microkorg editor itself especially has a problem with our
Midiface, or with class compliant devices.

Best regards,
Miditech Support
Kalvas, Taneli
[Reply All]
Lähetetyt
Thursday, March 19, 2015 2:34 PM
Hi!

What I am trying to achieve with the SysEx transmission is editing, saving and loading of the synthesizer patches. The dedicated editor software / librarian allows to edit  the patches on a PC and transfer the patch to the synthesizer, while editing making the work flow fluent. Each transfer is 294 bytes and therefore does not work. If I use MIDI-OX with delay functionality necessary to get the hardware working, I can not edit the patches on a PC. I can only save and load.

I personally don't have other interfaces, but I borrowed a M-audio Midisport 2x2 and it worked with the MicroKORG editor software as expected.

For everything else than the SysEx transfers, the Midiface device works as expected. It works in Windows and in Linux, where I use the Rosegarden sequencer.

Taneli

--
Taneli Kalvas
Ph.D., Researcher
Department of Physics, room FL114
P.O. Box 35 (YFL)
40014 University of Jyväskylä, Finland
Mobile: +358-44-314-1602
Fax:    +358-14-617-411
Email:  taneli.kalvas@jyu.fi
Miditech Support GMX [miditech@gmx.net]
[Reply All]
 
Thursday, March 19, 2015 9:39 AM
Hello again,
I send you issue again to our developers in Taiwan and hope to get a
statement of them soon.

I have some questions left please: What do you do with this Sysex
transmission "in practical"?

Do you try to make a MIDI dump from your Microkorg into a Sequenzer to save
the user settings?
Or a similar reason, what are you doing?

I do not really understand what you want to do in practical. Did you try
another class compliant MIDI interface?
What type? Did it work different? What MIDI music software do you use? Linux
based systems and music software?

Best regards,
Miditech Support
Kalvas, Taneli
[Reply All]
Lähetetyt
Thursday, March 19, 2015 9:17 AM
Hi!

I hope they could reproduce my test with the MIDI-OX. I bought my unit online from Thomann in Germany and my 30 day returns period has already passed. I also have a strong belief that the unit is not defect. It is highly improbable that the firmware would be broken like that on a single unit.

Taneli

--
Taneli Kalvas
Ph.D., Researcher
Department of Physics, room FL114
P.O. Box 35 (YFL)
40014 University of Jyväskylä, Finland
Mobile: +358-44-314-1602
Fax:    +358-14-617-411
Email:  taneli.kalvas@jyu.fi
Miditech Support GMX [miditech@gmx.net]
[Reply All]
 
Wednesday, March 18, 2015 9:18 PM
Sorry,
I did not get any additional reaction from our taiwanese developers. But of
course, they cannot test the compatibilty to every music and MIDI hardware which is available.

Because you are the first customer with Sysex Problems with the Midiface
4x4, is there a possibility to change it at your music shop and try another one. Maybe only your unit is
defect.

Best regards,
Miditech Support
Kalvas, Taneli
[Reply All]
Lähetetyt
Wednesday, March 18, 2015 2:16 PM
Hi!

I would like inquire if any progress has been made with the issue I pointed out.

Best regards,
Taneli Kalvas

--
Taneli Kalvas
Ph.D., Researcher
Department of Physics, room FL114
P.O. Box 35 (YFL)
40014 University of Jyväskylä, Finland
Mobile: +358-44-314-1602
Fax:    +358-14-617-411
Email:  taneli.kalvas@jyu.fi
Kalvas, Taneli
[Reply All]
Lähetetyt
Wednesday, March 11, 2015 7:59 PM
Hi!

I wasn't aware of the MIDI-OX software. Thank you for pointing that out. It is possible to do exactly the same tests in MIDI-OX that I did in Linux.

In the first scenario I transport 144 bytes of Sysex data through the Midiface 4x4. Everything works as expected. I have also shown the transport options of the software and you can see that the buffer size used by the program is 128. Everything works because all of the data fits in the buffer in the Midiface hardware. This scenario is shown in scen1_works.png.

In the second scenario I tried to transport 512 bytes of data. MIDI-OX breaks this into four blocks and feeds them through the Windows driver to the Midiface 4x4, which causes overwriting of the hardware buffer I suspect. The data becomes corrupted and some data is lost due to the overwriting. This is shown in scen2_fails.png. The MIDI-OX software contains an option to slow down the transport of data. I modified the second scenario by adding 50 ms delay after each 128 byte block. This is more than 320 us*128 = 41 ms and therefore the hardware has enough time to empty its internal buffer before new data arrives. This is shown in scen2_works.png. This delaying is exactly the same thing that I did in Linux as I explained before.

This does not prove that the hardware works according to specification. Most software do not have such delaying functionality because it shouldn't be needed. MIDI-OX is specialized software in this sense. For example the MicroKORG patch editor I am trying to use does not have it. It relies on the Windows driver and the hardware to perform according to specification and provide flow-control information without relying on timing on the user space software. I have confirmed that the MicroKORG patch editor works correctly with different class-compliant hardware on the same computer. The problem seems to be therefore in the Midiface hardware.

My guess is that there is a bug in the mechanism which provides information for the operating system driver about the output buffer fill level status in the Midiface hardware. I hope you can pinpoint the problem and make an update on the firmware.

Best regards,
Taneli Kalvas

--
Taneli Kalvas
Ph.D., Researcher
Department of Physics, room FL114
P.O. Box 35 (YFL)
40014 University of Jyväskylä, Finland
Mobile: +358-44-314-1602
Fax:    +358-14-617-411
Email:  taneli.kalvas@jyu.fi
Miditech Support GMX [miditech@gmx.net]
[Reply All]
 
Wednesday, March 11, 2015 9:01 AM
Hello,
our engineer in Taiwan tested the MIdiface 4x4 successful with a Sysex data
larger than 256 bytes. thats what he wrote yesterday:

My guys tested MIDIFACE 4x4 and found no problem. Please see attached
picture. Can you please ask customer to provide more information like
MIDI-OX screen like we did? Thanks

With Best Regards

Maybe you can try this again and also make a MIDI OX Screenshot of your
failure?

Best regards,
Miditech Support
Miditech Support GMX [miditech@gmx.net]
[Reply All]
 
Tuesday, March 10, 2015 7:47 PM
Hello and thanks for your explanations.
We gave it to our taiwaneese engineers, if they find a problem or solution,
maybe we can fix this with a firmware update for the Midiface 4x4.

Best regards,
Miditech Support
Kalvas, Taneli
[Reply All]
Lähetetyt
Tuesday, March 10, 2015 10:59 AM
Hello!

I am trying to communicate with a MicroKORG synthesizer. The complete data dump for this synth is roughly 32 kbytes. I tried the MicroKORG editor first under Windows, but after experiencing problems I switched to Linux, which provides better programming utilities for studying the problems with the communication.

For my studies I connected the output of port 1 to input of port 2 on the hardware and had two programs running. One sending out data and one listening on the other port. For data less than 256 bytes everything works as it should. With larger data sizes part of the data disappears and the sequence gets mangled (data is corrupted). By looking at the data received it looks like if the ring buffer in the device gets overwritten before the bytes get through the MIDI out port.

After this I made another test: I modified the program to write to the midi output port in N=128 byte blocks and added a 352*N mikrosecond delay after each block. This delay allows time for the Midiface hardware to empty its buffer before new data if written in. I believe this test shows that the device works otherwise as it should, but it fails to inform the usb/midi driver of the computer about the filled up buffer.

Unfortunately I am only able to do this delaying in my own software and therefore I can not fix the problem with hardware when it is being used by other programs.

Best regards,
Taneli Kalvas

--
Taneli Kalvas
Ph.D., Researcher
Department of Physics, room FL114
P.O. Box 35 (YFL)
40014 University of Jyväskylä, Finland
Mobile: +358-44-314-1602
Fax:    +358-14-617-411
Email:  taneli.kalvas@jyu.fi
Miditech Support GMX [miditech@gmx.net]
[Reply All]
 
Tuesday, March 10, 2015 10:37 AM
Hello,
what Sysex file do you try to send? And with which sequenzer/software?
How can you check how the handling of a Sysex file larger 245 bytes is?

Best regards,
Miditech Support
Kalvas, Taneli
[Reply] [Reply All] [Forward]
Actions
To:
 info@miditech.de 
Lähetetyt
Tuesday, March 10, 2015 1:06 AM
Dear Sir/Madam,

I bought a Midiface 4x4 and have been trying to use the interface to transfer SysEx patches to/from a synthesizer. The transfer did not work and therefore I started investigating the reasons. In the end I found that the reason for transfer failure was a faulty device firmware, which does not check against filling up the device buffer of the output port. For SysEx patch writes larger than 256 bytes the new data overwrites the device buffer before the overwritten bytes were sent.

1. In my opinion the device does not qualify as "class compliant" midi-usb interface as it is being marketed.
2. I would like to know if there exists an updated firmware driver for the device to fix this issue.

The usb serial name for the device is MIDIPLUS / MIDI4x4 / MIDIPLUS-BC-1A0B-07DA0908-MIDI4x4. The device is branded as "Miditech Midiface 4x4". The device revision number reported by the usb driver is 1.01

Best regards,
Taneli Kalvas

-- 
Taneli Kalvas
Ph.D., Researcher
Department of Physics, room FL114
P.O. Box 35 (YFL)
40014 University of Jyväskylä, Finland
Mobile: +358-44-314-1602
Fax:    +358-14-617-411
Email:  taneli.kalvas@jyu.fi

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RawMIDI behaviour with MidiFace 4x4
  2015-03-24  6:42           ` Kalvas, Taneli
@ 2015-03-25 21:45             ` Clemens Ladisch
  0 siblings, 0 replies; 13+ messages in thread
From: Clemens Ladisch @ 2015-03-25 21:45 UTC (permalink / raw)
  To: Kalvas, Taneli, alsa-devel

Kalvas, Taneli wrote:
> What is the policy with external contributions for the snd-usb-audio/midi?

See Documentation/SubmittingPatches.

> From my first session with the usb documents ("USB MIDI Devices 1.0")
> and the kernel code I could not find the flow-control for the midi
> interface buffer in either one.

The flow control is implicit in the USB bulk transfer protocol, i.e.,
the device must accept a packet only when it can handle it.  The host
controller hardware automatically retries sending until this succeeds.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2015-03-25 21:46 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-07 17:26 RawMIDI behaviour with MidiFace 4x4 Kalvas, Taneli
2015-03-09  8:38 ` Ricard Wanderlof
2015-03-09  8:47   ` Clemens Ladisch
2015-03-09 11:37     ` Kalvas, Taneli
2015-03-09 14:29     ` Ricard Wanderlof
2015-03-09 18:40       ` Clemens Ladisch
2015-03-09  8:43 ` Clemens Ladisch
2015-03-09 19:22   ` Kalvas, Taneli
2015-03-09 21:47     ` Clemens Ladisch
2015-03-10  7:32       ` Kalvas, Taneli
2015-03-10  8:02         ` Clemens Ladisch
2015-03-24  6:42           ` Kalvas, Taneli
2015-03-25 21:45             ` Clemens Ladisch

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.