<div dir="ltr">Hi Miller.<br>Thats very exciting news!<br>Can you give a brief synopsis of what you think the biggest remaining limitations are and a rough timeline as to when a stable multi-instance pdlib would be available for general use?<br>
<br>Thanks again!<br>Rob Bairos.<br><br></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Sun, May 11, 2014 at 3:00 AM, Miller Puckette <span dir="ltr"><<a href="mailto:msp@ucsd.edu" target="_blank">msp@ucsd.edu</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">To Pd developers...<br>
<br>
I've adapted Pd to nternally use a "pdinstance" structure to allow<br>
multiple schedulers (including DSP chains) to run in one address space.<br>
With slight modification (see below) libpd can use this to run separate<br>
patches asynchronously.<br>
<br>
I tried to "instance-ize" all Pd symbols to keep them private but ran into<br>
seemingly insoluble problems, so am leaving all symbols global for now.<br>
(So patches used in pdlib, if they want to be usable in a multiple-instance<br>
scenaro, should protect all send/receive/table/delay/etc named objects with<br>
a $[0-9] somewhere.<br>
<br>
I didn't look hard, but I thnk pdlib now will need a way to send $ arguments<br>
to patches via libpd_openfile() somehow. Also, libpd_init_audio() will want to<br>
make number of channels per-instance, etc. I've put some relevant comments<br>
in the test program I'll include below (and sorry for the length of this<br>
mail!)<br>
<br>
Here's how I modified libpd_wrapper/z_libpd.c:<br>
<br>
55d54<br>
< sys_time = 0;<br>
110c109<br>
< sched_tick(sys_time + sys_time_per_dsp_tick);<br>
---<br>
> sched_tick();<br>
130c129<br>
< sched_tick(sys_time + sys_time_per_dsp_tick); \<br>
---<br>
> sched_tick(); \<br>
<br>
----------------------<br>
and here (sorry again) is the test program, "pdtest2.c" adapted from<br>
libpd-master/samples/c_samples/c/pdtest.c :<br>
---------------------<br>
<br>
#include <stdio.h><br>
#include "z_libpd.h"<br>
#include "m_imp.h"<br>
#define TIMEUNITPERMSEC (32. * 441.)<br>
<br>
void pdprint(const char *s) {<br>
printf("%s", s);<br>
}<br>
<br>
void pdnoteon(int ch, int pitch, int vel) {<br>
printf("noteon: %d %d %d\n", ch, pitch, vel);<br>
}<br>
<br>
int main(int argc, char **argv) {<br>
t_pdinstance *pd1 = pdinstance_new(), *pd2 = pdinstance_new();<br>
if (argc < 3) {<br>
fprintf(stderr, "usage: %s file folder\n", argv[0]);<br>
return -1;<br>
}<br>
<br>
int srate = 44100;<br>
// maybe these two calls should be available per-instnace somehow:<br>
libpd_set_printhook(pdprint);<br>
libpd_set_noteonhook(pdnoteon);<br>
/* set a "current" instance before libpd_init() or else Pd will make<br>
an unnecessary third "default" instance. */<br>
pd_setinstance(pd1);<br>
libpd_init();<br>
/* ... here we'd sure like to be able to have number of channels be<br>
per-nstance. The sample rate is still global within Pd but we might<br>
also consider relaxing that restrction. */<br>
libpd_init_audio(1, 2, srate);<br>
<br>
float inbuf[64], outbuf[128]; // one input channel, two output channels<br>
// block size 64, one tick per buffer<br>
<br>
pd_setinstance(pd1); // talk to first pd instance<br>
<br>
// compute audio [; pd dsp 1(<br>
libpd_start_message(1); // one entry in list<br>
libpd_add_float(1.0f);<br>
libpd_finish_message("pd", "dsp");<br>
<br>
// open patch [; pd open file folder(<br>
libpd_openfile(argv[1], argv[2]);<br>
<br>
pd_setinstance(pd2);<br>
<br>
// compute audio [; pd dsp 1(<br>
libpd_start_message(1); // one entry in list<br>
libpd_add_float(1.0f);<br>
libpd_finish_message("pd", "dsp");<br>
<br>
// open patch [; pd open file folder(<br>
libpd_openfile(argv[1], argv[2]);<br>
<br>
/* the follownig two messages can be sent without setting the pd nstance<br>
and anyhow the symbols are global so they may affect multiple instances.<br>
However, if the messages change anyhing in the pd instacne structure<br>
(DSP state; current time; list of all canvases n our instance) those<br>
changes will apply to the current Pd nstance, so the earlier messages,<br>
for instance, were sensitive to which was the current one.<br>
<br>
Note also that I'm using the fact taht $0 is set to 1003, 1004, ...<br>
as patches are opened -it would be better to opent the patches with<br>
settable $1, etc parameters to libpd_openfile(). */<br>
<br>
// [; pd frequency 1 (<br>
libpd_start_message(1); // one entry in list<br>
libpd_add_float(1.0f);<br>
libpd_finish_message("1003-frequency", "float");<br>
<br>
// [; pd frequency 1 (<br>
libpd_start_message(1); // one entry in list<br>
libpd_add_float(2.0f);<br>
libpd_finish_message("1004-frequency", "float");<br>
<br>
// now run pd for ten seconds (logical time)<br>
int i, j;<br>
for (i = 0; i < 3; i++) {<br>
// fill inbuf here<br>
pd_setinstance(pd1);<br>
libpd_process_float(1, inbuf, outbuf);<br>
if (i < 2)<br>
{<br>
for (j = 0; j < 8; j++)<br>
printf("%f ", outbuf[j]);<br>
printf("\n");<br>
}<br>
pd_setinstance(pd2);<br>
libpd_process_float(1, inbuf, outbuf);<br>
if (i < 2)<br>
{<br>
for (j = 0; j < 8; j++)<br>
printf("%f ", outbuf[j]);<br>
printf("\n");<br>
}<br>
}<br>
<br>
return 0;<br>
}<br>
<br>
----------------------<br>
I replaced "test.c" as follows:<br>
---------------------<br>
<br>
#N canvas 406 290 450 300 10;<br>
#X obj 97 64 loadbang;<br>
#X obj 97 131 print;<br>
#X obj 186 106 dac~;<br>
#X obj 97 107 f 0;<br>
#X obj 128 107 + 1;<br>
#X obj 97 86 metro 2;<br>
#X obj 185 41 r \$0-frequency;<br>
#X obj 188 73 osc~;<br>
#X obj 248 127 print \$0-frequency;<br>
#X obj 248 97 loadbang;<br>
#X connect 0 0 5 0;<br>
#X connect 3 0 1 0;<br>
#X connect 3 0 4 0;<br>
#X connect 4 0 3 1;<br>
#X connect 5 0 3 0;<br>
#X connect 6 0 7 0;<br>
#X connect 6 0 8 0;<br>
#X connect 7 0 2 0;<br>
#X connect 7 0 2 1;<br>
#X connect 9 0 8 0;<br>
<br>
----------------------------<br>
and got this output:<br>
<br>
print: 0<br>
1003-frequency: bang<br>
print: 0<br>
1004-frequency: bang<br>
1003-frequency: 1<br>
1004-frequency: 2<br>
1.000000 1.000000 0.999999 0.999999 0.999998 0.999998 0.999997 0.999997<br>
1.000000 1.000000 0.999998 0.999998 0.999996 0.999996 0.999995 0.999995<br>
print: 1<br>
0.999944 0.999944 0.999943 0.999943 0.999942 0.999942 0.999941 0.999941<br>
print: 1<br>
0.999815 0.999815 0.999810 0.999810 0.999804 0.999804 0.999799 0.999799<br>
print: 2<br>
print: 2<br>
<br>
... Looks like there are 2 schedulers adn DSP chains running :)<br>
<br>
Miller<br>
<br>
<br>
<br>
_______________________________________________<br>
Pd-dev mailing list<br>
<a href="mailto:Pd-dev@iem.at">Pd-dev@iem.at</a><br>
<a href="http://lists.puredata.info/listinfo/pd-dev" target="_blank">http://lists.puredata.info/listinfo/pd-dev</a><br>
</blockquote></div><br></div>