Latenz- und jitterarme MIDI/OSC-Übertragung von Ableton Live zur iPad-App
Zusammenfassung
Ein iPad-Controller für Ableton Live taugt auf der Bühne nur, wenn die Verbindung schnell und stabil ist. Mehr als 10 ms zwischen Berührung und Klang sind bereits spürbar, und visuelles Feedback auf dem iPad sollte innerhalb von 30 ms ankommen. Spezielle Werkzeuge, um das zu messen, gab es nicht. Also habe ich ein Testsystem gebaut und die Verbindung damit Schritt für Schritt optimiert.
Das System bestand aus drei Teilen: einer iPad-App mit Testszenarien, etwa 8 Reglern, die per Multitouch gleichzeitig gedreht werden; einer Mac-App, die jede Nachricht zwischen iPad und Ableton Live weiterleitete und Latenz und Jitter jeder Verbindung in einem Live-Dashboard anzeigte; und einem Python MIDI Remote Script in Ableton Live.
Mit jeder gemessenen Änderung sank die mediane Eingabelatenz vom iPad zu Ableton Live von 27,8 ms auf 4,98 ms. Zusammen mit einer typischen Audio-Interface-Latenz von 4 ms ergibt das 8,98 ms von der Berührung bis zum Klang, innerhalb des Ziels von 10 ms. Der visuelle Round Trip lag bei 9,97 ms, deutlich unter 30 ms.
Die wiederverwendbaren Teile (Netzwerk, Latenzmessung und Bedienelemente) flossen in ein Swift Package für künftige Controller-Apps.
Ergebnisse
- Mediane Eingabelatenz, iPad zu Ableton Live
- 27,8 → 4,98 ms
- Berührung bis Klang, mit 4 ms Audiolatenz
- 8,98 ms
- Ziel: unter 10 ms
- Visueller Round Trip
- 9,97 ms
- Ziel: unter 30 ms
- Run-Loop-Puls. Abletons Remote Scripts verarbeiteten eingehende OSC-Nachrichten nur in einer Run Loop, die etwa alle 100 ms lief. Das verursachte den größten Teil der Verzögerung und das Sägezahnmuster unten. Selbst ein Listener auf die Song-Position kam nur auf 80 ms herunter. Remote Scripts bevorzugen MIDI, also schickte die Mac-App alle 0,1 ms eine MIDI-CC-Nachricht als Puls, und jeder Puls brachte das Script dazu, seine OSC-Warteschlange abzuarbeiten. Die Run Loop sank von etwa 100 ms auf unter 1 ms.
- OSC-Bundles. Schnelle Reglerbewegungen erzeugten Schübe von Nachrichten, die offenbar an eine Grenze von Paketen pro Sekunde stießen und als Wellen in der Latenz sichtbar wurden. Mehrere OSC-Nachrichten in ein Bundle zu packen, senkte die Zahl der Pakete und beseitigte die Wellen.
- 128 Schritte pro Umdrehung. Der Touchscreen des iPads lieferte weit mehr Werte, als irgendjemand hören kann. Jeden Regler auf 128 Schritte pro Umdrehung zu quantisieren, die Auflösung eines MIDI-CC, bedeutete weniger Nachrichten.
- Mac zu Ableton Live
- iPad zu Mac
Vorher: ohne Optimierung, Median 27,8 ms
Nachher: alle drei Schritte, Median 4,98 ms
Eingabelatenz von 50 aufeinanderfolgenden Paketen, während 8 Regler gleichzeitig gedreht werden. Beide Diagramme haben dieselbe Skala.
Daten anzeigen
| Paket | Vorher (ms) | Nachher (ms) | ||
|---|---|---|---|---|
| Mac zu Ableton | iPad zu Mac | Mac zu Ableton | iPad zu Mac | |
| 1 | 3,53 | 2,27 | 6,04 | 2,86 |
| 2 | 0,41 | 2,03 | 2,26 | 1,41 |
| 3 | 0,48 | 1,94 | 1,53 | 1,82 |
| 4 | 0,57 | 1,86 | 1,56 | 1,51 |
| 5 | 40,11 | 1,36 | 3,21 | 1,75 |
| 6 | 40,37 | 2,48 | 4,55 | 0,80 |
| 7 | 40,79 | 2,11 | 0,62 | 1,08 |
| 8 | 37,70 | 1,69 | 1,85 | 12,16 |
| 9 | 38,42 | 4,63 | 0,99 | 1,98 |
| 10 | 34,30 | 4,68 | 1,45 | 1,82 |
| 11 | 34,37 | 4,59 | 3,21 | 1,81 |
| 12 | 31,58 | 3,29 | 2,34 | 2,44 |
| 13 | 31,87 | 2,99 | 0,95 | 1,31 |
| 14 | 28,21 | 2,63 | 3,80 | 1,07 |
| 15 | 28,41 | 2,42 | 0,98 | 1,48 |
| 16 | 23,54 | 3,15 | 4,36 | 1,52 |
| 17 | 23,85 | 2,83 | 0,91 | 2,15 |
| 18 | 23,88 | 2,81 | 5,28 | 3,12 |
| 19 | 20,83 | 1,77 | 3,73 | 1,15 |
| 20 | 20,98 | 2,24 | 4,65 | 1,17 |
| 21 | 16,99 | 2,11 | 1,12 | 1,36 |
| 22 | 17,25 | 2,25 | 7,11 | 2,48 |
| 23 | 13,41 | 1,94 | 8,56 | 3,55 |
| 24 | 9,51 | 1,58 | 6,05 | 1,36 |
| 25 | 9,93 | 2,67 | 3,12 | 1,61 |
| 26 | 5,71 | 2,78 | 3,83 | 1,73 |
| 27 | 2,30 | 2,33 | 4,26 | 1,80 |
| 28 | 39,21 | 2,58 | 8,99 | 2,96 |
| 29 | 36,55 | 4,46 | 9,44 | 2,53 |
| 30 | 32,61 | 4,56 | 2,21 | 1,00 |
| 31 | 28,74 | 4,27 | 4,97 | 1,04 |
| 32 | 29,19 | 3,81 | 5,29 | 1,56 |
| 33 | 25,57 | 3,28 | 1,98 | 0,91 |
| 34 | 21,69 | 3,96 | 0,95 | 1,07 |
| 35 | 22,23 | 3,44 | 2,64 | 2,36 |
| 36 | 18,28 | 3,01 | 9,90 | 1,49 |
| 37 | 10,41 | 3,35 | 10,07 | 1,34 |
| 38 | 10,38 | 3,39 | 6,41 | 2,00 |
| 39 | 8,04 | 1,66 | 3,51 | 1,35 |
| 40 | 1,93 | 3,63 | 3,40 | 1,32 |
| 41 | 43,93 | 4,82 | 4,89 | 1,53 |
| 42 | 45,50 | 4,19 | 1,37 | 1,43 |
| 43 | 42,44 | 3,50 | 2,39 | 1,01 |
| 44 | 38,61 | 3,34 | 9,99 | 0,92 |
| 45 | 34,64 | 3,18 | 3,70 | 1,00 |
| 46 | 30,93 | 2,76 | 5,73 | 1,36 |
| 47 | 31,09 | 2,49 | 9,21 | 1,00 |
| 48 | 27,07 | 2,51 | 1,79 | 1,46 |
| 49 | 22,82 | 2,97 | 4,13 | 3,19 |
| 50 | 18,88 | 2,40 | 0,96 | 1,20 |
Wahl des Übertragungswegs
Bevor ich irgendetwas optimiert habe, habe ich im Testsystem verschiedene Wege verglichen, iPad und Mac zu verbinden:
- Inter-Device MIDI und Bluetooth MIDI (CoreMIDI): stabil, aber jede neue Verbindung musste in macOS von Hand eingerichtet werden.
- Peertalk: 2,5 ms Round Trip, aber über 10 ms unter Last, nicht mehr gepflegt und nicht mit iOS 16 kompatibel.
- Multipeer Connectivity: nie unter 30 ms Round Trip, und es wechselte von selbst den Übertragungsweg, was Jitter von über 10 ms verursachte.
- SwiftyOSC: 50 bis 100 ms, weil es sein Networking auf dem Main Thread ausführte.
- MIDI 2.0: vielversprechend, aber von Ableton Live noch nicht unterstützt.
- SwiftNIO mit OSCCore setzte sich durch: unter 1,5 ms Round Trip zwischen iPad und Mac und auch die niedrigste Latenz auf der Verbindung vom Mac zu Ableton Live.