[alsa-devel] RawMIDI behaviour with MidiFace 4x4
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
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 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
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
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 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
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
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.
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
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 increase 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
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
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
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
participants (3)
-
Clemens Ladisch
-
Kalvas, Taneli
-
Ricard Wanderlof