alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* need help diagnosing USB MIDI latency problem with MPD16
@ 2010-09-14 23:36 Krzysztof Foltman
  0 siblings, 0 replies; only message in thread
From: Krzysztof Foltman @ 2010-09-14 23:36 UTC (permalink / raw)
  To: alsa-devel

[-- Attachment #1: Type: text/plain, Size: 2457 bytes --]

  Hello,

Some time ago, I wrote the Akai MPD16 protocol handlers (input/output) 
for the USB MIDI driver. Unfortunately, the kernel driver seems to 
suffer from a rather embarrassing input latency, it looks like the MIDI 
event timing granularity is >100ms (so the latency is variable, making 
the pad practically useless except if a rhythm is played with the rate 
matching the polling rate!). At the same time, a simple Python based 
contraption using libusb and bulkRead in a while loop, gets much better 
results. The same USB MIDI driver in the same kernel and PC doesn't have 
noticeable problems with class-compliant E-Mu Xboard25 connected to the 
same USB port.

Both devices use endpoints in bulk mode. I've attached the excerpts of 
lsusb -v output for both devices - the only differences are:

1) the Akai device isn't class compliant,
2) the E-mu device has one pair of inputs/outputs, the Akai has two 
(control/configuration and MIDI proper)
3) the maximum packet length is 32 for E-mu, 64 for Akai.

When I enabled logging in midi.c (#define DUMP_PACKETS), it looks like 
the device is returning data packets rather infrequently, as a single 
packet often contains multiple events (up to 3) when two pads are 
pressed in rapid succession. So, it looks like a problem outside of my 
snd_usbmidi_akai_input.

One thing that *does* help, though, is disabling the 'control' port by 
adding endpoints[0].in_cables = 0; in Akai quirk handling in 
snd_usbmidi_create - when input from the control port is not polled, the 
choppiness disappears completely. I'm guessing that the device itself 
(or something in between) has some problems having to handle the URBs 
for both endpoints, and that perhaps the IN/NAK exchange on a "control" 
endpoint causes the device's microcontroller (or something else?) to 
stall for a while. However, in that case, a proper solution (one that 
doesn't involve sacrificing the ability to use control port for 
configuration) would involve submitting URBs for the control input 
endpoint only when control port is open on ALSA side, and cancelling 
them when the port is closed. However, that sounds pretty invasive.

Any hints? The device in question is rather uncommon and hasn't been 
supported for a while, so refactoring the whole USB MIDI driver to 
accommodate it doesn't sound like a great idea - but still, the latency 
thing sucks pretty bad for a drumming-oriented device!

Thanks in advance,
Krzysztof


[-- Attachment #2: xboard.usb --]
[-- Type: text/plain, Size: 4746 bytes --]

Bus 005 Device 003: ID 041e:3f00 Creative Technology, Ltd 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x041e Creative Technology, Ltd
  idProduct          0x3f00 
  bcdDevice            0.47
  iManufacturer           1 E-MU Systems, Inc.
  iProduct                2 E-MU Xboard25
  iSerial                 3 E-MU-62-3F00-07D60505-90185-98
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength          101
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xc0
      Self Powered
    MaxPower              250mA
    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           37
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               1 Embedded
        bJackID                 1
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               2 External
        bJackID                 2
        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                   0 
      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 
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0020  1x 32 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
        MIDIStreaming Endpoint Descriptor:
          bLength                 5
          bDescriptorType        37
          bDescriptorSubtype      1 (GENERAL)
          bNumEmbMIDIJack         1
          baAssocJackID( 0)       1
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0020  1x 32 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
        MIDIStreaming Endpoint Descriptor:
          bLength                 5
          bDescriptorType        37
          bDescriptorSubtype      1 (GENERAL)
          bNumEmbMIDIJack         1
          baAssocJackID( 0)       3
Device Status:     0x0000
  (Bus Powered)


[-- Attachment #3: akai.usb --]
[-- Type: text/plain, Size: 2678 bytes --]

Bus 005 Device 006: ID 09e8:0062 AKAI  Professional M.I. Corp. 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass          255 Vendor Specific Class
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0         8
  idVendor           0x09e8 AKAI  Professional M.I. Corp.
  idProduct          0x0062 
  bcdDevice            1.00
  iManufacturer           1 
  iProduct                2 
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           46
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          3 
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           4
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0 
      bInterfaceProtocol    255 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1


[-- Attachment #4: akai.py --]
[-- Type: text/x-python, Size: 1907 bytes --]

import usb
import alsaseq

mpd16 = None

idVendor = 0x09e8
idProduct = 0x0062

for bus in usb.busses():
    for device in bus.devices:
        if device.idVendor == idVendor and device.idProduct == idProduct:
            mpd16 = device
            break

if mpd16 is None:
    raise ValueError, "No MPD16 found"

conf = mpd16.configurations[0]
iface = conf.interfaces[0][0]

midiept = None
for ept in iface.endpoints:
    if ept.address == 0x82:
        midiept = ept
        break
if midiept is None:
    raise ValueError, "MIDI endpoint not found"
    
dev = mpd16.open()
dev.setConfiguration(mpd16.configurations[0])
dev.claimInterface(0)
dev.setAltInterface(0)
#dev.reset()

#print "MPD16", dir(mpd16)
#print "Config", dir(conf)
#print "Iface", dir(iface)
#print dev.getString(2, 200)
#print midiept.maxPacketSize
alsaseq.client("MPD16", 0, 1, False)
while True:
    data = dev.bulkRead(midiept.address, midiept.maxPacketSize, 0)
    if len(data) == 2:
        continue
    pos = 0
    while pos < len(data):
        elen = data[pos] - 32
        edata = data[pos + 1 : pos + 1 + elen]
        channel = edata[0] & 0x0F
        if edata[0] >= 0x90 and edata[0] <= 0x9F:
            if edata[2] > 0:
                alsaseq.output( (alsaseq.SND_SEQ_EVENT_NOTEON, 1, 0, 253, (0, 0), (0, 0), (0, 0), (channel, edata[1], edata[2], 0, 0)))
            else:
                alsaseq.output( (alsaseq.SND_SEQ_EVENT_NOTEOFF, 1, 0, 253, (0, 0), (0, 0), (0, 0), (channel, edata[1], 0, 0, 0)))
        if edata[0] >= 0xA0 and edata[0] <= 0xAF:
            alsaseq.output( (alsaseq.SND_SEQ_EVENT_KEYPRESS, 1, 0, 253, (0, 0), (0, 0), (0, 0), (channel, edata[1], edata[2], 0, 0)))
        if edata[0] >= 0xB0 and edata[0] <= 0xBF:
            alsaseq.output( (alsaseq.SND_SEQ_EVENT_CONTROLLER, 1, 0, 253, (0, 0), (0, 0), (0, 0), (channel, 0, 0, 0, edata[1], edata[2])))
        pos += 1 + elen
dev.releaseInterface()

[-- Attachment #5: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2010-09-14 23:37 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-14 23:36 need help diagnosing USB MIDI latency problem with MPD16 Krzysztof Foltman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).