Title: Detecting xruns in process callback · Issue #81 · spatialaudio/jackclient-python · GitHub
Open Graph Title: Detecting xruns in process callback · Issue #81 · spatialaudio/jackclient-python
X Title: Detecting xruns in process callback · Issue #81 · spatialaudio/jackclient-python
Description: 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 MID...
Open Graph Description: 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 th...
X Description: 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 wor...
Opengraph URL: https://github.com/spatialaudio/jackclient-python/issues/81
X: @github
Domain: patch-diff.githubusercontent.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Detecting xruns in process callback","articleBody":"Hi and thanks for the great library, been using it for years!\r\n\r\n**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:\r\n\r\n```python\r\njack_midi_event_write = jack._lib.jack_midi_event_write\r\n\r\njack_port_get_buffer = jack._lib.jack_port_get_buffer\r\n\r\n\r\nclass Process:\r\n __slots__ = ('_before', '_buffer', '_client', '_port', '_xrun')\r\n\r\n def __init__(self, client: jack.Client, port: jack.OwnMidiPort) -\u003e None:\r\n self._before = 0;\r\n self._buffer = jack.RingBuffer(2 ** 8)\r\n self._xrun = threading.Event()\r\n self._client = client\r\n self._port = port\r\n\r\n def process(self, frames: int) -\u003e None:\r\n xrun = self._xrun\r\n xrun_set = xrun.is_set()\r\n port = self._port\r\n client = port._client\r\n last_frame_time = client.last_frame_time\r\n blocksize = client.blocksize\r\n\r\n if not xrun_set and last_frame_time - blocksize == self._before:\r\n port.clear_buffer()\r\n if xrun_set:\r\n xrun.clear()\r\n\r\n self._before = last_frame_time\r\n src_buffer = self._buffer\r\n space = src_buffer.read_space\r\n\r\n if space != 0:\r\n data = src_buffer.read(space)\r\n dst_buffer = jack_port_get_buffer(port._ptr, blocksize)\r\n i = 0\r\n while i != space:\r\n jack_midi_event_write(dst_buffer, 0, data[i : i + 3], 3)\r\n i += 3\r\n\r\n def handle_xrun(self, delay_usec: float) -\u003e None:\r\n self._xrun.set()\r\n\r\n def _append(self, event: Tuple[int, int, int]) -\u003e None:\r\n self._buffer.write(bytes(event))\r\n\r\n def note_on(self, note: int) -\u003e None:\r\n self._append((0x99, note, 100))\r\n\r\n def note_off(self, note: int) -\u003e None:\r\n self._append((0x89, note, 0))\r\n```\r\nI'm doing two things:\r\n\r\n1. I'm comparing `last_frame_time - blocksize` to the `last_frame_time` on the previous process callback.\r\n\r\n2. Using the `set_xrun_callback` to set a `threading.Event()`\r\n\r\nI'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++.\r\n\r\nThanks.\r\n","author":{"url":"https://github.com/dj-foxxy","@type":"Person","name":"dj-foxxy"},"datePublished":"2020-01-23T11:09:08.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":5},"url":"https://github.com/81/jackclient-python/issues/81"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:18b807be-a396-63c2-359e-955ef064a428 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | ED56:3461FF:EAA2DA:132024F:6976D229 |
| html-safe-nonce | 53190cffc3b1ae15744cab52493694f14439ec8dda4424321fc96d85b3b34d31 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFRDU2OjM0NjFGRjpFQUEyREE6MTMyMDI0Rjo2OTc2RDIyOSIsInZpc2l0b3JfaWQiOiIxODIwNTY2OTgyNzY0MTg4MjAxIiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 7d89b989637bf578a290c852d4cc81c1de657300e8bbac7d12f81899fafc16dd |
| hovercard-subject-tag | issue:554090030 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/spatialaudio/jackclient-python/81/issue_layout |
| twitter:image | https://opengraph.githubassets.com/004f5b9d24b50f3cab74ba60e6bbd468cd928e5043a30fc53a743d58567631ac/spatialaudio/jackclient-python/issues/81 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/004f5b9d24b50f3cab74ba60e6bbd468cd928e5043a30fc53a743d58567631ac/spatialaudio/jackclient-python/issues/81 |
| og:image:alt | 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 th... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | dj-foxxy |
| hostname | github.com |
| expected-hostname | github.com |
| None | 01d198479908d09a841b2febe8eb105a81af2af7d81830960fe0971e1f4adc09 |
| turbo-cache-control | no-preview |
| go-import | github.com/spatialaudio/jackclient-python git https://github.com/spatialaudio/jackclient-python.git |
| octolytics-dimension-user_id | 7491513 |
| octolytics-dimension-user_login | spatialaudio |
| octolytics-dimension-repository_id | 27613463 |
| octolytics-dimension-repository_nwo | spatialaudio/jackclient-python |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 27613463 |
| octolytics-dimension-repository_network_root_nwo | spatialaudio/jackclient-python |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | f752335dbbea672610081196a1998e39aec5e14b |
| ui-target | canary-2 |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width