Re: [Faudiostream-users] Virtual analog and filter discretization

2021-07-08 Thread Julius Smith
Greetings,

It sounds like there is a bug.  The bilinear transform preserves stability,
but it can get into trouble with "delay-free loops" when there is feedback
around what is transformed.

Nowadays, I would digitize an analog circuit using Jatin Chowdhury's latest
code, e.g.,

https://github.com/jatinchowdhury18/KlonCentaur.git
https://github.com/jatinchowdhury18/wdf-bakeoff

(It's still using bilinear transforms, but element by element, for the most
part, resolving delay-free loops using Wave Digital Filter ideas)

On Thu, Jul 8, 2021 at 6:13 AM Jean Pierre Cimalando via Faudiostream-users
 wrote:

> Hello,
>
> recently I implemented and published a music plugin with faust [1],
> which implements the digital model of a bass tone circuit.
>
> A problem encountered during this process is the discretization of the
> EQ section, located on the bottom part of the schematic [2], running
> from C25 to C20 not included.
>
> This circuit describes as a low-frequency peak filter (+ or - gain),
> combined with a high-frequency shelf, parameterized by a pair of coupled
> knobs labelled as bass and treble.
>
> I have produced a program for computing the expression for the analog
> transfer function [3], and applying the bilinear transform.
> While the analog transfer function matches the SPICE results, I observed
> the digital filter does not meet the criterion for stability (that is,
> poles inside the unit circle).
>
> There is faust source code [4], the unstable EQ is replaced with an
> adhoc substitute having a relatively matching transfer function.
>
> Any hints on producing a more valid discretization of this system?
> Thank you very much
>
> [1] https://github.com/jpcima/Bass21
> [2] https://blog-imgs-91-origin.fc2.com/d/r/u/drugscore/02_49_4SABDsch.png
> [3] https://git.io/JcQi5
> [4] https://git.io/JcQPy
>
>
> ___
> Faudiostream-users mailing list
> Faudiostream-users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/faudiostream-users
>


-- 
"Anybody who knows all about nothing knows everything" -- Leonard Susskind
___
Faudiostream-users mailing list
Faudiostream-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/faudiostream-users


Re: [Faudiostream-users] lufs loudness analyser

2021-07-08 Thread Julius Smith
Hi Dario,

The problem seems to be architecture-dependent.  I am on a Mac (latest
non-beta software) using faust2caqt.  What are you using?

I do not see the "strange behavior" you describe.

Your test looks good for me in faust2octave, with gain set to 0.01 (-40 dB,
which triggers the display bug on my system).  In Octave, faustout(end,:)
shows

 -44.744  -44.968  -44.708

which at first glance seems close enough for noise input and slightly
different averaging windows.  Changing the signal to a constant 0.01, I get

 -39.994  -40.225  -40.000

which is not too bad, but which should probably be sharpened up.  The third
value (zi_lp) is right on, of course.

gain = 0.01; // hslider("Gain [unit:dB]",-70,-70,0,0.1) : ba.db2linear;
sig = gain;  //sig = no.noise * gain;

On Thu, Jul 8, 2021 at 3:53 AM Dario Sanfilippo 
wrote:

