Frequency range and magic numbers

Hello, I am looking for a little help with something that is probably pretty basic.

Some of the “Rack math” is causing me a little confusion.

In trying to understand the relationship between volts and frequency in Rack, I took a look at the VoltageStandards. From these, I understand the expectation is that input “voltages” don’t exceed 0V to 10V or \pm{5} V.

The frequency formula given is f = f_{0} \cdot 2^{V} which seems to mean that I should expect that f = 2 \cdot 2^{V} for an LFO and f = 261.6265 \cdot 2^{V} for a “normal” oscillator. Ok, so far so good.

When I started looking at the Fundamental LFO (mainly because I would like to translate an LFO that I have working outside of Rack into a Rack module), I began thinking that I might be in trouble. The frequency parameter is defined like:

configParam(
  paramId = FREQ_PARAM, 
  minValue = -8.f, 
  maxValue = 10.f, 
  defaultValue = 1.f, 
  name = "Frequency", 
  unit = " Hz", 
  displayBase = 2, 
  displayMultiplier = 1
);

This is confusing firstly due to the range, which appears to be 18 rather than 10. When I plug these values into the frequency equations above thinking that -8 and 10 are describing the voltage range I get the following:

  • Volts of -8 = 0.0078125
  • Volts of 10 = 2048

These appear to be too small and too big respectively. I was expecting to see a range of about 0.1 to 20 Hz.

Question 1: How do these values (-8 and 10) relate the voltage and frequency?


The next question may be related to whatever I am missing here…

In the frequency calculation,

void setPitch(T pitch) {
  pitch = simd::fmin(pitch, 10.f);
  freq = dsp::approxExp2_taylor5(pitch + 30) / 1073741824;
}

Question 2: Where do the “magic numbers” 30 and 1073741824 come from?

I would be very happy with direct answers of if there is something anyone can point me to which describes what boat I am apparently missing.

Thank you!

Hi! Good questions!

Regarding the ranges, note that the docs for LFO1/2 here give the range as one osc per 4 minutes (~0.0042 Hz) up to ~1000Hz for the frequency knob. So that’s approximately the range of the -8 and +10 values; without investigating further, it looks like the docs might be slightly off. (EDIT: actually, I think the docs are right; you used 2 as the baseline frequency in your calculation, but I think it’s actually 1, so the -8 and 10 range is actually 0.00390625 to 1024 Hz, which is right in line with the docs).

The +30 and division are there so that the Taylor series approximation function, which is being called for efficiency, can handle negative exponents (which it would blow up on if fed directly). If you check the function definition in approx.hpp you’ll see a comment to this effect and an example which adds 20 to the argument and divides the result by 2^{20} to unscale. Here, there’s protection against negative values up to -30, and I’ll leave the pleasure of discovering how that relates to 1,073,741,824 to you (just because it’s satisfying to figure out :slight_smile: )

1 Like

Thank you very much! I think I am getting much closer, though I still feel a little behind on this topic.

Two things -

In the Voltage Guide, it states that “Low-frequency oscillators and clock generators should use 120 BPM (f_0 = 2 Hz).” That intuitively makes sense to me, so I am wondering…and it feels like a silly question…was this advice just not taken for Fundamental’s LFO or am I missing something else?

Regarding the big number…thank you for that - it took me a minute but when I had a look at dsp::approxExp2_taylor5 it stood out pretty quickly.

Awesome!

I had never noticed the baseline of 2 in the Voltage Guide–thanks!

By the LFO1/2 code, the default freq is 1, the default knob position is 1, and there’s no multiplier in setPitch; I didn’t clock the low frequency, but I checked by ear and the highest knob position is 1,024Hz (per the manual), not 2,048Hz.

I think what’s going on in LFO1/2 is that there’s no external direct voltage control over the pitch (just FM, which is obviously a different thing), and so the module can use whatever internal “voltage” it likes for the knob to talk to the oscillator core. It’s basically just a convenient way of scaling the knob (the way you would use different resistances and baselines for hardware pots). No other module would see the actual value and so it doesn’t matter. If there were an LFO Rate input, it should (and presumably would) follow the baseline, where an input voltage of 0 would yield a LFO rate of 2Hz.

2 Likes

I suspect you are right. Thank you for the insight & conversation!

1 Like