Hello, just to have a better understanding of this Ugen, could someone put me on track here ? Thanks a lot.

Do you want to do this in a SynthDef with just SinOsc? Or … what do you mean by ‘on track?’

Yes, a SynthDef with SinOsc’s (do we need to use also a BPF ?).

I would like to understand the structural relation between fundfreq / formfreq / bwfreq…

Thanks !

Great - that helps. And yes, I’m guessing in the end you’ll need more that SinOscs (which makes the title of the topic a little confusing unless you want an example to get as close as you can). I don’t have an answer at the moment, but I’ll take a look later to see what I can suggest.

for creating formants you need two resonances. for example two RLPFs or two SinOscs:

```
(
{
var lfo = MouseX.kr(1,0);
var sig = SinOsc.ar(lfo.linexp(0, 1, 100, 500)) + SinOsc.ar(lfo.linexp(0, 1, 1000, 500));
sig ! 2 * 0.1;
}.play;
)
s.freqscope;
```

EDIT: here are also two versions of windowed sync which is doing a kind of fake RLPF by shifting the formants:

1.)

```
(
SynthDef(\windowsync, {
arg syncEgTop=8, syncRatio=2, syncDcy=0.5;
var syncEnv = EnvGen.kr(Env([syncEgTop / syncRatio, 1], [syncDcy], \exp));
var gainEnv = EnvGen.kr(Env.adsr(0.01, 0.3, 0.6, 0.1), \gate.kr(1), doneAction: Done.freeSelf);
var freq = \freq.ar(440);
var sig, in, phase, synced;
in = LFTri.ar(freq);
phase = Sweep.ar(in, freq * syncRatio * syncEnv);
synced = SinOsc.ar(0, (phase % 1) * 2pi).squared;
sig = synced * in;
sig = sig * gainEnv;
sig = Pan2.ar(sig, \pan.kr(0), \amp.kr(0.25));
Out.ar(\out.kr(0), sig);
}).add;
)
(instrument: \windowsync, freq: [57,60,64,65,70].midicps, syncEgTop: 20).play;
```

2.)

```
(
SynthDef(\windowsync, {
arg freq=440, syncRatio=2, syncEgTop=20, syncDcy=0.5, overlap=1;
var sig, fundamental, synced;
var freqEnv = EnvGen.kr(Env([syncEgTop / syncRatio, 1], [syncDcy], \exp));
var gainEnv = EnvGen.kr(Env.adsr(0.01, 0.3, 0.6, 0.1), \gate.kr(1), doneAction: Done.freeSelf);
fundamental = GrainSin.ar(
numChannels: 1,
trigger: Impulse.ar(freq),
dur: 1 / freq,
freq: freq,
);
synced = GrainSin.ar(
numChannels: 1,
trigger: fundamental,
dur: overlap / freq,
freq: freq * syncRatio * freqEnv,
);
sig = synced.squared * fundamental;
sig = LeakDC.ar(sig);
sig = sig * gainEnv;
sig = Pan2.ar(sig, \pan.kr(0), \amp.kr(0.25));
Out.ar(\out.kr(0), sig);
}).add;
)
(instrument: \windowsync, freq: [57,60,64,65,70].midicps, syncEgTop: 20).play;
```

and a vector phase shaping pseudo Ugen ive been working on some time ago. whichs produces formants for bigger vertical values:

```
(
var nearestEven, nearestOdd, vps;
nearestEven = {
arg val;
var val_floor, val_ceil, res, distance;
val_floor = val.floor;
val_ceil = val.ceil;
res = Select.ar(val % 2,
[ val_floor, val_ceil ],
);
distance = (val - res).abs;
[ res, distance ];
};
nearestOdd = {
arg val;
var val_floor, val_ceil, res, distance;
val_floor = val.floor;
val_ceil = val.ceil;
res = Select.ar(val + 1 % 2,
[ val_floor, val_ceil ],
);
distance = (val - res).abs;
[ res, distance ];
};
vps = { |trig, freq, horizontal, vertical|
var vertical_even = nearestEven.(vertical);
var vertical_odd = nearestOdd.(vertical);
var cos, phasor, sig;
vertical = [vertical_even[0], vertical_odd[0]];
phasor = Phasor.ar(Impulse.ar(trig), freq/2 * SampleDur.ir, horizontal.neg, 1-horizontal, horizontal.neg);
phasor = phasor.bilin(0, horizontal.neg, 1-horizontal, vertical, 0, 1);
cos = (phasor * 2pi).cos.neg;
sig = XFade2.ar(cos[0], cos[1], vertical_even[1] * 2 - 1);
sig = LeakDC.ar(sig);
sig;
};
{
var freq = \freq.kr(110);
var horizontal = MouseX.kr(0.01,0.99);
var vertical = K2A.ar(MouseY.kr(1.0,10.0));
var sig = vps.(0, freq, horizontal, vertical);
sig!2 * 0.1;
}.play(fadeTime: 0);
)
```

Great examples, the vector phase is wonderfull, thanks a lot @ dietcv !