Thanks

I will look into installing Faust locally, I am bit deterred by the vast
amount of dependencies
and my little experience with installing such projects.

I also don't have much experience with make and compiling and C,
but I think faust2rpialsaconsole might be onther option I have to look into
as running it on a Pi seems a reasonable solution for hardware.
I do have a Pi 400, on which unfortunately the Patch OS which might be a
good choice for OS does not run (or I didnt get it to run ).

to 4)
The code and concept is public and libre from my side, but maybe licenses
of third parties have to be considered.

So I reused and altered code from the Faust library ( by Julius Smith I
think ) for the allpass delay,
and the idea for the triangular filter was originally inspired by the
historic Variophon triangular oscillator, etc.
so at least a proper note with history and references would be desireable.
Since the concept has a really long history with many sources and variants,
and is floating on my desk since years,
it's a bit difficult to be accurate in this regards, and to do this justice.

The code also still needs some minor tweaks and cosmetic changes before it
is released in a 'final' version.
For instance it uses two SVFs in series at the moment with very similar
corner frequencies,
which could probably be replaced by a single SVF with a 'morphing' output.

A previous version had roughly antialiased synched noise (windowed with a
quarter sine wave) in a addition to the osciallator,
to mimick a corpus impulse response, and to enhance piano and string
reminiscent sounds.

I now tried to replace this with short allpass delays but it sounds less
convincing and "boxed", and setting
the length of the allpass chain is also too arbitrary att the moment.

Also noise has the interesting property that it has fluctuations, so a seed
could be matched
to produce a sequence that resembles the derivative (or 2nd derivative) of
a real corpus impulse response.

I would like to keep the paramter set to 4 though, as the idea for a
hardware interface is to have
two rows with 4 push and turn encoders each, one row for synth and one for
EQ and other effects,
with each encoder serving also as a button to select a set of 4 parameters
that belong together, like ADSR.
( sketch :
https://assets.steadyhq.com/production/post/c0d7b8ae-4d1f-4afa-afe8-8bcce17883ac/uploads/images/5prochhxdb/UI.jpg?auto=compress&w=800&fit=max&dpr=2&fm=webp
)

(Pressing two encoders in the corners simultanously could be used for
saveing and laoding presets.)

This is one reason why the noise was omitted in this version.

Such a controller should be seperate from the computing hardware and be
useful for many things,
and could be easy to build from two I²C breakout boards from Adafruit,
but I do not have the tools and funds for this at the moment, and it
requires
additional code for interfacing, which I do not have experience with.

The idea defintively is to make it an all open source and somewhat flexible
synth concept.

An interesting aspect for me is that it touches and fuses many aspects of
the history of synthesis,
and synthesis approaches, starting with the Trautonium, modulation
synthesis, subtractive,
aspects and findings of physical modeling, etc, in a very compact but
meaningful parameter set and combination.
( less paramter than a Mini Moog I think, from which it also borroughs of
course).

By this it is also a good simplified model to learn and teach I think, for
instance you could
examine what makes a sound "pianoide" and then expand on this with real
pianos and real accurate modeling
of real phyiscal forces etc., and then again examine their perceptual
significance and compare to this "cartoon"
version, and many similar things.

I dont know whats the best way to publish this so others can contribute and
expand on this.
Maintaining and ovreseeing a project on Sourceforge or similar requires a
lot of work and energy and experience
which I do not have.
So I am also looking for interested people I can hand this idea over,
Including it with Faust examples would be interesting in this regards,  but
I am not sure it is fundamental and also simple enough for this, etc.

Gabriel




On Wed, Sep 10, 2025 at 3:14 PM Stéphane Letz <l...@grame.fr> wrote:

> Hi,
>
> Thanks for this interesting code. For exporting the code, you have several
> options:
>
> 1) exporting the DSP for a standard plugin format.
>
>         - you can possibly use the JUCE export for that, as an
> intermediate step:
> https://github.com/grame-cncm/faust/tree/master-dev/architecture/juce.
> For maximal flexibility the best would be to compile and install a local
> Faust version.
>
>         - another option is to use the Fadeli project
> https://github.com/DISTRHO/Fadeli
>
> 2) you may find more info on this page
> https://faust.grame.fr/community/powered-by-faust
>
> 3) you can connect to the Faust developer/user community on Discord
> channel, see https://faust.grame.fr/community/help/
>
> 4) You wrote « I am proposing the attached synthesis engine. » : Is the
> code public ? Are you interested to contribute it in the Faust examples:
> https://faustdoc.grame.fr/examples/
>
> Thanks.
>
> Stéphane
>
>
> > Le 4 sept. 2025 à 11:53, ga <gvoxangel...@gmail.com> a écrit :
> >
> > Hello
> > I am proposing the attached synthesis engine.
> > It uses a "3D" oscillator that oscillates in x,y, z ( similar to FM / AM)
> > The radius of x,y is fed into a pickup distortion, which goes into a
> triangular filter ( 3 phase offset copies going into an integrator) an
> asymmetric distortion.
> > It has only 4× 4 parameter, including classic ADSR and LFO, envelope
> hardwired to oscillation amplitudes.
> > Its capable of a variety of semi- realistic sounds.
> > Sound demo is here:
> > https://youtu.be/7CBhMcYDWac?feature=shared
> >
> >
> > I would need some help to streamline the code mor Faustian,
> > to export including GUI, and to export including the effect,
> > and maybe ideas how to port this to some small hardware, Pi or Daisy Pod
> ( though I doubt it will run there ). as well as opinion on the method and
> ideas.
> >
> > Code:
> >
> > declare options "[midi:on][nvoices:8]";
> > declare options "[-vec]";
> > declare name "Paradigma_9 v007";
> > declare version "0.0.7";
> > declare author "gabriel";
> > declare copyright "https://steady.page/en/voxangelica/";;
> > declare license "DWTW";
> > // a synthesizer with "philonic" 3D spin oscillator and triangular filter
> > import("stdfaust.lib");
> > import("maths.lib");
> >
> > // frequency ratios table
> > frtonum = waveform{1,16,9,6,5,4,7,3,8,5,7,15};
> > frtodiv = waveform{1,15,8,5,4,3,5,2,5,3,4, 8};
> >
> > // MIDI
> > midigrp(x) = hgroup("[1]MIDI",x);
> > f = nentry("freq",200,40,2000,0.1) ;
> > kmidi = nentry("key",69,0,127,1) ;
> > bend = ba.semi2ratio(hslider("bend[midi:pitchwheel][style:
> knob]",0,-2,2,0.01)) ;
> > gain = nentry("gain",0.6,0,1,0.01)<:* ;
> > master = hslider("volume[midi:ctrl 7]",1,0,2,0.01) ;
> > gate = button("gate") ;
> >
> > // spin oscill params
> > rtogrp(x) = hgroup("[2]philonic",x);
> > rto1sel = rtogrp(hslider("[1]x[style:knob]",-12,-24,24,1));
> > rto2sel = rtogrp(hslider("[2]z[style:knob]",19,-24,24,1));
> > fbka =
> rtogrp(hslider("[3]excentric[style:knob]",0.4,0,1,0.01)<:*:*(1/ma.PI));
> > detune =
> rtogrp(hslider("[4]warble[style:knob]",0.125,0,0.5,0.005)/ma.SR);
> > pickd =
> rtogrp(hslider("[5]distance[style:knob]",0.7,0.25,1,0.0625))<:*:si.smoo;
> >
> > // LFO and Envelope Parameter
> > lfogrp(x) = hgroup("[3]envelope & lfo",x);
> > enva = (lfogrp(ba.db2linear(hslider("[1]A[style:knob]",20,15,66,1)
> )/1000));
> > envd = (lfogrp(ba.db2linear(hslider("[2]D[style:knob]",74,26,100,1)
> )/1000)*envpscal);
> > envs = (lfogrp(hslider("[3]S[style:knob]",0,0,1,0.01) ));
> > envr = (lfogrp(ba.db2linear(hslider("[4]R[style:knob]",50,26,100,1)
> )/1000)*envpscal);
> > lfof = lfogrp(hslider("[5]LFO Hz[style:knob]",3,0.1,12,0.1));
> > lfvibra = lfogrp(hslider("[6]Vibrato[style:knob]",0.125,0,2,0.01))<:*;
> >
> > env = en.adsre(enva,envd*envpscal,envs,envr*envpscal,gate);
> > envg = env:_* gain;
> >
> > lfosn = qsin(mphasor(lfof/ma.SR));
> >
> > // Triangular Filter Parameter
> > fltgrp(x) = hgroup("[4]triangulation",x);
> > wid = fltgrp(hslider("[1]rise[style:knob]",4.89,1,9,0.001)):2^_:1/_;
> > edge = fltgrp(hslider("[2]fall[style:knob]",6,1,9,0.001)):2^_:1/_;
> > fiq = fltgrp(hslider("[3]q[style:knob]",1.18,0.5,3.87,0.01))<:*;
> > hpon = fltgrp(checkbox("[4]highpass"));
> > drive = fltgrp(hslider("[5]drive[style:knob]",0,-6,36,0.1)):_/20.0:10^_;
> >
> > rto1oct = rto1sel / 12 : floor;
> > rto1semi = rto1sel + 24 : _% 12;
> > rto1a = frtonum, rto1semi : rdtable;
> > rto1b = frtodiv, rto1semi : rdtable;
> > rto1 = (rto1a/rto1b)*(2^rto1oct);
> > rto1r = min((1/ rto1),1);
> >
> > rto2oct = rto2sel / 12 : floor;
> > rto2semi = rto2sel + 24 : _% 12;
> > rto2a = frtonum, rto2semi : rdtable;
> > rto2b = frtodiv, rto2semi : rdtable;
> > rto2 = rto1*(rto2a/rto2b)*(2^rto2oct);
> > rto2r = min((1 / rto2),1);
> >
> > // fve
> > lg2f = ma.log2(f/440);
> > stretch = 0.0333*lg2f;
> > envpscal = ( - 3 * lg2f ):ba.db2linear;
> > fplus = f*bend + lfosn* lfvibra*f * 0.5/12*envg + stretch;
> >
> > w = f/ma.SR;
> > w2 = rto1 * w;
> > w3 = rto2 * w;
> > wplus = fplus/ma.SR;
> >
> > fbk1 = fbka*(0.5 -w)^4;
> > fbk2 = fbka*(0.5 - w2)^4*rto1r;
> > fbk3 = fbka*(0.5 - w3)^4*rto2r;
> >
> > // modulation reduction per frequency
> > redux1 = ((3.3 -((rto1+1)*w) )/3.3),0: max:_^3;
> > redux2 = ((3.3 -((rto2+1)*w) )/3.3),0: max:_^3;
> > modep = envg;
> > modep1 = envg * redux1 *rto1r * gain ;
> > modep2 = envg * redux2 *rto2r * gain ;
> >
> > // sine oscillator
> > wrap(n) = n-( floor( n +0.5)) ;
> > qsincurve(x) = 1 - ( (x*x)<: *(1.2253517*16),(_<:*:*
> (-3.60562732*16)):>_ );
> > qsin(x) = x+(0.5): wrap <: (abs:-(0.25):qsincurve),_:ma.copysign;
> > // feedback depth reduction curve
> > fbcurve (x)= x:abs:-(1) <:^(3):_,(x):ma.copysign;
> >
> > // oscillator
> > mphasor(fw) = (+(fw) ~ (wrap));
> > oscsn(fw, off) = mphasor(fw) + off:qsin:+~*(0.5);
> > osc1(fw, off) = ((fw),+(off):(oscsn)) ~
> (*(fbk2):fi.pole(0.5):_*fbcurve(fw));
> > dcrem(x) = x <:_,_': -: +~*(0.999773243);
> >
> > // 3D
> > oscy(fw, off) = (osc1(fw, off )*osc1(fw*rto2+2*detune,0.75 +
> off)*modep2)*modep;
> > oscx(fw, off) = (osc1(fw*rto1+detune,0.25 +
> off)*osc1(fw*rto2+2*detune,0.25 + off)*modep2)*modep1;
> > oscxy(fw, off) = (oscy(fw, off)<:*),(oscx(fw, off)<:*):+:sqrt:
> fi.zero(1.0);//dcrem; //
> > //oscxyb(fw, off) = (oscy(fw, off):fi.zero(1)) <:_,(_^2),((oscx(fw,
> off):fi.zero(1):_^2)): _, (_+_):_,(_+0.1:_^(3/2)):_/_;
> > // with pickup
> > oscxyc(fw, off) = oscxy(fw, off) <:_,(_^2:_+pickd:_^(3/2)):/;
> > //
> > //synthvox(fw, ph2, ph3, g1, g2, g3) = (oscxy(fw, 0):_*g1), (oscxy(fw,
> ph2):_*g2),(oscxy(fw, ph3):_*g3):>_ ;
> > synthvox(fw, ph2, ph3, g1, g2, g3) = (oscxyc(fw, 0):_*g1), (oscxyc(fw,
> ph2):_*g2),(oscxyc(fw, ph3):_*g3):>_ ;
> > // triangulation
> > widredux = w <:+:_^3:1.0-_;
> > // diff to max f in octaves, reduced for higher octaves
> > dwo = ( 0.25 / wid ):max(_, 1): ma.log2: ma.inv: _*widredux: ma.inv;
> > //edge = 1/7; // falling triangle edge,
> > egderto = edge / wid;
> > wid2 = wid * (2^(dwo * (1-envg ))):
> >         _* (2^(dwo * (1- gain ) )):
> >         min( _, 0.25): max( _, 4 / (ma.SR/fplus));
> > wid2e = edge: min( _, 0.25): max( _, 4 /(ma.SR/fplus));
> >
> > fiw = wplus/wid2;
> > fiwtail = wplus/wid2e;
> > // triangle coefficients
> > apg0 = fiw;
> > apg1 = - apg0 - fiwtail;
> > apg2 = fiwtail;
> > // integration freq
> > igpole = 1.0-5.0/ma.SR;
> > resf = (fplus /( wid2 +wid2e) ): min( _, (0.249 * ma.SR));
> >
> > // shaper
> > // x - 0.15x²-0.15x³
> > tubicclip = _:min(_, (1.19419)):max(_,(-1.86086));
> > //tubic(x) = x - 0.15*(x^2)-0.15*(x^3);
> > tubicilo(x) = x,
> >                 // normal for in < 1.2e-4
> >                 ( x - 0.15*(x^2)-0.15*(x^3) ),
> >                 // ILO:
> >                 (( 0.5*(x^2) - 0.05*(x^3) - 0.0375*(x^4) ),(x <:_,_':-
> :_<:(abs:max(_,1.2e-4)),(ma.signum):ma.copysign):/):
> >                 // select
> >                 ba.if( (_:abs:_<= 1.2e-4), _, _ ):dcrem;
> > //
> > superfbp = 1 - sin( 2 * ma.PI * w );
> >
> > // make sound
> > process = synthvox(wplus, wid2, wid2e, apg0, apg1, apg2):
> fi.dcblockerat(10.0): fi.pole(igpole) : fi.svf.peak( resf, fiq) <:
> >             ba.if( hpon, fi.svf.hp( fplus/(wid+wid):min(_, ma.SR*0.249),
> 0.707 ),_):
> >             _*drive: tubicclip: tubicilo:_*(1/drive);
> > effect = _ * master:rev;
> >
> > //
> ###############################################################################################
> > // CIELverb
> ######################################################################################
> > // minimalist reverb
> > //
> > // UI
> > revgrp(x) = hgroup("[5]reverb",x);
> > sizem =
> revgrp(hslider("[1]size[style:knob]",0,-1.5,1.5,0.02)):(2.0)^_:_*16.7:si.smoo;
> > revt = revgrp(hslider("[2]revTime[style:knob]",60,40,80,0.1)):
> ba.db2linear:_*0.001;
> > bright = revgrp(hslider("[4]brightness[style:knob]",90,52,112,0.1)):
> ba.midikey2hz;
> > earlyl = revgrp(hslider("[5]early/late[style:knob]",0,0,1,0.01));
> > drywet = revgrp(hslider("[6]dry/wet[style:knob]",0.5,0,1,0.01)) <:*;
> >
> > // reverb settings
> > // change revt with size
> > revtadapt = revt * ( 0.161*(sizem^3)/(6*sizem^2 ));
> > // diffusion delay times
> > revd0 = ma.SR * (sizem / 334);
> > revd1 = revd0 * 1 / ( 2 - log(2));
> > revd2 = revd0 * 1 / ( 3 - log(2));
> > revd3 = revd0 * 1 / ( 4 - log(2));
> > revgn = 10^(-3*(( sizem/ 334 )/revtadapt));
> > // diffusion allpass coeficients
> > revc = 0.707;//0.61803; //
> > revc1 = -revc * 10^(-3*(( revd1/ ma.SR )/revtadapt));
> > revc2 = -revc * 10^(-3*(( revd2/ ma.SR )/revtadapt));
> > revc3 = -revc * 10^(-3*(( revd3/ ma.SR )/revtadapt));
> > // post (early)
> > revdp = revd3 * 1 / ( 4 - log(2));
> > postd1 = revdp * 1 / ( 2 - log(2));
> > postd2 = postd1 * 1 / ( 3 - log(2));
> > postd3 = postd2 * 1 / ( 4 - log(2));
> > postc = 0.382;//1/3;//0.61803; //
> > postc1 = -postc * 10^(-3*(( postd1/ ma.SR )/(revtadapt * 1 / ( 4 -
> log(2)))));
> > postc2 = -postc * 10^(-3*(( postd2/ ma.SR )/(revtadapt * 1 / ( 4 -
> log(2)))));
> > postc3 = -postc * 10^(-3*(( postd2/ ma.SR )/(revtadapt * 1 / ( 4 -
> log(2)))));
> >
> > // left right delay time offsets
> > postdlroff = ma.SR * 0.15 /334 ;
> >
> > lfo1 = os.oscsin(0.13)*8.0;
> > apcomblp(maxdel,N,g) = (+ <:
> (de.fdelay1a(maxdel,N-1.5)<:_,_':+:_*0.5),*(g)) ~ *(-g) : mem,_ : +;
> > // post diffusion (early reflections, placed after reverb loop)
> > postdiff( in ) = in <:
> >                 (apcomblp( 4096, postd1, postc1): apcomblp( 4096, postd2
> + postdlroff, postc2): apcomblp( 4096, postd3 - postdlroff*0.382, postc3)),
> >                 (apcomblp( 4096, postd1 + postdlroff, postc1) :apcomblp(
> 4096, postd2 - postdlroff*0.382, postc2): apcomblp( 4096, postd3, postc3));
> >
> > // feedback filter
> > dampp = sin( 2 * ma.PI * bright/ma.SR);
> > fidamp = _*(dampp) : +~*(1-dampp) <:_,_':+:_*0.5: *(revgn);
> >
> >
> > // reverb
> > rev = _<: +~ (apcomblp( 4096, revd1 - lfo1, revc1):apcomblp( 4096, revd2
> + lfo1, revc2): apcomblp( 4096, revd3,revc3): de.fdelay1a( 4096, revd0
> ):fidamp ),_:(_*drywet:postdiff),((_*(1-drywet))<:_,_):route(4, 4,
> (1,1),(2,3),(3,2),(4,4)):>(_+_),(_+_);
> >
> > // END REVERB
> ############################################################################
> >
> > _______________________________________________
> > Faudiostream-users mailing list
> > Faudiostream-users@lists.sourceforge.net
> > https://lists.sourceforge.net/lists/listinfo/faudiostream-users
>
>
_______________________________________________
Faudiostream-users mailing list
Faudiostream-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/faudiostream-users

Reply via email to