> Hi, Julius.
>
> I must be missing something, but I couldn't see the behaviour that you
> described, that is, the gating behaviour happening only for the display and
> not for the output.
>
> If a remove the hbargraph altogether, I can still see the strange
> behaviour. Just so we're all on the same page, the strange behaviour we're
> referring to is the fact that, after going back to low input gains, the
> displayed levels are -inf instead of some low, quantifiable ones, right?
>
> Using a leaky integrator makes the calculations rather inaccurate. I'd say
> that, if one needs to use single-precision, averaging with a one-pole
> lowpass would be best:
>
> import("stdfaust.lib");
> zi = an.ms_envelope_rect(Tg);
> slidingSum(n) = fi.pole(.99) <: _, _@int(max(0,n)) :> -;
> slidingMean(n) = slidingSum(n)/rint(n);
> zi_leaky(x) = slidingMean(Tg*ma.SR, x * x);
> lp1p(cf, x) = fi.pole(b, x * (1 - b))
> with {
> b = exp(-2 * ma.PI * cf / ma.SR);
> };
> zi_lp(x) = lp1p(1 / Tg, x * x);
> Tg = 0.4;
> sig = no.noise * gain;
> gain = hslider("Gain [unit:dB]",-70,-70,0,0.1) : ba.db2linear;
> level = ba.linear2db : *(0.5);
> process = sig <: level(zi) , level(zi_leaky) , level(zi_lp);
>
> Ciao,
> Dr Dario Sanfilippo
> http://dariosanfilippo.com
>
>
> On Thu, 8 Jul 2021 at 00:39, Julius Smith  wrote:
>
>> > I think that the problem is in an.ms_envelope_rect, particularly the
>> fact that it has a non-leaky integrator. I assume that when large values
>> recirculate in the integrator, the smaller ones, after pushing the gain
>> down, are truncated to 0 due to single-precision. As a matter of fact,
>> compiling the code in double precision looks fine here.
>>
>> I just took a look and see that it's essentially based on + ~ _ : (_
>> - @(rectWindowLenthSamples))
>> This will indeed suffer from a growing roundoff error variance over time
>> (typically linear growth).
>> However, I do not see any noticeable effects of this in my testing thus
>> far.
>> To address this properly, we should be using TIIR filtering principles
>> ("Truncated IIR"), in which two such units pingpong and alternately reset.
>> Alternatively, a small exponential decay can be added: + ~ *(0.99)
>> ... etc.
>>
>> - Julius
>>
>> On Wed, Jul 7, 2021 at 12:32 PM Dario Sanfilippo <
>> sanfilippo.da...@gmail.com> wrote:
>>
>>> I think that the problem is in an.ms_envelope_rect, particularly the
>>> fact that it has a non-leaky integrator. I assume that when large values
>>> recirculate in the integrator, the smaller ones, after pushing the gain
>>> down, are truncated to 0 due to single-precision. As a matter of fact,
>>> compiling the code in double precision looks fine here.
>>>
>>> Ciao,
>>> Dr Dario Sanfilippo
>>> http://dariosanfilippo.com
>>>
>>>
>>> On Wed, 7 Jul 2021 at 19:25, Stéphane Letz  wrote:
>>>
 « hargraph seems to have some kind of a gate in it that kicks in around
 -35 dB. » humm…. hargraph/vbargrah only keep the last value of their
 written FAUSTFLOAT* zone, so once per block, without any processing of
 course…

 Have you looked at the produce C++ code?

 Stéphane

 > Le 7 juil. 2021 à 18:31, Julius Smith  a
 écrit :
 >
 > That is strange - hbargraph seems to have some kind of a gate in it
 that kicks in around -35 dB.
 >
 > In this modified version, you can hear that the sound is ok:
 >
 > import("stdfaust.lib");
 > Tg = 0.4;
 > zi = an.ms_envelope_rect(Tg);
 > gain = hslider("Gain [unit:dB]",-10,-70,0,0.1) : ba.db2linear;
 > sig = no.noise * gain;
 > process = attach(sig, (sig : zi : ba.linear2db : *(0.5) :
 hbargraph("test",-70,0)));
 >
 > On Wed, Jul 7, 2021 at 12:59 AM Klaus Scheuermann 
 wrote:
 > Hi all,
 > I did some testing and
 >
 > an.ms_envelope_rect()
 >
 > seems to show some strange behaviour (at least to me). Here is a video
 > of the test:
 > https://cloud.4ohm.de/s/64caEPBqxXeRMt5
 >
 > The audio is white noise and the testing code is:
 >
 > import("stdfaust.lib");
 > Tg = 0.4;
 > zi = an.ms_envelope_rect(Tg);
 > process = _ : zi : b

[Faudiostream-users] Virtual analog and filter discretization

2021-07-08 Thread Jean Pierre Cimalando via Faudiostream-users
Hello,

recently I implemented and published a music plugin with faust [1],
which implements the digital model of a bass tone circuit.

A problem encountered during this process is the discretization of the
EQ section, located on the bottom part of the schematic [2], running
from C25 to C20 not included.

This circuit describes as a low-frequency peak filter (+ or - gain),
combined with a high-frequency shelf, parameterized by a pair of coupled
knobs labelled as bass and treble.

I have produced a program for computing the expression for the analog
transfer function [3], and applying the bilinear transform.
While the analog transfer function matches the SPICE results, I observed
the digital filter does not meet the criterion for stability (that is,
poles inside the unit circle).

There is faust source code [4], the unstable EQ is replaced with an
adhoc substitute having a relatively matching transfer function.

Any hints on producing a more valid discretization of this system?
Thank you very much

[1] https://github.com/jpcima/Bass21
[2] https://blog-imgs-91-origin.fc2.com/d/r/u/drugscore/02_49_4SABDsch.png
[3] https://git.io/JcQi5
[4] https://git.io/JcQPy


___
Faudiostream-users mailing list
Faudiostream-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/faudiostream-users


Re: [Faudiostream-users] lufs loudness analyser

2021-07-08 Thread Dario Sanfilippo
Hi, Julius.

I must be missing something, but I couldn't see the behaviour that you
described, that is, the gating behaviour happening only for the display and
not for the output.

If a remove the hbargraph altogether, I can still see the strange
behaviour. Just so we're all on the same page, the strange behaviour we're
referring to is the fact that, after going back to low input gains, the
displayed levels are -inf instead of some low, quantifiable ones, right?

Using a leaky integrator makes the calculations rather inaccurate. I'd say
that, if one needs to use single-precision, averaging with a one-pole
lowpass would be best:

