First time here? Check out the FAQ!
x

Density of Stochastic Triggers or: Where do the magic numbers in the CloudBank density calculation come from?

0 votes
866 views

In the CloudBank-Resynthesis Prototype the density of the triggers is provided by a calculation in the CentreValue of a Noise Sound. 

 

 

I understand what this expression says and I understand that by moving the CentreValue of the Noise we're changing the density of values that will be greater than 0 and therefore trigger the CloudBank. But I don't understand why this expression is the way it is and where the two magic numbers 1.5015014821509d and -6.66 come from. 

Do those numbers have a special meaning and how does this work?

If you want to know why I'm asking, I'm making a Sound with stochastic triggering and I want to create a density of triggers that roughly equates to a frequency. 

I've made a little Sound for comparing the density of a regular pulse train with a random trigger source.

 

asked Jan 10, 2021 in Using Kyma by alan-jackson (Virtuoso) (15,840 points)
edited Jan 10, 2021 by alan-jackson

2 Answers

+1 vote
 
Best answer

To summarize the discussion in the comments, in your test example, the GateToPulse Sound ignores consecutive triggers from the Threshold, thus causing the difference between the pulse train and the noise density measurements (because truly random triggers can occur on consecutive samples).

If you reduce the Noise trigger probability by the likelihood of two consecutive samples in a row being above the threshold, then the two branches (noise and pulse train densities) track each other a lot more closely. The compensated CenterValue for the Noise would be:

(1 - (2 * !Frequency hzToSignal)) sqrt negated

answered Jan 12, 2021 by ssc (Savant) (128,120 points)
selected Jan 13, 2021 by alan-jackson
+1 vote

The overall effect of this expression is to "warp" the !Density fader such that is spends more of its throw at smaller numbers and only a small proportion of its distance is devoted to larger numbers. 

The expression is actually (!Density * (0.666 inverse - !Density * -6.66) twoExp * 2 - 1), which would be equivalent to (6.66 * !Density) twoExp / 1024 * !Density (which is then scaled and offset to be in the range of [-1,1] so it can serve as the center value of the Noise).

For Density = 0, this would be 0 / 1024 * 0

For Density = 1, this would be 6.66 twoExp / 1024 * 1 = 0.098755153537997d

so the range is approximately [0, 0.1]

In other words, it changes the range of the !Density fader to 0.1, and warps it so more of its throw is spent at the smaller values.

I know you're already familiar with this, but for anyone else reading this who hasn't seen it yet, a good way to get a feel for what a Capytalk expression does is to:

  • Select the Capytalk expression
  • Use Ctrl+Y to evaluate it
  • Move the faders so you can see the relationship between input and output values while watching an oscilloscope trace of the results.
answered Jan 10, 2021 by ssc (Savant) (128,120 points)
It feels like I'm asking someone to do my homework for me :). I want to make a random trigger source where I can set its density of triggers as a frequency - that is the frequency of a pulse train that would have equivalent density. I think that means I want a density that relates linearly to !Density. I've made a little Sound to measure the density of random triggers and compare it to the density of a regular pulsetrain. With the CenterValue of 0 I get the highest density which seems to equate to the density of a 1/4 sample rate pulse train.

As I move the pulseTrain's frequency down, the density measure tracks linearly with frequency. What kind of expression should I put in CenterValue to make it track the same, from 1/4 sample rate down to 0?

I'll add my test rig Sound to the original question.
You could try:
(!Density * (0.666 inverse - !Density * -6.66) twoExp) to control the DutyCycle of a PulseTrain (with Variable DutyCycle checked).
My density control was going to work at sample rate and I wanted to use the hzToSignal standard. A frequency signal value of 0.5 would equate to a frequency of 1/4 sample rate. So I wanted a density signal of 0.5 to equate to a density of triggers equivalent to a pulseTrain running at 1/4 sample rate.
If you want a 1-sample wide pulse train with the same density as the Noise triggers have now (on average), you could implement this with Sounds:
(!Density * (0.666 inverse - !Density * -6.66) twoExp) * 2
and paste that Sound into the frequency of a OscillatorTimeIndex and feed the output of the OscillatorTimeIndex into your encapsulated Sound that creates a 1-sample wide pulse (since it outputs a pulse on the zero crossing of the OscillatorTimeIndex).
Paste which Sound in the OscillatorTimeIndex? Is that Constant?

