Hi and thanks for the great library, been using it for years!
What's the best way to detect if the last process callback lead to an xrun? Here's my use case: I'm sending MIDI, which works 99% of the time. But when an xrun occurs, the MIDI events aren't sent to connected inputs and on the next process callback I clear the buffer and they're lost forever. Here's how I'm currently doing it:
jack_midi_event_write = jack._lib.jack_midi_event_write
jack_port_get_buffer = jack._lib.jack_port_get_buffer
class Process:
__slots__ = ('_before', '_buffer', '_client', '_port', '_xrun')
def __init__(self, client: jack.Client, port: jack.OwnMidiPort) -> None:
self._before = 0;
self._buffer = jack.RingBuffer(2 ** 8)
self._xrun = threading.Event()
self._client = client
self._port = port
def process(self, frames: int) -> None:
xrun = self._xrun
xrun_set = xrun.is_set()
port = self._port
client = port._client
last_frame_time = client.last_frame_time
blocksize = client.blocksize
if not xrun_set and last_frame_time - blocksize == self._before:
port.clear_buffer()
if xrun_set:
xrun.clear()
self._before = last_frame_time
src_buffer = self._buffer
space = src_buffer.read_space
if space != 0:
data = src_buffer.read(space)
dst_buffer = jack_port_get_buffer(port._ptr, blocksize)
i = 0
while i != space:
jack_midi_event_write(dst_buffer, 0, data[i : i + 3], 3)
i += 3
def handle_xrun(self, delay_usec: float) -> None:
self._xrun.set()
def _append(self, event: Tuple[int, int, int]) -> None:
self._buffer.write(bytes(event))
def note_on(self, note: int) -> None:
self._append((0x99, note, 100))
def note_off(self, note: int) -> None:
self._append((0x89, note, 0))
I'm doing two things:
-
I'm comparing last_frame_time - blocksize to the last_frame_time on the previous process callback.
-
Using the set_xrun_callback to set a threading.Event()
I'm not sure if I'm doing any of this correctly, just experimenting to see what works. I know you're not meant to use Python for realtime, but it's working too well to justify moving to C++.
Thanks.
Hi and thanks for the great library, been using it for years!
What's the best way to detect if the last process callback lead to an xrun? Here's my use case: I'm sending MIDI, which works 99% of the time. But when an xrun occurs, the MIDI events aren't sent to connected inputs and on the next process callback I clear the buffer and they're lost forever. Here's how I'm currently doing it:
I'm doing two things:
I'm comparing
last_frame_time - blocksizeto thelast_frame_timeon the previous process callback.Using the
set_xrun_callbackto set athreading.Event()I'm not sure if I'm doing any of this correctly, just experimenting to see what works. I know you're not meant to use Python for realtime, but it's working too well to justify moving to C++.
Thanks.