import("stdfaust.lib");
zi = an.ms_envelope_rect(Tg);
slidingSum(n) = fi.pole(.99) <: _, _@int(max(0,n)) :> -;
slidingMean(n) = slidingSum(n)/rint(n);
zi_leaky(x) = slidingMean(Tg*ma.SR, x * x);
lp1p(cf, x) = fi.pole(b, x * (1 - b))
with {
b = exp(-2 * ma.PI * cf / ma.SR);
};
zi_lp(x) = lp1p(1 / Tg, x * x);
Tg = 0.4;
sig = no.noise * gain;
gain = hslider("Gain [unit:dB]",-70,-70,0,0.1) : ba.db2linear;
level = ba.linear2db : *(0.5);
process = sig <: level(zi) , level(zi_leaky) , level(zi_lp);

Ciao,
Dr Dario Sanfilippo
http://dariosanfilippo.com


On Thu, 8 Jul 2021 at 00:39, Julius Smith  wrote:

> > I think that the problem is in an.ms_envelope_rect, particularly the
> fact that it has a non-leaky integrator. I assume that when large values
> recirculate in the integrator, the smaller ones, after pushing the gain
> down, are truncated to 0 due to single-precision. As a matter of fact,
> compiling the code in double precision looks fine here.
>
> I just took a look and see that it's essentially based on + ~ _ : (_
> - @(rectWindowLenthSamples))
> This will indeed suffer from a growing roundoff error variance over time
> (typically linear growth).
> However, I do not see any noticeable effects of this in my testing thus
> far.
> To address this properly, we should be using TIIR filtering principles
> ("Truncated IIR"), in which two such units pingpong and alternately reset.
> Alternatively, a small exponential decay can be added: + ~ *(0.99) ...
> etc.
>
> - Julius
>
> On Wed, Jul 7, 2021 at 12:32 PM Dario Sanfilippo <
> sanfilippo.da...@gmail.com> wrote:
>
>> I think that the problem is in an.ms_envelope_rect, particularly the
>> fact that it has a non-leaky integrator. I assume that when large values
>> recirculate in the integrator, the smaller ones, after pushing the gain
>> down, are truncated to 0 due to single-precision. As a matter of fact,
>> compiling the code in double precision looks fine here.
>>
>> Ciao,
>> Dr Dario Sanfilippo
>> http://dariosanfilippo.com
>>
>>
>> On Wed, 7 Jul 2021 at 19:25, Stéphane Letz  wrote:
>>
>>> « hargraph seems to have some kind of a gate in it that kicks in around
>>> -35 dB. » humm…. hargraph/vbargrah only keep the last value of their
>>> written FAUSTFLOAT* zone, so once per block, without any processing of
>>> course…
>>>
>>> Have you looked at the produce C++ code?
>>>
>>> Stéphane
>>>
>>> > Le 7 juil. 2021 à 18:31, Julius Smith  a
>>> écrit :
>>> >
>>> > That is strange - hbargraph seems to have some kind of a gate in it
>>> that kicks in around -35 dB.
>>> >
>>> > In this modified version, you can hear that the sound is ok:
>>> >
>>> > import("stdfaust.lib");
>>> > Tg = 0.4;
>>> > zi = an.ms_envelope_rect(Tg);
>>> > gain = hslider("Gain [unit:dB]",-10,-70,0,0.1) : ba.db2linear;
>>> > sig = no.noise * gain;
>>> > process = attach(sig, (sig : zi : ba.linear2db : *(0.5) :
>>> hbargraph("test",-70,0)));
>>> >
>>> > On Wed, Jul 7, 2021 at 12:59 AM Klaus Scheuermann 
>>> wrote:
>>> > Hi all,
>>> > I did some testing and
>>> >
>>> > an.ms_envelope_rect()
>>> >
>>> > seems to show some strange behaviour (at least to me). Here is a video
>>> > of the test:
>>> > https://cloud.4ohm.de/s/64caEPBqxXeRMt5
>>> >
>>> > The audio is white noise and the testing code is:
>>> >
>>> > import("stdfaust.lib");
>>> > Tg = 0.4;
>>> > zi = an.ms_envelope_rect(Tg);
>>> > process = _ : zi : ba.linear2db : hbargraph("test",-95,0);
>>> >
>>> > Could you please verify?
>>> >
>>> > Thanks, Klaus
>>> >
>>> >
>>> >
>>> > On 05.07.21 20:16, Julius Smith wrote:
>>> > > Hmmm, '!' means "block the signal", but attach should save the
>>> bargraph
>>> > > from being optimized away as a result.  Maybe I misremembered the
>>> > > argument order to attach?  While it's very simple in concept, it can
>>> be
>>> > > confusing in practice.
>>> > >
>>> > > I chose not to have a gate at all, but you can grab one from
>>> > > misceffects.lib if you like.  Low volume should not give -infinity,
>>> > > that's a bug, but zero should, and zero should become MIN as I
>>> mentioned
>>> > > so -infinity should never happen.
>>> > >
>>> > > Cheers,
>>> > > Julius
>>> > >
>>> > >
>>> > > On Mon, Jul 5, 2021 at 10:39 AM Klaus Scheuermann >> > > > wrote:
>>> > >
>>> > > Cheers Julius,
>>> > >
>>> > >
>>> > >
>>> > > At least I understood the 'attach' pr