Yes, please explain, once you find the answer.
Of course you do! Source code is the most accurate form of documentation!
In the pushNoteName at https://github.com/VCVRack/Rack/blob/768d859187d64aed4d3d3db1f9c3aef596676116/src/Quantity.cpp#L61, you can see the code that does the functionality as I described above: the “plain” note name with a translation of voltage into hertz, and the note name with “v” appended for the voltage itself
Right,there are several sequencers that you could not type C5 into and get a usable voltage level, but now you type C5v and get just what you like.
You could actually already use the ftov
function in input fields in the past, but there would be slight rounding errors since it’s the voltage translated into a frequency and then back to the voltage. E.g. ftov(c4)
ends up a fraction below 0V instead of exactly 0V when I try it. Whether that offset is of any impact depends on the scenario ofcourse, it probably won’t be noticed in most cases.
It looks like I got lucky with the timing of the release: the fixed version is now also available in the library
Ok, I think I might be getting it now, mind you without having programmed a module or read any source
- Most knobs that are bound to anything related to pitch, are directly bound to a number. When you rotate the knob you change that number. So what does that number express or encode?
- On modules such as VCV:VCO or VCV:LFO the number of the “FREQ” knob is directly bound to frequency. So you can literally right-click it and type in a frequencey, such as 440 or 1200.
- On modules such as VCV:Compare, VCV:Seq3 or Solim the number of the “B offset”, “Step value” or “Limit” knobs are instead bound to voltage, and you can right-click the knob to set a voltage directly, and that voltage (can) correspond to a pitch according to the Rack voltage standards.
- I guess you could say that philosofically the difference between those two approaches/methods is (might be?), that in one group the value always directly has to do with a frequency, whereas in the other group you have the “CV type values” that may or may not have a bearing on a frequency/pitch. I guess someone could also complain and say “why are they not all simply bound to voltage, since everything is voltage anyway?” and I don’t think I have a deep answer to that, other than maybe “sometimes you want frequency”, but really I don’t know.
- So far so good. Now, because humans don’t really like to manually translate frequency or voltage into pitch using some formula, Andrew decided to help us out and introduced (a while back) the “input mini language” (aka. Parameter Commands), which are human friendly macros to do the translation. You can right-click a pitch related knob and type in a macro.
- For knobs bound to frequency we can, instead of typing the frequency to get the pitch, simply type the desired pitch, such as “C4” or “E1”. This works on e.g. VCV:VCO and VCV:LFO, and the macro will translate the given pitch to the corresponding frequency that the knob takes/uses.
- For knobs bound to voltage that doesn’t work. Instead, to translate a human writable pitch into the voltage that the knob needs, we can type e.g.
ftov(C6)
to set the 2V that corresponds to the note C6. By the way, many common math functions can be used in that macro language, including simple math symbols. - Because ftov(C6) is still a bit clunky to type, Andrew in Rack v2.6.1 introduced the shorthand (e.g.)
C6v
to express the same 2V asftov(C6)
does. So now on modules such as VCV:Compare, VCV:Seq3 or Solim we can right-click the knob and simply typeC6v
to set the voltage (2V) for the pitch C6.
And thus endeth the saga
Yes, see my explanation above.
So what makes a particular parameter be a “voltage” or a “frequency”? I’m guessing it’s something about the way the parameter is registered with the module, but what are the details?
Well you’re the module programmer but if I’m reading it right then
configParam<FrequencyQuantity>(FREQ_PARAM, -8.f, 10.f, 1.f, "Frequency", " Hz", 2, 1);
in LFO means that although the underlying value used is -8 - 10, the display scale is exponential base 2, which is what is shown and can be input, and I’m guessing the engine then marshalls between the display scale and the underlying value.
So if I’m right I guess the determining factor is the display scale.
The doc for configParam:
It’s just down to how you configure your parameter and its conversions to and from human readable values. Naively, if you set your parameter’s range to [32, 20000] and use it as-is, it’ll be in Hz, and if you set it to [-2, 2] and convert from 1V/Oct in process, it’ll be in V/Oct.
In practice, though, for frequency you’d want to use the displayBase
, displayMultiplier
and displayOffset
arguments of configParam
to set up a conversion. What internal range you use is up to you, you can use 1V/Oct internally if you want to, or anything else that can be calculated using that system. e.g., Fundamental’s VCO uses the range [-54, 54]
for its frequency parameter internally, but sets it up to convert that to Hz automatically.
The conversion is done in ParamQuantity
’s getDisplayValue
and setDisplayValue
overrides. I made a graph in Desmos at some point to make it easier to test the values.
I’ve overridden those plenty, but haven’t used the premade ones much. I always think that stuff is mysterious and magical…
Thank you very much to all, I find the whole discussion very interesting, even though there probably is a lot I do not know or understand.
In the end, I am asking myself the question: What damage would it do (or would it be impossible) if the proper command for voltage-type parameters was not ‘C4v’, but simply ‘C4’, in order to simplify operation (and in harmony with using frequency-type parameters)?
I understand that it makes a difference behind the scenes, but is the distinction carved out by the ‘v’ in the command critical from the perspective of the user?
NB: I am terribly sorry for having sent this thread by @not-things off-topic with my question. Perhaps someone could spin out the discussion to its own little thread?
The note commands are “dumb”- they’re essentially just math constants handled by the expression system, which has no knowledge about the underlying parameter, nor what it’s doing with the value of the expression you put in. There also isn’t really any way to have Rack automatically determine whether the input needs frequency or 1V/Oct, so it ends up falling on the user to choose which needs to be used.
The “correct” way to “fix” this would be for all module developers to set up their frequency parameters to convert to Hz when displaying to the user, but not everyone wants to or knows how to do it.
I’m sorry too. @moderators could we ask one of you to move these latest posts to a new topic “Pitch parameter values”? Thanks!
Thanks for posting the video showing Solim’s operation. Such an intuitive and musical module. Would love to see this on the 4ms Meta.
Thanks!
I had a quick look at the Meta docs, but the limitations on the SDK page says that there is no support for expander modules. So most of the Solim functionality would not be accessible…
It has taken up a couple of months of my free time to develop, test and document, but a new module is now available as a beta release:
TimeSeq - a JSON script driven sequencer
This module started with the idea to write something that would allow developers to test their own modules: by outputting scripted voltages and verifying the resulting values on input ports, it would be possible to verify that a module works as expected when presented with CV inputs. But as I kept adding functionality to the scripting idea, I realized that it was actually turning into a scriptable sequencer. So I shifted the focus towards that, though there is still an ‘assert’ action in there that can be used as a testing tool.
TimeSeq supports:
- 8 polyphonic input ports that can receive voltages or input triggers
- 8 polyphonic output ports (with scriptable polyphony)
- internal variables
- internal triggers to start, restart, stop and chain sequences
- conditional actions
- random voltages
- support for several parallel sequences
The JSON scripts allows simple sequences or more complex logic to be created. E.g. while adding features to the JSON script, I realized that it’s possible to write a script that implements the Bernoulli Gate functionality, so that is one of the samples that can be found in the documentation.
The first second beta release (build for windows, mac and Linux in GitHub) can be found at https://github.com/not-things-modular/not-things-vcv/releases/tag/v2.0.3-timeseq-beta-01
https://github.com/not-things-modular/not-things-vcv/releases/tag/v2.0.3-timeseq-beta-02
With the documentation pages:
- Main documentation page with links to:
- Overview of the UI - how the TImeSeq UI interacts with the a loaded script
- JSON Script concept overview - get an idea of the concepts in the JSON script
- JSON Script syntax - dive into the details of the JSON script
- Some script samples with explanation:
- A chord and note sequence
- A clock signal generator
- The Bernoulli Gate simulator
- An Oscillator demonstration
The current documentation is an initial version that I’ll have to go through a couple of times to refine, but it should contain information about all the features. There are some more sample scripts planned (e.g. a sample-and-hold script and a CV modulation script that will complement the existing “chord and note sequence” sample)
Very interesting, I’ve been having similar ideas. Looking forward to seeing where this goes
Looks great, will be fun to dive into this.