Skip to content

Commit

Permalink
lichen-community-systemsgh-65: Example of working multi-segment fit f…
Browse files Browse the repository at this point in the history
…or 1v/oct calibration.
  • Loading branch information
colinbdclark committed Nov 26, 2023
1 parent 2f6a6a4 commit 1a2e4b1
Showing 1 changed file with 28 additions and 19 deletions.
47 changes: 28 additions & 19 deletions libsignaletic/src/libsignaletic.c
Original file line number Diff line number Diff line change
Expand Up @@ -2875,27 +2875,36 @@ void sig_dsp_Calibrator_generate(void* signal) {
// The ADC tops out slightly before 5 volts,
// so this keeps it the in the range of 9 semitones
// above the fourth octave.
// This sounds accurate at 2V, but is flat
// in octaves below and sharp in higher ones.

// size_t calibrationIdx = (size_t) floorf(fabsf(source));
// struct sig_dsp_Calibrator_State start = self->states[calibrationIdx];
// struct sig_dsp_Calibrator_State end = self->states[calibrationIdx + 1];
// float yk = start.avg;
// float ykplus1 = end.avg;
// float tk = start.target;
// float tkplus1 = end.target;
// float px = yk + ((ykplus1 - yk) / (tkplus1 - tk)) * (source - tk);
// FLOAT_ARRAY(self->outputs.main)[i] = px;

float yk = self->states[1].avg;
float ykplus1 = self->states[3].avg;
float delta = ykplus1 - yk;
float scale = 2.0f / delta;
float offset = 1.0f - scale * yk;
float px = offset + (scale * source);
// This is now very accurate across the whole range,
// Although it does seem to be about 10 cents flat for some reason.

// Look up the start and end values of the segment
// that our value is within range of.
size_t calibrationIdx = (size_t) floorf(sig_clamp(source, 0.0f, 4.0f));
struct sig_dsp_Calibrator_State start = self->states[calibrationIdx];
struct sig_dsp_Calibrator_State end = self->states[calibrationIdx + 1];

// y is the target segment.
float yk = start.target;
float ykplus1 = end.target;

// t is the measured segment during the calibration process.
float tk = start.avg;
float tkplus1 = end.avg;

// x is the incoming sample to be fit to the segment.
float x = source;
float px = yk + ((ykplus1 - yk) / (tkplus1 - tk)) * (x - tk);
FLOAT_ARRAY(self->outputs.main)[i] = px;

// float yk = self->states[1].avg;
// float ykplus1 = self->states[3].avg;
// float delta = ykplus1 - yk;
// float scale = 2.0f / delta;
// float offset = 1.0f - scale * yk;
// float px = offset + (scale * source);
// FLOAT_ARRAY(self->outputs.main)[i] = px;

self->previousGate = gate;
}
}
Expand Down

0 comments on commit 1a2e4b1

Please sign in to comment.