How to make each instance of an abstraction contain a unique subpatch puredata
@crttrkix
I don't 100% understand what @whale-av wrote, so this response may just repeat an idea @whale-av already gave you. But maybe not. I agree that
all you have done is change the name of the sub-patch.
So why not instead change the name of an object within your subpatch using the argument to the enclosing abstraction? The analogy isn't perfect, but it's sort of like passing a function pointer, and the weird object inside the abstraction is like an abstract superclass but for a single function. OMG that was too complicated to be helpful 

Do different instances of Pure Data run in different threads?
Press control+shift+escape to open the task manager, in details you can right click on wish86.exe and or pd.exe and define the allowed cores for the application.
I never tryed this but just saw it there now.
As @whale-av said, maybe you have to copy the pd folder and maybe rename the second application.
I guess there are other ways to start and run applications on a specific thread in win, but you can search for yourself as this is not Pd specific.
And as @whale-av said, these instances are completly independent and they
won't run in sync. They run asynchronous. Useful for special tasks, for example to do sth with fast-forward-message while the other patch stays in real-time.
If you want to spread patches across different cpu cores but still in sync, use the [pd~] object.
Either way shmem lib is very useful to share memory / share arrays between pd-instances.
(Looking at the task-manager when using [pd~] I see the cores are constanly changing, Looks like Windows is dynamicly changing the cores. Might be good enough or even better to let Windows manage it instead of assigning fixed threads. Same might be true when running asynchronous instances. )
pack s s s , pak s s s
@gentleclockdivider of course, you can look at the code.
static void pack_anything(t_pack *x, t_symbol *s, int ac, t_atom *av)
{
t_atom *av2 = (t_atom *)alloca((ac + 1) * sizeof(t_atom));
int i;
for (i = 0; i < ac; i++)
av2[i + 1] = av[i];
SETSYMBOL(av2, s);
obj_list(&x->x_obj, 0, ac + 1, av2);
}
you have to get into a few functions, but basically the argument 's' is the 'selector' (in this case '-' or 'X'), 'ac' is the count of items in the list (after the selector) and *av is the pointer to the atoms that make it up.
first, it allocates a new list of atoms of length of the input elements (elements after the selector, in this case 0) + 1 = 1
then it shifts all the input elements up by 1, and inserts the selector as a symbol in the first element
Then obj_list will distribute all the elements of that list to the inlets of pack, from right to left which will set the atoms that pack is storing for those inlets
when obj_list lastly reaches/distributes to the leftmost it will call pack_symbol, which will call pack_bang which triggers the atoms pack has stored to be output as another new list
binding pack_anything to anythings coming into the first inlet is done by calling class_addanything in pack_setup method
On-air light, trouble receiving int via OSC
@whale-av From that link you posted (@av-whale) I read this...
"OSC messages are not sent simply as text strings - the messages are assembled in a very specific format for transmission, including converting the int32 and float32 arguments to 32-bit values (either integer or floating point), and ensuring all parts of the message are 4-byte-aligned,"
This makes sense, because when I was sending messages formatted as [send xyz 123 456] I was getting an error on the x32 screen saying something like, "Message not formatted as 4-bytes" or something along those lines. I was coming up short trying to find info on that error, but this answers that question.
Thank you both! I'm going to try this today (as long as I can find some time). Super exciting! Thanks for spelling it out at the end of your reply @av-whale.
One thing I was going to say- the formatting like, [send /cs/chan/at/0] does work for the lighting board (to turn the on-air DMX light on/off, those messages are highlighted below), but I'm not getting anything in return (and don't need to).

Also, I had a bang connected to [send ch mix 2 on] in the last patch, but yeah the formatting wasn't quite right.
Again, thank you both. I'm going to look at the oscformat help patch and will post here (with findings) when I add it into the patch. Hopefully today.
Pd's latency on a Mac running QLab
@whale-av Thanks. RE 2 mk4s, don't bother checking, I was just curious how you'd know which option to choose when presented with "would you like the Ultralite mk4 or the Ultralite mk4?"
I see the potential for that in Discovery and Pro Audio Control, and can imagine a similar choice in Pd's Media->Audio Settings. At least in Pro Audio Control, at the bottom of the Device page, in teeny tiny print at the bottom, there's the device serial number....
Update: RTFM! pg 12, item 8: "click to rename the interface"
Necro off-topic update
: I bought a second mk4 to be just like @whale-av and while you can connect 2 to the same windows machine and configure them, you can't run 2 of them at the same time using ASIO drivers. Neither Pd nor REAPER show 2, and MOTU support says it's not possible.
looking for velvet noise generator
As I was imagining, as a C code, this is all hassle free, very simple, and never misses a period. And the code is pretty simple. And Multichannel capable 

