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.)
I think this should be fine.(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).
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.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 */ }
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
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@lists.iem.at https://lists.puredata.info/listinfo/pd-dev