Oscillator range after V/Oct calibration

Hello everyone !

I recently started to toy with daisy seed and patch submodule and I encountered a problem.

I managed to code a simple sine vco with one CV input for V/Oct and one frequency knob for tuning. To do so I founded the scale and offset value for V/Oct by debugging and using the formula that I found in VoctCalibration class source code.

But since I implemented the V/Oct tracking, the range of the frequency knob is very low : from 8hz to around 250hz. Is there any solution to increase this range ?

I must mention that the V/Oct CV input and the frequency knob are connected to the same ADC (CV_1). I can’t really change this design because I work on an already existent module which include patch submodule (the module is Sibilla by Clatters).

Here is my code :

#include "daisy_patch_sm.h"
#include "daisysp.h"

using namespace daisy;
using namespace patch_sm;
using namespace daisysp;

DaisyPatchSM patch;
Oscillator   osc;
VoctCalibration calibrator;

void AudioCallback(AudioHandle::InputBuffer  in,
                   AudioHandle::OutputBuffer out,
                   size_t                    size)
{
    calibrator.Record(0.113, 0.378); // 1v and 3v value retrieved via COM debugging
    patch.ProcessAllControls();

    float climb_knob = patch.GetAdcValue(CV_1);
    float freq = mtof(calibrator.ProcessInput(climb_knob));

    osc.SetFreq(freq);

    for(size_t i = 0; i < size; i++)
    {
        float sig = osc.Process();
        OUT_L[i]  = sig;
        OUT_R[i]  = sig;
    }
}

int main(void)
{
    patch.Init();
    osc.Init(patch.AudioSampleRate());
    patch.StartAudio(AudioCallback);
    while(1) {}
}

Hope someone could help me :slight_smile:

What haapens when you apply positive voltage to the CV input?

Perhaps do voltage to frequency instead of mtof?

Add inline float vtof() before void AudioCallback, and do this instead

float freq = vtof(climb_knob);

inline float vtof(float v, float base = 261.625580f, float factor = 1.0f)
{  
	return powf(2, v) * (base / factor);
}

It is added to the voltage given by the knob, the V/Oct tracking on CV input works really well by the way.
The only problem is that the frequency range of the knob is really small, even padded with 30 midi notes I only have a range from about ~50hz to ~1400hz.

During testing and debugging I founded that without any voltage to CV input and the knob fully turned clockwise the maximum value return by patch.GetADCValue(CV_1) is around 0.64.
Maybe the problem is here ?

Sadly it don’t works, as the scale and offset were calculated with VoctCalibration class. This class calculate scale and offset to convert to a midi note

Sorry, why do you need to use that class?

To calibrate the CV input that is used as a V/Oct input. The CV_1 ADC is connected to the CV input and a knob (I can’t change this hardware design as i’m working on already existant module called Sibilla that is using a patch submodule, I’m trying to create a custom firmware on it)

Are you trying then to go from V/Oct to midi, or V/Oct to frequency?

how about using a linearMap function?

// linear rescaling
inline float linearMap(float x, float in_min, float in_max, float out_min, float out_max)
{
	if (x < 0.0f)
	{
		x = 0.0f;
	}

	return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

Here i’m trying to go from V/Oct to midi due to the ‘limitation’ of VoctCalibration class, but at the end i need a frequency to feed my oscillator, that is why i use the mtof function that convert a midi note to a frequency.

If there is a method that permit to have a great V/Oct tracking on CV input and a wide range of frequencies on the knob I will use it !

I will try the linear rescaling but as far as i know V/Oct must be exponential, am I wrong ?

I believe that frequency is exponential, v/oct is linear.

1v oct chart.pdf (102.2 KB)

I don’t think you need to use midi, just scale your voltage and use frequency to volt function.

1V/octave is NOT linear for frequency. Yes, the voltage goes up in equal steps, but the frequency doesn’t.

It would be helpful to see a schematic of how the CV and pot are wired. If the pot is powered by 5V, and is going into a CV input which is calibrated to 1V/octave, then it is appropriate for the pot to have a 5 octave range.

Ok so I added the linearMap idea float climb_freq = vtof(linearMap(climb_knob, -0.020172, 0.637573, 0, 5)); (those weird floats are the value returned by the ADC when the knob is in min and max position)

The knob have now a much wider range but it begin (at min position) only at aroud D2 (so around 293hz) and the V/Oct deviate from +10cents every octave

Am i missing something ?

Sadly I didn’t have the schematic as I didn’t created this module (Sibilla by Clatters), I searched for it on internet but didn’t find anything. I doubt that the CV input is calibrated for V/Oct as I didn’t see any trimpot on the PCB. There is only 4 Opamps (TL074) a couple of resistors, some capacitors and diodes and of course a patch submodule.

float cv_input = linearMap(climb_knob, -0.020172f, 0.637573f, 0.0f, 5.0f);
float climb_freq = vtof(cv_input, 261.625580f, 4.0f);

Try it this way perhaps, the 4.0f will divide the base frequency down two octaves.

Ah yes you are right I didn’t payed attention to the factor argument !
So it looks like it works, i keep having a difference of 10 cent every octave but that must due to min and max value of the knob, if you have a little bit of time do you have any idea how to have a precise value of the min and max value of the knob ? Is it even possible ?

Unfortunately I don’t know.

I would try to limit the cv_input to a range of 0.0f - 0.5f and see if that changes anything?

if (climb_knob < 0.0f)
{
climb_knob == 0.0f
}

if (climb_knob > 0.5f)
{
climb_knob = 0.5f;
}

tele_player is very knowledgeable and may be able to help you further.

Sadly it didn’t change anything, thanks a lot for your help !

The error of 10 cent per octave is the reason for calibration.

Is it adding an addition 10 cents for each octave above the base frequency?

Like this?

C1 + 0
C2 +10
C3 +20

Are you using a keyboard or a sequencer as the CV source? Can you output voltages for a number of octaves and check the values against the chart I uploaded?

You can write code to compensate, you will need some data though to look at to see what the pattern is.

Yes it’s exactly this !
I’m using a quantized sequencer as a CV source, I also tried with a keyboard and it’s the same case.

I will try to find a workaround to compensate this shift !

That is exactly what calibration is for.

Edit: I suppose I’ve been too brief in my responses.

If I’m reading correctly, using the code in the original post, CV tracking was good, but you want more range on the knob. That doesn’t seem feasible, since pot and CV are on the same ADC.

1 Like