So far this is what I have....
// Porres 2024
#include "m_pd.h"
#include <stdlib.h>
#include "random.h"
#define MAXLEN 1024
typedef struct _velvet{
t_object x_obj;
double *x_phase;
double *x_lastphase;
t_random_state x_rstate;
int x_id;
t_float *x_rand;
int x_nchans;
t_float x_hz;
t_int x_n;
t_int x_ch2;
t_int x_ch3;
t_inlet *x_inlet_reg;
t_inlet *x_inlet_bias;
t_outlet *x_outlet;
double x_sr_rec;
}t_velvet;
static t_class *velvet_class;
static void velvet_seed(t_velvet *x, t_symbol *s, int ac, t_atom *av){
random_init(&x->x_rstate, get_seed(s, ac, av, x->x_id));
}
static t_int *velvet_perform(t_int *w){
t_velvet *x = (t_velvet *)(w[1]);
t_float *in1 = (t_float *)(w[2]);
// t_float *in2 = (t_float *)(w[3]); // bias placeholder
// t_float *in3 = (t_float *)(w[4]); // regularity placeholder
t_float *out = (t_float *)(w[5]);
double phase = x->x_phase;
double lastphase = x->x_lastphase;
for(int j = 0; j < x->x_nchans; j++){
for(int i = 0, n = x->x_n; i < n; i++){
double hz = in1[jn + i];
double step = hz * x->x_sr_rec; // phase step
step = step > 1 ? 1 : step < 0 ? 0 : step; // clipped phase_step
out[jn + i] = ((phase[j] + x->x_rand[j]) >= 1.) && ((lastphase[j] + x->x_rand[j]) < 1.);
if(phase[j] >= 1.){
uint32_t *s1 = &x->x_rstate.s1;
uint32_t *s2 = &x->x_rstate.s2;
uint32_t *s3 = &x->x_rstate.s3;
x->x_rand[j] = (t_float)(random_frand(s1, s2, s3)) * 0.5 + 0.5;
post("phase = %f", phase[j]);
post("random = %f", x->x_rand[j]);
phase[j] -= 1; // wrapped phase
}
lastphase[j] = phase[j];
phase[j] += step;
}
}
x->x_phase = phase;
x->x_lastphase = lastphase;
return(w+6);
}
static void velvet_dsp(t_velvet *x, t_signal **sp){
x->x_n = sp[0]->s_n, x->x_sr_rec = 1.0 / (double)sp[0]->s_sr;
int chs = sp[0]->s_nchans;
x->x_ch2 = sp[1]->s_nchans, x->x_ch3 = sp[2]->s_nchans;
if(x->x_nchans != chs){
x->x_lastphase = (double *)resizebytes(x->x_lastphase,
x->x_nchans * sizeof(double), chs * sizeof(double));
x->x_phase = (double *)resizebytes(x->x_phase,
x->x_nchans * sizeof(double), chs * sizeof(double));
x->x_rand = (t_float )resizebytes(x->x_rand,
x->x_nchans * sizeof(t_float), chs * sizeof(t_float));
x->x_nchans = chs;
}
signal_setmultiout(&sp[3], x->x_nchans);
if((x->x_ch2 > 1 && x->x_ch2 != x->x_nchans)
|| (x->x_ch3 > 1 && x->x_ch3 != x->x_nchans)){
dsp_add_zero(sp[3]->s_vec, x->x_nchansx->x_n);
pd_error(x, "[velvet~]: channel sizes mismatch");
return;
}
dsp_add(velvet_perform, 5, x, sp[0]->s_vec,
sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec);
}
static void *velvet_free(t_velvet *x){
inlet_free(x->x_inlet_bias);
inlet_free(x->x_inlet_reg);
outlet_free(x->x_outlet);
freebytes(x->x_phase, x->x_nchans * sizeof(*x->x_phase));
freebytes(x->x_lastphase, x->x_nchans * sizeof(*x->x_lastphase));
freebytes(x->x_rand, x->x_nchans * sizeof(*x->x_rand));
return(void *)x;
}
static void *velvet_new(t_symbol *s, int ac, t_atom *av){
s = NULL;
t_velvet *x = (t_velvet *)pd_new(velvet_class);
x->x_id = random_get_id();
x->x_phase = (double *)getbytes(sizeof(*x->x_phase));
x->x_lastphase = (double *)getbytes(sizeof(*x->x_lastphase));
x->x_rand = (t_float *)getbytes(sizeof(*x->x_rand));
x->x_hz = x->x_phase[0] = x->x_lastphase[0] = x->x_rand[0] = 0;
velvet_seed(x, s, 0, NULL);
if(ac){
while(av->a_type == A_SYMBOL){
if(ac >= 2 && atom_getsymbol(av) == gensym("-seed")){
t_atom at[1];
SETFLOAT(at, atom_getfloat(av+1));
ac-=2, av+=2;
velvet_seed(x, s, 1, at);
}
else
goto errstate;
}
if(ac && av->a_type == A_FLOAT){
x->x_hz = av->a_w.w_float;
ac--, av++;
}
}
x->x_inlet_bias = inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
pd_float((t_pd *)x->x_inlet_bias, 0);
x->x_inlet_reg = inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
pd_float((t_pd *)x->x_inlet_reg, x->x_phase[0]);
x->x_outlet = outlet_new(&x->x_obj, &s_signal);
return(x);
errstate:
post("[velvet~]: improper args");
return(NULL);
}
void velvet_tilde_setup(void){
velvet_class = class_new(gensym("velvet~"), (t_newmethod)velvet_new, (t_method)velvet_free,
sizeof(t_velvet), CLASS_MULTICHANNEL, A_GIMME, 0);
CLASS_MAINSIGNALIN(velvet_class, t_velvet, x_hz);
class_addmethod(velvet_class, (t_method)velvet_dsp, gensym("dsp"), A_CANT, 0);
class_addmethod(velvet_class, (t_method)velvet_seed, gensym("seed"), A_GIMME, 0);
}
I need an object to unpack an incoming midi chord (midi in, note in )
@gentleclockdivider This is becoming perhaps a bit heated, unnecessarily?
I guess part of the confusion is that there are two purposes being discussed. One is display ("show all incoming midi notes that make up the chord"). The other is performing the notes as audio.
whale-av is correct that if you want to play the notes audibly, it's easier not to pack the note numbers into a single list.
- Note performance, approach 1: Notes come in --> play them polyphonically.
- Note performance, approach 2: Notes come in --> pack the note numbers into a list --> unpack the list --> play the notes polyphonically.
whale-av was trying to caution you against the second approach for audio performance. Those comments were not addressing the problem of display.
For display, I gave you a couple of examples (btw those examples were mine, not whale-av's, proper credit), so that problem is solved, I think.
max msp has a dedicated object for exactly that , says enough .
As shown, it's possible to do using core Pd objects.
If you replace the [notein] at the top with a pair of inlets (note number and velocity), and put an outlet at the end, you can save it as an abstraction and then you have a dedicated object. You could even add a list box in a graph-on-parent zone and get built-in display.
hjh
Controlling Ardour from Pure Data
@whale-av said:
@atux Give this a try and let me know.......
Pressing [transport_play( nothing happens in Ardour, also removing "ardour" in [oscformat ardour].
This is the output in console:
--------------------------------------------------------------------
:: Cyclone 0.8-0; Released October 22nd 2023
:: License: BSD-3-Clause (aka Revised BSD License)
:: Copyright © 2003-2021 - Krzysztof Czaja, Hans-Christoph Steiner,
:: Fred Jan Kraan, Alexandre Porres, Derek Kwan, Matt Barber
:: and others.
:: -----------------------------------------------------------------
:: Cyclone 0.8-0 needs at least Pd 0.54-0
:: (you have 0.54-1, you're good!)
:: Loading the cyclone library loaded non alphanumeric objects,
:: which are: [!-], [!-~], [!/], [!/~], [!=~], [%~], [+=~],
:: [<=~], [<~], [==~], [>=~] and [>~]
:: NOTE: Loading this binary did not load the path
:: you need to add 'cyclone' to the "preferences=>path"
:: or use [declare -path cyclone] (this guarantees search priority)
--------------------------------------------------------------------
home/a/Pd/externals/hcs: can't load library
-------------------------------------------------------------------
-----> ELSE - EL Locus Solus' Externals for Pure Data <-----
-------------------------------------------------------------------
- Version: 1.0-0 rc-11; (Released February 06th 2024)
- Author: Alexandre Torres Porres & others
- Repository: https://github.com/porres/pd-else
- License: Do What The Fuck You Want To Public License
(unless otherwise noted in particular objects, check 'license' folder)
- ELSE 1.0-0 rc-11 needs at least Pd 0.54-1
(you have 0.54-1, you're good!)
-------------------------------------------------------------------
- NOTE: There's an accompanying tutorial by Alexandre Torres Porres.
You can find it as part of the ELSE library download, look for the
"Live-Electronics-Tutorial" folder inside the ELSE folder.
It has a CC license. Please check its README on how to install it!
-------------------------------------------------------------------
- ALSO NOTE: Loading this binary did not install the ELSE library
you must add it to the "path preferences" in order to load objects
without a prefix
-------------------------------------------------------------------
- ALSO ALSO NOTE: Loading this binary did install an object browser
plugin for Vanilla and ELSE objects when right clicking on a canvas.
-------------------------------------------------------------------
-----> ELSE - EL Locus Solus' Externals for Pure Data <-----
-------------------------------------------------------------------
♡♡♡
♡ the zexy external 2.4.2
♡ (c) 1999-2023 IOhannes m zmölnig
♡ forum::für::umläute
♡ iem @ kug
♡ compiled Jul 7 2023
♡ send me a 'help' message
♡♡♡
matchbox: OSC-pattern matching code (c) Matt Wright, CNMAT
CREB: version 0.9.2darcs
/home/a/Pd/externals/ext13: can't load library
/home/a/Pd/externals/mrpeach: can't load library
opened alsa MIDI client 129 in:1 out:1
@whale-av said:
On my system in Pd 0.54.1 the MrPeach library will load just by putting the full path in Path preferences...
I see that it also gives me an error for other libraries. However, I also tried to reinstall mrpeach from Find externals, and in any case the mrpeach path is present:

Not clipping! (?) OMG, MY BAD, NEVERMIND
@jameslo @jameslo Not gospel...... because there are so many unknowns.
The values sent will not actually be between -1 and +1 but will be (probably signed) integers between -32768 (?) and 32767 for 16bit.
Pd processes at 32bit floating point.... so much bigger integers.. and can write those values to files.
But usually a stream will be 16 or 24bit.
Maybe the Pd value of 1 represents 32767..... a safe(ish) value for a 16bit stream for the computer internal soundcard.
But your usb soundcards are probably 24bit and so can accept much higher values without an integer overflow.
SPDIF 20bit or sometimes 24bit.
I don't know whether the bit depth is negotiated and the integer range scaled at the output from Pd, but maybe not.
Right from the birth of digital audio there was no standard for the ADC circuit.... sometimes it would accept 0dBu, often +18, or something else.
The numbers are streamed out of Pd to the OS, routed by the drivers..etc.
What happens to the numbers after that, or even during that process?
What do individual manufacturers do to keep their idiot customers happy?
As long as there are no integer overflows, and they arrive at the DAC within its range, there will be no clipping.
David.
How to use multiple audio devices (input)?
@whale-av Hey, thank you. It works well for about five minutes and then the sound gets glitchy/noisy for a couple of minutes bit before returning to normal for a while.
In the ASIO4ALL advanced settings, I have the following toggled on:
PreSonus AudioBox iTwo
---Out 2x 44.1kHz 24Bits
Logicool BRIO (webcam)
BOSS GP-10
---IN(GP-10)
*ASIO Buffer Size is 512 for everything
*Latency compensation is set to 32 samples in and out
*Allow Pull Mode is off
*Always Resample 44.1kHz<->48Hz is off (PD is running in 44.1kHz)
*Force WDM Driver to 16 Bit
Any idea what could be wrong? I guess I could try ditching the BRIO webcam's audio for a mic that goes into the Presonus if reducing the amount of devices from three to two would help.



