Rtosc Realtime Open Sound Control
Rtosc Realtime Open Sound Control Mark McCurry 2018 Rtosc - - PowerPoint PPT Presentation
Rtosc Realtime Open Sound Control Mark McCurry 2018 Rtosc - - PowerPoint PPT Presentation
Rtosc Realtime Open Sound Control Rtosc Realtime Open Sound Control Mark McCurry 2018 Rtosc Realtime Open Sound Control Motivation What is OSC? Path + argument types + argument data Types include: i : int32 , s : string , b :
Rtosc Realtime Open Sound Control Motivation
What is OSC?
◮ Path + argument types + argument data ◮ Types include: i:int32, s:string, b:binary-blob, f:float32,
h:int64, t:timetag, d:float64, S:symbol, r:rgb, m:4-byte-MIDI, c:int8, T:true, F:false, N:nil, and I:Inf.
Rtosc Realtime Open Sound Control Motivation
What is OSC?
◮ Message serialization ◮ Semi-complex inter-process communication
Rtosc Realtime Open Sound Control Motivation
What Doesn’t OSC Normally Do?
Rtosc Realtime Open Sound Control Motivation
What Does Rtosc Add?
◮ Low level Serialization (C) ◮ High Level Dispatch/Metadata (C++) ◮ Restricted problem domain
Rtosc Realtime Open Sound Control C core
OSC Serialization
char buffer[256];
Rtosc Realtime Open Sound Control C core
OSC Serialization
char buffer[256]; int ret = rtosc_message(buffer, sizeof(buffer), "/path", "si", "some arguments", 123);
Rtosc Realtime Open Sound Control C core
OSC Serialization
char buffer[256]; int ret = rtosc_message(NULL, 0, "/path", "si", "some arguments", 123);
Rtosc Realtime Open Sound Control C core
OSC Serialization
char buffer[256]; int ret = rtosc_message(buffer, sizeof(buffer), "/path", "si", "some arguments", 123); const char *args = rtosc_argument_string(buffer);
Rtosc Realtime Open Sound Control C core
OSC Serialization
char buffer[256]; int ret = rtosc_message(buffer, sizeof(buffer), "/path", "si", "some arguments", 123); const char *args = rtosc_argument_string(buffer); const char *first_arg = rtosc_argument(buffer, 0).s; int second_arg = rtosc_argument(buffer, 1).i;
Rtosc Realtime Open Sound Control Dispatch API
Working With Messages
◮ Messages need to be dispatched to handle them
Rtosc Realtime Open Sound Control Dispatch API
Working With Messages
◮ Messages need to be dispatched to handle them ◮ ZynAddSubFX has a lot of parameters
Rtosc Realtime Open Sound Control Dispatch API
Working With Messages
◮ Messages need to be dispatched to handle them ◮ ZynAddSubFX has a lot of parameters ◮ Dispatch needs to be fast
Rtosc Realtime Open Sound Control Dispatch API
Dispatch Tree
Message: /foo/bar Tree:-| abc | xxx | yyy | foo(*) +-|qwerty |path |bar(*)
Rtosc Realtime Open Sound Control Dispatch API
Dispatch Example
struct Envelope { float attack, decay, release; };
Rtosc Realtime Open Sound Control Dispatch API
Dispatch Example
struct Envelope { float attack, decay, release; }; rtosc::Ports ports = { {"attack", NULL, NULL, [](const char *msg, rtosc::RtData &rt) { }}, };
Rtosc Realtime Open Sound Control Dispatch API
Dispatch Example
struct Envelope { float attack, decay, release; }; rtosc::Ports ports = { {"attack:f", NULL, NULL, [](const char *msg, rtosc::RtData &rt) { Envelope &obj = *(Envelope*)rt.obj;
- bj.attack = rtosc_argument(msg, 0).f;
}}, };
Rtosc Realtime Open Sound Control Dispatch API
Dispatch Example
struct Envelope { float attack, decay, release; }; rtosc::Ports ports = { {"attack:f", ":max\0=15\0", NULL, [](const char *msg, rtosc::RtData &rt) { Envelope &obj = *(Envelope*)rt.obj;
- bj.attack = rtosc_argument(msg, 0).f;
}}, };
Rtosc Realtime Open Sound Control Dispatch API
Dispatch Example
struct Envelope { float attack, decay, release; }; #define rObject Envelope rtosc::Ports ports = { rParamF(attack, rLinear(0, 15), rMap(unit, sec), "Attack Time"), };
Rtosc Realtime Open Sound Control Dispatch API
Dispatch Example
struct Envelope { float attack, decay, release; }; #define rObject Envelope rtosc::Ports ports = { rParamF(attack, rLinear(0, 15), rMap(unit, sec), "Attack Time"), rParamF(decay, rLinear(0, 15), rMap(unit, sec), "Decay Time"), rParamF(release, rLinear(0, 15), rMap(unit, sec), "Release Time"), };
Rtosc Realtime Open Sound Control Dispatch API Metadata
Metadata
◮ Minimum/Maximum ◮ Linear/Log scaling ◮ Documentation strings ◮ Units ◮ Option symbol ⇀ value mappings
Rtosc Realtime Open Sound Control Dispatch API Metadata
Metadata
◮ Reflection ◮ Avoids repetition ◮ Keeps information near code use
Rtosc Realtime Open Sound Control Dispatch API Metadata
Metadata Improvements
◮ osc-doc API reference ◮ Learning MIDI/Plugin-host bindings ◮ Reuse of metadata in generating the GUI
Rtosc Realtime Open Sound Control Dispatch API Speed
Rtosc Performance
◮ Rtosc Is fast
Rtosc Realtime Open Sound Control Dispatch API Speed
Rtosc Performance
◮ Rtosc Is fast ◮ No really
Rtosc Realtime Open Sound Control Dispatch API Speed
Sonic Pi - Integration
Impl per op
- ps per second
speedup Encoding an average message fast osc 1.2 us 800,000 9.6x samsosc 3.8 us 260,000 3.1x
- sc-ruby
12 us 83,000 – Decoding an average message fast osc 0.6 us 1,700,000 50x samsosc 4.7 us 230,000 7.4x
- sc-ruby
29 us 34,000 –
Rtosc Realtime Open Sound Control Dispatch API Speed
Liblo point of comparison
Impl. per op
- ps per second
speedup Decoding an average message liblo 218 ns 4,600,000
- rtosc
53 ns 19,000,000 4.1x Encoding an average message liblo 383 ns 2,600,000
- rtosc
125 ns 8,000,000 3.1x Dispatch message on single layer liblo 530 ns 1,900,000
- rtosc
54 ns 19,000,000 10x
Rtosc Realtime Open Sound Control Dispatch API Speed
Liblo algorithm scaling
ZynAddSubFX has:
◮ 3,805,225 unique OSC paths ◮ e.g. /part1/kit5/adpars/VoicePar7/AmpLfo/Pfreq ◮ An average depth of 6.11 subpaths ◮ With minimal hashing an average of 6.11 matches are needed
for rtosc, and 3,805,225 for liblo
Rtosc Realtime Open Sound Control Dispatch API Speed
Liblo algorithm scaling
◮ Liblo match time: 18.3 ms ◮ Rtosc match time: 380 ns
Rtosc Realtime Open Sound Control Dispatch API Speed
Liblo algorithm scaling
◮ Liblo match time: 18.3 ms ◮ Rtosc match time: 380 ns ◮ Liblo: ≈55 messages per second ◮ Rtosc: ≈2,600,000 messages per second
Rtosc Realtime Open Sound Control Dispatch API Speed
Discussion of Trade offs
◮ Fast, but maintainable
Rtosc Realtime Open Sound Control Dispatch API Speed
A comparison
#d e f i n e rObject LFOParams #undef rChangeCb #d e f i n e rChangeCb i f ( obj− >time ) { obj− >last update timestamp = obj− >time− >time ( ) ; } s t a t i c const r t o s c : : Ports p o r t s = { r S e l f (LFOParams ) , rPaste , rOption ( loc , rProp ( i n t e r n a l ) , rOptions ( ad global amp , a d g l o b a l f r e q , a d g l o b a l f i l t e r , ad voice amp , a d v o i c e f r e q , a d v o i c e f i l t e r , u n s p e c i f i e d ) , ” l o c a t i o n
- f
the f i l t e r ”) , rParamF ( Pfreq , rShort (” f r e q ”) , r L i n e a r ( 0 . 0 , 1 . 0 ) , rDefaultDepends ( l o c ) , r P r e s e t ( ad global amp , 0x1 .42850 ap −1) , // 80 r P r e s e t ( a d g l o b a l f r e q , 0x1 .1 a3468p −1) , // 70 r P r e s e t ( a d g l o b a l f i l t e r , 0x1 .42850 ap −1) , r P r e s e t ( ad voice amp , 0x1 .6 ad5acp −1) , // 90 r P r e s e t ( a d v o i c e f r e q , 0x1 .93264 cp −2) , // 50 r P r e s e t ( a d v o i c e f i l t e r , 0x1 .93264 cp −2) , ” frequency
- f LFO\n”
” l f o frequency = (2ˆ(10∗ Pfreq )−1)/12 ∗ s t r e t c h \n” ” true frequency i s [ 0 , 8 5 . 3 3 ] Hz”) , rParamZyn ( P i n t e n s i t y , rShort (” depth ”) , rDefaultDepends ( l o c ) , r D e f a u l t (0) , r P r e s e t ( ad voice amp , 32) , r P r e s e t ( a d v o i c e f r e q , 40) , r P r e s e t ( a d v o i c e f i l t e r , 20) , ” I n t e n s i t y
- f LFO”) ,
rParamZyn ( Pstartphase , rShort (” s t a r t ”) , r S p e c i a l ( random ) , rDefaultDepends ( l o c ) , r D e f a u l t (64) , r P r e s e t ( a d v o i c e f r e q , 0) , ” S t a r t i n g Phase ”) , rOption ( PLFOtype , rShort (” type ”) , rOptions ( sine , t r i a n g l e , square , up , down , exp1 , exp2 ) , r D e f a u l t ( s i n e ) , ”Shape
- f LFO”) ,
rParamZyn ( Prandomness , rShort (” a . r . ” ) , r S p e c i a l ( d i s a b l e ) , r D e f a u l t (0) , ” Amplitude Randomness ( c a l c u l a t e d uniformly at each c y c l e )”) , rParamZyn ( Pfreqrand , rShort (” f . r . ” ) , r S p e c i a l ( d i s a b l e ) , r D e f a u l t (0) , ” Frequency Randomness ( c a l c u l a t e d uniformly at each c y c l e )”) , rParamZyn ( Pdelay , rShort (” delay ”) , r S p e c i a l ( d i s a b l e ) , rDefaultDepends ( l o c ) , r D e f a u l t (0) , r P r e s e t ( ad voice amp , 30) , ” Delay b e fo re LFO s t a r t \n0 . . 4 second delay ”) , rToggle ( Pcontinous , rShort (” c ”) , r D e f a u l t ( f a l s e ) , ” Enable f o r g l o b a l
- p e r a ti o n ”) ,
rParamZyn ( Pstretch , rShort (” s t r ”) , rCentered , r D e f a u l t (64) , ”Note frequency s t r e t c h ”) , }; #undef rChangeCb
s t r i n g InterChange : : r e s o l v e E n v e l o p e ( CommandBlock ∗ getData ) { i n t value = l r i n t ( getData− >data . value ) ; bool w r i t e = ( getData− >data . type & 0x40 ) > 0; unsigned char c o n t r o l = getData− >data . c o n t r o l ; unsigned char npart = getData− >data . part ; unsigned char k i t i t e m = getData− >data . k i t ; unsigned char engine = getData− >data . engine ; unsigned char i n s e r t = getData− >data . i n s e r t ; unsigned char insertParam = getData− >data . parameter ; i n t par2 = getData− >data . par2 ; s t r i n g env ; s t r i n g name ; i f ( engine == 0) name = ” AddSynth ”; e l s e i f ( engine == 1) name = ” SubSynth ”; e l s e i f ( engine == 2) name = ” PadSynth ”; e l s e i f ( engine >= 0x80 ) { name = ” Add Voice ”; i n t nvoice = engine & 0 x3f ; name += t o s t r i n g ( nvoice + 1 ) ; i f ( engine >= 0xC0 ) name += ” Modulator ”; } switch ( insertParam ) { case 0: env = ” Amp”; break ; case 1: env = ” Freq ”; break ; case 2: env = ” F i l t ”; break ; case 3: env = ” B. Width ”; break ; } i f ( i n s e r t == 3) { i f ( ! w r i t e ) { r e t u r n (” Freemode add/remove i s w r i t e- nly .
- r
Rtosc Realtime Open Sound Control Dispatch API Speed
Current/Future Work
◮ Automations ◮ Automated Analysis of Trees ◮ Faster message encode/decode ◮ More standardized metadata
Rtosc Realtime Open Sound Control Dispatch API Speed
Conclusions
Rtosc is:
◮ A way to handle OSC Inside RT apps ◮ A library designed to retrofit existing apps ◮ Powerful thanks to low level API and metadata powered high
level
◮ Maintainable ◮ Fast
Rtosc Realtime Open Sound Control Dispatch API Speed