[PD-dev] tilde object rework ideas

Christof Ressi info at christofressi.com
Fri Sep 2 01:00:52 CEST 2022


Hi Miller,

this sounds great! First-class multi-channel support would be a real 
game changer.

Actually, after Winfried Ritsch told me about the "pd_snake" project, I 
came up with a couple of ideas on my own. You can find them here: 
https://git.iem.at/pd/pdsnake/-/blob/master/docu/discussion.txt. Don't 
know if this aligns with what you are envisioning, but it might give you 
some inspiration either way :-)

In particular, I would like to point out 
https://git.iem.at/pd/pdsnake/-/blob/master/docu/discussion.txt#L33-41. 
This would allow us to create patches where the channel count can be 
changed dynamically with a single message!

Also, multi-channel signals would give us a chance to vectorize DSP 
algorithms that are otherwise hard or impossible to optimize. For 
example, with modern AVX instructions you can compute 8 oscillators or 
IIR filters for the price of 1. (With proper manual loop unrolling, just 
like in the "*_perform8" methods, some compilers are able to vectorize 
it automatically.)

> (one question about this... I _could_ take a sightly bigger risk and put the
> last 3 fields ahead of s_refcount, etc, which I don't think anyone should
> be using... this would make things look cleaner).
I think this should be fine.

> typedef struct _signal
> {
>      int s_n;            /* *TOTAL* number of points in the array */
>      t_sample *s_vec;    /* the array */
>      t_float s_sr;       /* *TOTAL* samples per second */
>      int s_refcount;     /* number of times used */
>      int s_isborrowed;   /* whether we're going to borrow our array */
>      struct _signal *s_borrowedfrom;     /* signal to borrow it from */
>      struct _signal *s_nextfree;         /* next in freelist */
>      struct _signal *s_nextused;         /* next in used list */
>      int s_vecsize;      /* allocated size of array in points */
>      	/* *** NEW STUFF *** */
>      t_float s_rate;     /* sample rate */
>      int s_length;       /* number of points in each channel */
>      int s_nchans;       /* number of channels */
>      int s_overlap;      /* number of times each sample will appear */
> }
Personally, I would keep s_n as the number of samples /per channel/. The 
total number of samples is simply s_n * s_nchans. Existing externals - 
that do not know about s_nchans - would effectively operate on the first 
channel and ignore the rest. Newer multi-channel-aware externals, on the 
other hand, may use all the channels.

I also think that DSP objects would need a new API method to create 
multi-channel /outputs/. The general idea is that the /input /channel 
counts are taken from upstream, but the /output /channel counts are 
specified by the object and passed downstream. (There might be objects 
where input and output channel count differs; any kind of 
merger/splitter/mixer objects comes to my mind.)

I think I have some more ideas/notes in one of my notebooks. I can look 
them up and see if there's something useful.

Anyway, I am quite excited about this!

Cheers,

Christof

On 01.09.2022 21:58, Miller Puckette via Pd-dev wrote:
> Hi Pd dev -
>
> I'm preparing to rework the DSP network to give tilde objects more control over
> their inputs and outputs, for instance allowing for multi-channel signals and to
> allow objects to decide for themselves whether to promote float inputs to
> signals (so that you don't have to say "+~ 0 to get the faster version, and so
> that I can make the hip/lop/bp/vcf frequency and Q inputs available as signals
> or as floats).
>
> Of course I mean to make this compatible with existin DSP objects, although for
> simplicity I'm going to propose one slightly risky move, changing the size of
> the t_signal structure -- as iohannes mentioned a few years ago, this seems
> very unlikely to break anyone's tilde objects.  The new structure would now
> look as follows:
>
> typedef struct _signal
> {
>      int s_n;            /* *TOTAL* number of points in the array */
>      t_sample *s_vec;    /* the array */
>      t_float s_sr;       /* *TOTAL* samples per second */
>      int s_refcount;     /* number of times used */
>      int s_isborrowed;   /* whether we're going to borrow our array */
>      struct _signal *s_borrowedfrom;     /* signal to borrow it from */
>      struct _signal *s_nextfree;         /* next in freelist */
>      struct _signal *s_nextused;         /* next in used list */
>      int s_vecsize;      /* allocated size of array in points */
>      	/* *** NEW STUFF *** */
>      t_float s_rate;     /* sample rate */
>      int s_length;       /* number of points in each channel */
>      int s_nchans;       /* number of channels */
>      int s_overlap;      /* number of times each sample will appear */
> }
>
> (one question about this... I _could_ take a sightly bigger risk and put the
> last 3 fields ahead of s_refcount, etc, which I don't think anyone should
> be using... this would make things look cleaner).
>
> For example, the FFT object's outputs should really have a sample rate of 1/N
> times the input sample rate, a vector length of 1, and a channel count of N. For
> compatibility, I'd take the "s_n" field to just be N, although in the future one
> could optionally use s_length as N and run as many DFTs as there are channels.
> (This would be incompatible with current practice in wierd situations in which
> one ran an fft~ objects into another fft~ objects as input - a real bad idea but
> perhaps the only way in vanilla to time-reverse a signal block by block, so I
> bet someone is depending on being able to do that :)
>
> Meanwhile, before the DSP routine is called, all signal inputs are populated
> with vectors by promoting float inputs to signals, all inputs are guaranteed to
> have the same s_n field, and all outputs are automatically generated to match
> all the inputs.  I want that to be the default option but to allow the object to
> access non-matching signals, not-filled-in signals (so that it can schedule
> scalar versions, as in "+~", and to take care of generating its own output
> signals (which may thus have different sizes from the input signals).
>
> I could then design a "trunk~" object that combines or splits one-channel
> signals into multichannel ones, and I could extend +~, etc., to know how to add
> one-channel signals to multichannel ones.  Also, clone~ could (optionally)
> unpack multichannel signals to distribute among copies.
>
> it might also be useful to have the option to ask for the output signals,
> if auto-generated, never to reuse the same vector as the input; I guess that
> can be provided if there's a demand for it.
>
> I'm thinking this is a big enough and dangerous enough change that I should do
> it on a separate branch first.  I've got some travel coming up but hope to start
> coding soonish.
>
> cheers
> Miller
>
>
>
> _______________________________________________
> Pd-dev mailing list
> Pd-dev at lists.iem.at
> https://lists.puredata.info/listinfo/pd-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puredata.info/pipermail/pd-dev/attachments/20220902/fb8d2c96/attachment.htm>


More information about the Pd-dev mailing list