What I want to do is do it the other way around. That is have a Noise based trigger with the same density as a PulseTrain. I was trying to work out the math(s) for setting the density of triggers from the Noise source that would be equivalent to a PulseTrain at a certain frequency.

Thanks
Do you want the noise-based trigger to take a pulse train as its input? Or to set the CenterValue of the Noise in terms of !Frequency?
Hi, yes set the CentreValue in terms of frequency. Thanks
Try the CenterValue set to:
!Frequency hzToSignal - 1
Thanks! It's getting closer, but assuming I'm measuring this the right way,it's not quite working. I'm using the Sound linked in my question to measure the density which is using the AveragingLowpassFilter set to 25 hz.

The highest density of triggers from the noise source occurs when CentreValue is 0. At that point the density is equivalent to a frequency of 1/4 sample rate.

In the expression "!Frequency hzToSignal - 1", it will be zero when !Frequency is 1/2 sample rate rather than 1/4 sample rate.

I tried "(!Frequency * 2) hzToSignal - 1" but that's not tracking with the comparison PulseTrain at the same frequency.

It looks like the density does not track linearly with !Frequency.

I think it's a probability thing...  "!Frequency hzToSignal -1" starts tracking well at low frequencies but above 1/8 sample rate falls away.  I think it's related to why a noise source maxes out at 1/4 sample rate trigger density. When triggers are sparse then the frequency density is going to be roughly equal to the probability that the noise value is above zero. So it will track linearly at first.

But as the density of triggers increases it becomes more likely that two subsequent values will be above zero and instead of being two triggers that's only a single trigger because it must return to zero or below before it can retrigger.

The fastest trigger frequency possible is half sample rate where every other sample is positive and the samples in between are zero or negative - and that would be vanishingly rare, let's say virtually impossible, to get from a noise source.  

It's at this point I'd normally shine the π symbol into the sky and hope for rescue by a math(s) hero, preferably in a cape.
Thinking more about it, any density over 1/4 sample rate is becoming less random as 1/2 sample rate density is only achievable with no randomness at all. One way I've tried to fade from 1/4 sample rate up to 1/2 sample rate density is to XOR the random triggers with a PulseTrain of regular triggers at that frequency for anything above 1/4 SR.

I don't know if that's mathematically justifyable... but it sounds good.

Anyway so the density based on CenterValue only needs to track up to 1/4 sample rate.
The GateToPulse Sound ignores consecutive triggers from the Threshold, causing the difference between the pulse train and the noise measurements. Truly random triggers can occur on consecutive samples.

You get the same measurement from the noise and the pulse if you remove the GateToPulse.

If you want to include the GateToPulse then the center value of the noise should be:

(1 - (2 * !Frequency hzToSignal)) sqrt negated

and the range of !Frequency should be 0 to the quarter sample rate.
Ah yes that is true that the GateToPulse is preventing triggers on consecutive samples but that's because any consumer of a trigger would also do the same. I'm using these random triggers to trigger a TriggeredSampleAndHold. The TSAH triggers on the leading edge so won't resample if the triggers are on consecutive samples...

...if there was a TrackAndHold that would probably work, wouldn't it? Coincidentally I've just made one. Have I just answered my own question?

Thank you for the counselling session, much appreciated!
We modified our response above to adjust the probability to account for triggers on two consecutive samples. Center value should be

(1 - (2 * !Frequency hzToSignal)) sqrt negated
Ah wicked! Yes that's the one. That tracks great, thank you.
...