[PD] throw~/catch~ headroom

IOhannes m zmölnig zmoelnig at iem.at
Sun May 3 21:16:23 CEST 2009


hi

including the mailing list again, as i guess that you already know what 
i am talking about...

Andy Farnell wrote:
> 
> A patch with N contributory signals, like an additive synth.
> The mix is (s1 + s2 + s3 ... sN) / N
> If each voice has a small DC offset then the sum will eventually drift
> outside the bounds -1.0 +1.0. When it happens in Pd the output goes silent.

what you are describing is valid for _any_ signal addition (whether it 
uses throw~/catch~, an explicit [+~] or implicit addition by connecting 
several signal-cords to a single inlet~.

apart from that it is not true at all.
if each voice has a small DC offset of µ (for the lack of epsilon on my 
keyboard), where µ is max(abs(DCn)) then the sum of the offsets will be 
µ*N and since you are normalizing by N the resulting offset will be µ 
(since µ is actually an upper boundary of the real offsets, the real 
resulting offset will be guaranteed to be no more than µ)


> 
> In some systems a certain safe way of working is to just add carelessly,
> do the division and then use a single DC trap at the end to remove any 
> accumulated error in the sum.
> 
> Most times this works fine in Pd. 
> 
> Otherwise you'd need N divisions and N [hip~] all before the sum which
> is expensive.

how come you assume a difference in the 2 approaches?
since [hip~] is a linear-time-invariant system, applying it to the sum 
of the signals should yield the same result as applying it to each 
signal and then summing them.

the differences are mainly in needed CPU-power; and you might get 
different artefacts due to floating-point precision.

> 
> But sometimes, with at least 8 normalised signals, you get silence
> at the [catch~ sum] even though there seems to be headroom.

what do you need by "headroom"?
"headroom" is usually used when a signal must not go beyond a certain 
threshold and you want to make sure that you stay clear off this 
threshold; this is important when dealing with fixed-point numbers, 
(e.g. as used by dacs on soundcards)
there is nothing comparable with floating-point numbers. Pd uses 
floating point numbers throughout to represent signals. if you add to 
in-phase signals of amplitude 1, you will get a new signal of amplitude 
2. no problem.
the only problem arises is, when you send this signal to the [dac~], 
which acts as a link to a fixed-point unit (your soundcard), and thus 
superimposes the limitations of this device to the signal it receives: 
it will clip the signal between -1..+1 and quantize to whatever your 
audio API needs. if your signal has a DC offset above +1 (or below -1) 
then you will hear nothing.
(and of course there are other problems with floating point, like adding 
a very big signal to a very low signal; or adding 10^8 0dbFS signals)

but this really  has nothing to do with [catch~] and applies to all 
adding of signals.

> 
> I went looking at the dsp_add() function trying to clarify the way Pd 
> sums many signals. And also considered creation order issues and
> which blocks are being summed...

adding signals is usualy done by applying the "+" operator to 
corresponding samples :-)


> 
> Replicating the problem is hard, but I had one just last week, a complex
> musical patch (rjdj) that stopped working when you mixed in some more channels.
> (though each individual channel seemed fine and had only tiny drift)

so what was the output of the [catch~] bus?

if you still have a version of this non-working patch lying around i 
would be happily have a look at it.

> 
> In the end a hack I found always works is to use delay buffers
> to replace throw/catch pairs.

but a delay-buffer is a replacement for [send~]/[receive~] and not for 
[throw~]/[catch~]. it is a 1-to-n distribution rather than a n-to-1 
summation.

> 
> Another possible solution is to stage the bus, so have, say 8 signals throw
> to bus-submix1 and another to bus-submix2 and then combine the two submix
> buses.

that's even more confusion.
why would several stages lower the effect (rather than enlarge it)?

> 
> Maybe someone more familiar with the code can speculate what is going on?
> 

unfortunately my eee's speakers will not output much below 130 Hz so i 
cannot fully appreciate your patch now...
however, attached is a slightly modified version with the sole purpose 
of proving that the two parts create the same result.

(the only non-obvious part is the order-forcing of throw~-before-catch~ 
in order to make the 2 patches play sample-synchronously.

mfgasdr
IOhannes
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: test-headroom.pd
URL: <http://lists.puredata.info/pipermail/pd-list/attachments/20090503/ef531971/attachment.txt>


More information about the Pd-list mailing list