I think the global shared symbol space will cause some confusion (patches will have to protect their sends and receives, etc., by fabricating local names using '$' characters.
Also, it won't be possible to run several Pds concurrently on several threads - in a threaded environment, each Pd instance will have to lock all others out while it runs. (There might be a fix for that by replacing all static variables in Pd by thread-local ones, but this is untested and I'd hate to do it unless there's a real need for it, since it would involve systematically changing 100s of variable definitions in Pd.)
I'm not sure about timing - that depends partly on the libpd release process that I'm not involved in.
cheers Miller On Mon, May 12, 2014 at 09:45:25AM -0400, Rob Bairos wrote:
Hi Miller. Thats very exciting news! 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?
Thanks again! Rob Bairos.
On Sun, May 11, 2014 at 3:00 AM, Miller Puckette msp@ucsd.edu wrote:
To Pd developers...
I've adapted Pd to nternally use a "pdinstance" structure to allow multiple schedulers (including DSP chains) to run in one address space. With slight modification (see below) libpd can use this to run separate patches asynchronously.
I tried to "instance-ize" all Pd symbols to keep them private but ran into seemingly insoluble problems, so am leaving all symbols global for now. (So patches used in pdlib, if they want to be usable in a multiple-instance scenaro, should protect all send/receive/table/delay/etc named objects with a $[0-9] somewhere.
I didn't look hard, but I thnk pdlib now will need a way to send $ arguments to patches via libpd_openfile() somehow. Also, libpd_init_audio() will want to make number of channels per-instance, etc. I've put some relevant comments in the test program I'll include below (and sorry for the length of this mail!)
Here's how I modified libpd_wrapper/z_libpd.c:
55d54 < sys_time = 0; 110c109
< sched_tick(sys_time + sys_time_per_dsp_tick);
sched_tick();
130c129
< sched_tick(sys_time + sys_time_per_dsp_tick); \
sched_tick(); \
and here (sorry again) is the test program, "pdtest2.c" adapted from libpd-master/samples/c_samples/c/pdtest.c :
#include <stdio.h> #include "z_libpd.h" #include "m_imp.h" #define TIMEUNITPERMSEC (32. * 441.)
void pdprint(const char *s) { printf("%s", s); }
void pdnoteon(int ch, int pitch, int vel) { printf("noteon: %d %d %d\n", ch, pitch, vel); }
int main(int argc, char **argv) { t_pdinstance *pd1 = pdinstance_new(), *pd2 = pdinstance_new(); if (argc < 3) { fprintf(stderr, "usage: %s file folder\n", argv[0]); return -1; }
int srate = 44100; // maybe these two calls should be available per-instnace somehow: libpd_set_printhook(pdprint); libpd_set_noteonhook(pdnoteon); /* set a "current" instance before libpd_init() or else Pd will make an unnecessary third "default" instance. */ pd_setinstance(pd1); libpd_init(); /* ... here we'd sure like to be able to have number of channels be per-nstance. The sample rate is still global within Pd but we might also consider relaxing that restrction. */ libpd_init_audio(1, 2, srate);
float inbuf[64], outbuf[128]; // one input channel, two output channels // block size 64, one tick per buffer
pd_setinstance(pd1); // talk to first pd instance
// compute audio [; pd dsp 1( libpd_start_message(1); // one entry in list libpd_add_float(1.0f); libpd_finish_message("pd", "dsp");
// open patch [; pd open file folder( libpd_openfile(argv[1], argv[2]);
pd_setinstance(pd2);
// compute audio [; pd dsp 1( libpd_start_message(1); // one entry in list libpd_add_float(1.0f); libpd_finish_message("pd", "dsp");
// open patch [; pd open file folder( libpd_openfile(argv[1], argv[2]);
/* the follownig two messages can be sent without setting the pd
nstance and anyhow the symbols are global so they may affect multiple instances. However, if the messages change anyhing in the pd instacne structure (DSP state; current time; list of all canvases n our instance) those changes will apply to the current Pd nstance, so the earlier messages, for instance, were sensitive to which was the current one.
Note also that I'm using the fact taht $0 is set to 1003, 1004, ... as patches are opened -it would be better to opent the patches with settable $1, etc parameters to libpd_openfile(). */
// [; pd frequency 1 ( libpd_start_message(1); // one entry in list libpd_add_float(1.0f); libpd_finish_message("1003-frequency", "float");
// [; pd frequency 1 ( libpd_start_message(1); // one entry in list libpd_add_float(2.0f); libpd_finish_message("1004-frequency", "float");
// now run pd for ten seconds (logical time) int i, j; for (i = 0; i < 3; i++) { // fill inbuf here pd_setinstance(pd1); libpd_process_float(1, inbuf, outbuf); if (i < 2) { for (j = 0; j < 8; j++) printf("%f ", outbuf[j]); printf("\n"); } pd_setinstance(pd2); libpd_process_float(1, inbuf, outbuf); if (i < 2) { for (j = 0; j < 8; j++) printf("%f ", outbuf[j]); printf("\n"); } }
return 0; }
I replaced "test.c" as follows:
#N canvas 406 290 450 300 10; #X obj 97 64 loadbang; #X obj 97 131 print; #X obj 186 106 dac~; #X obj 97 107 f 0; #X obj 128 107 + 1; #X obj 97 86 metro 2; #X obj 185 41 r $0-frequency; #X obj 188 73 osc~; #X obj 248 127 print $0-frequency; #X obj 248 97 loadbang; #X connect 0 0 5 0; #X connect 3 0 1 0; #X connect 3 0 4 0; #X connect 4 0 3 1; #X connect 5 0 3 0; #X connect 6 0 7 0; #X connect 6 0 8 0; #X connect 7 0 2 0; #X connect 7 0 2 1; #X connect 9 0 8 0;
and got this output:
print: 0 1003-frequency: bang print: 0 1004-frequency: bang 1003-frequency: 1 1004-frequency: 2 1.000000 1.000000 0.999999 0.999999 0.999998 0.999998 0.999997 0.999997 1.000000 1.000000 0.999998 0.999998 0.999996 0.999996 0.999995 0.999995 print: 1 0.999944 0.999944 0.999943 0.999943 0.999942 0.999942 0.999941 0.999941 print: 1 0.999815 0.999815 0.999810 0.999810 0.999804 0.999804 0.999799 0.999799 print: 2 print: 2
... Looks like there are 2 schedulers adn DSP chains running :)
Miller
Pd-dev mailing list Pd-dev@iem.at http://lists.puredata.info/listinfo/pd-dev