Question

I'm trying to talk to a Novation Launchpad with pyportmidi. I have noticed that if I just keep sending it instructions using midiOut.WriteShort() it will process the first 100 or so, then loose the rest.

I guess that there is a buffer somewhere that is getting full, and once it's full, instructions are lost. I can work around the problem by adding a time.sleep(.1) after each message, but this obviously makes things very slow. Is there a way to test if the buffer is full, and only sleep if I need to? Or a way to wait for the buffer to empty before I send more data?

No correct solution

OTHER TIPS

When I took a look at the SVN repo, I ran across this in the wrapper code, note the 'Why is bufferSize 0 here?' comment..

def __init__(self, OutputDevice, latency=0):
...stuff...
    # Why is bufferSize 0 here?
    err = Pm_OpenOutput(&(self.midi), self.i, NULL, 0, PmPtr, NULL, latency)

The API documentation shows Pm_OpenOutput having the following signature

PmError Pm_OpenOutput (
    PortMidiStream **stream, 
    PmDeviceID outputDevice, 
    void *outputDriverInfo, 
    long bufferSize, 
    PmTimeProcPtr time_proc, 
    void *time_info, 
    long latency
)

There doesn't appear to be any obvious way to find out the current buffer stack length, and more importantly, it would appear that the Python wrapper ignores the buffer setting entirely anyway.

portmidi.c tells a slightly different tale:

if (bufferSize <= 0) bufferSize = 256; /* default buffer size */
     midi->queue = Pm_QueueCreate(bufferSize, sizeof(PmEvent));
     if (!midi->queue) {
         /* free portMidi data */
         *stream = NULL;
         pm_free(midi); 
         err = pmInsufficientMemory;
         goto error_return;
}

So, 256 is the default. Which would explain why you're running into problems around 100 or so.

However, something to keep in mind - MIDI is extremely slow, 31250 baud (31250 bits per second), since MIDI messages are (usually) 2 bytes (16 bits), that means a maximum of 1953 messages per second. (I may be wrong here, but I'm pretty close if I'm not right)

However, there is hope: A simple fix is, you can sleep down to 2ms on most operating systems without messing things up.

time.sleep(.002) # 2 millisecond sleep

However, since you're using write_short(), that would only give you 500 messages per second. So you might want to do something like have a queue that is polled every .002 seconds for outgoing messages, pop 16 off the stack, write them and then sleep. That way if your whole MIDI stack supports rates that fast you could get 8000 messages per second.

I noticed that in the following code, if I dropped the sleep time lower than .002, no MIDI would be sent at all until I exited the program, then all the events spewed onto the MIDI BUS. So there might be an issue with portmidi rate-limiting, or on OSX.

One other thing to keep in mind, if you're really blasting MIDI - most likely control-change values, if you're modifying something like a High Pass Filter, a value of '1' sounds a lot like '2', so if you make your messages less granular (increment or decrement by 2 or 4), you can cut down the number of messages without having a noticeable difference in the audio. This is a suboptimal solution, and in all likelihood your MIDI stack probably supports much faster than 31250 baud.

Another thing to consider is that if you slave your portmidi application to the MIDI clock, you can get a reliable stream of ticks from the MIDI host, which you could use as the trigger to write MIDI data back out, (no sleeps necessary).

Good luck!

-n

PPQN Clock MIDI 1.0

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top