Help with Hard Sync code

I ran across a feature of this freeware code by Xavier Halgand + Sean Bolton that uses minBlep filtered Osc’s.

I’m just now trying to figure out how to use the instances of each Osc created to create that “Let’s Go!” (The Cars) sound of Hard Synched Oscs.

Here's a snippet of the code...

–main struct used–

//class VCO_blepsaw

typedef struct
{
float out;
float amp;
float last_amp;
float freq;
float syncin;
float syncout;
float _p, _w, _z;
float _f [FILLEN + STEP_DD_PULSE_LENGTH];
int _j;
bool _init;

} VCO_blepsaw_t;

void VCO_blepsaw_Init(VCO_blepsaw_t *vco);
float VCO_blepsaw_SampleCompute(VCO_blepsaw_t *vco);


–a init function–

void VCO_blepsaw_Init(VCO_blepsaw_t *vco)
{
vco->_init = true;
vco->amp = 1.0f;
vco->freq = 440.f;
vco->syncin = 0.0f;
vco->_z = 0.0f;
vco->_j = 0;
memset (vco->_f, 0, (FILLEN + STEP_DD_PULSE_LENGTH) * sizeof (float));
}


–the main instance code–

float VCO_blepsaw_SampleCompute(VCO_blepsaw_t *vco)
{
int j;
float freq, syncin;
float a, p, t, w, dw, z;
syncin = vco->syncin;
freq = vco->freq;

p = vco->_p;  /* phase [0, 1) */
w = vco->_w;  /* phase increment */
z = vco->_z;  /* low pass filter state */
j = vco->_j;  /* index into buffer _f */

if (vco->_init) {
	p = 0.5f;
	w = freq / SAMPLERATE;
	if (w < 1e-5) w = 1e-5;
	if (w > 0.5) w = 0.5;
	/* if we valued alias-free startup over low startup time, we could do:
	 *   p -= w;
	 *   place_slope_dd(_f, j, 0.0f, w, -1.0f); */
	vco->_init = false;
}

//a = 0.2 + 0.8 * vco->_port [FILT];
a = 0.5f; // when a = 1, LPfilter is disabled

t = freq / SAMPLERATE;
if (t < 1e-5) t = 1e-5;
if (t > 0.5) t = 0.5;
dw = (t - w); // n= 1
w += dw;
p += w;

if (syncin >= 1e-20f) {  /* sync to master */

	float eof_offset = (syncin - 1e-20f) * w;
	float p_at_reset = p - eof_offset;
	p = eof_offset;

	/* place any DD that may have occurred in subsample before reset */
	if (p_at_reset >= 1.0f) {
		p_at_reset -= 1.0f;
		place_step_dd(vco->_f, j, p_at_reset + eof_offset, w, 1.0f);
	}

	/* now place reset DD */
	place_step_dd(vco->_f, j, p, w, p_at_reset);

	vco->syncout = syncin;  /* best we can do is pass on upstream sync */

} else if (p >= 1.0f) {  /* normal phase reset */

	p -= 1.0f;
	vco->syncout = p / w + 1e-20f;
	place_step_dd(vco->_f, j, p, w, 1.0f);

} else {

	vco->syncout = 0.0f;
}
vco->_f[j + DD_SAMPLE_DELAY] += 0.5f - p;

z += a * (vco->_f[j] - z); // LP filtering
vco->out = vco->amp * z;

if (++j == FILLEN)
{
	j = 0;
	memcpy (vco->_f, vco->_f + FILLEN, STEP_DD_PULSE_LENGTH * sizeof (float));
	memset (vco->_f + STEP_DD_PULSE_LENGTH, 0,  FILLEN * sizeof (float));
}

vco->_p = p;
vco->_w = w;
vco->_z = z;
vco->_j = j;

return vco->out;

}


There’s a few more functions to go with it, but I think the above is enough to get my question answered.

What I’m trying to figure out is:
DO I MAKE THE 1st minBlep Osc instance the MASTER and keep
vc0->syncin = 0;
??

To make things easier to track:
Let’s say I name the Master Osc “mastOsc” so I’d really have
mastOsc->syncin=0;
to start with.

Then…
Create a 2nd minBlep Osc, slaveOsc1, but USE THE MASTER’s
mastOsc->syncout
to synch slaveOsc1 to mastOsc??
thus I’d have
slaveOsc1->syncin = mastOsc->syncout

naturally I would have to tweak around mastOsc->freq and slaveOsc1->freq to get that Hard Sync effect…

or am I thinking this all wrong??

Thanks for any help.
/Blaine

Well I tinkered around with that code and did get it working!

If anyone cares to see…