Good morning!

Ok, I read it and removed two si.smoo from metering.

Could the whole lufs calculation be moved to control rate?

Or at least the calculation of loudness difference which uses a lp1p for
smoothing and gating?

difference(l,r)= (target- (Lk2(l,r):hbargraph("[1]Input LUFS
short-term",-40,0))):lp1p(leveler_speed_gated);

And how would I do that?
The latest code is here:
https://faustide.grame.fr/?code=https://raw.githubusercontent.com/trummerschlunk/master_me/master/master_me_gui.dsp

Klaus


On 20.07.21 23:24, Stéphane Letz wrote:
> Another tool to help understanding the code, using the « fir »  backend with 
> :  faust -lang fir  master_me_gui.dsp  (assuming «  make developer »  has 
> been used to compile Faust) 
>
> Then you can see that number of different operations in the methods,  
> especially the "Compute DSP » 
>
> ======= Compute DSP begin ==========
>
> Instructions complexity : Load = 886 Store = 257 Binop = 639 Mathop = 85 [ 
> expf = 1 fabsf = 18 log10f = 21 max_f = 25 min_f = 12 powf = 8 ] Numbers = 
> 413 Declare = 73 Cast = 27 Select = 0 Loop = 1 FunCall = 97
>
> ==> so a lof of heavy log10f, powf operations done for each computed sample.  
>
> If possible moving costly operatiosn from sample-rate to control rate can 
> help, read the first part of https://faustdoc.grame.fr/manual/optimizing/
>
> Stéphane
>
>
>> Le 20 juil. 2021 à 23:14, Klaus Scheuermann <kla...@posteo.de> a écrit :
>>
>> Thank you, I will read up on it...
>>
>> Just two more questions:
>>
>> 1.
>>
>> zi = an.ms_envelope_rect(Tg);
>> is still buggy, right? At least it behaves very differently than 'zi_lp'
>> 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);
>> 2.
>>
>> Regarding cpu-hunger, can you tell, which parts of master_me are eating up 
>> most resources?
>> For instance, I am calling 'Lk2' four times of which three are the same... 
>> does it matter?
>>
>> Klaus
>>
>> On 20.07.21 22:49, Stéphane Letz wrote:
>>> This is the occasion to remind all of you of some debugging tools that can 
>>> help here:
>>>
>>> - read 
>>> https://faustdoc.grame.fr/manual/optimizing/#debugging-the-dsp-code
>>>
>>>
>>> - especially the interp-trace tool: 
>>> https://github.com/grame-cncm/faust/tree/master-dev/tools/benchmark#interp-tracer
>>>
>>>
>>> - which gives on master_me_gui.dsp : interp-tracer -trace 4 
>>> master_me_gui.dsp 
>>>
>>> Libfaust version : 2.33.1 (LLVM 12.0.1)
>>> Compiled with additional options : 
>>> Using interpreter backend
>>> getName master_me_gui
>>> ------------------------
>>> init 44100
>>> ------------------------
>>> instanceInit 44100
>>> ------------------------
>>> classInit 44100
>>> ------------------------
>>> instanceConstants 44100
>>> ------------------------
>>> instanceResetUserInterface 
>>> ------------------------
>>> instanceClear 
>>> ------------------------
>>> compute 16
>>> -------- Interpreter 'Inf' trace start --------
>>> opcode 204 kLog10f int 0 real 0 offset1 -1 offset2 -1
>>> opcode 11 kLoadIndexedReal int 0 real 0 offset1 16 offset2 2 name fRec21
>>> opcode 1 kInt32Value int 0 real 0 offset1 -1 offset2 -1
>>> opcode 0 kRealValue int 0 real 20 offset1 -1 offset2 -1
>>> opcode 13 kStoreIndexedReal int 0 real 0 offset1 16 offset2 2 name fRec21
>>> opcode 1 kInt32Value int 0 real 0 offset1 -1 offset2 -1
>>> opcode 11 kLoadIndexedReal int 0 real 0 offset1 14 offset2 2 name fRec22
>>> opcode 1 kInt32Value int 0 real 0 offset1 -1 offset2 -1
>>>
>>> so does indeed detect the log10(0) failure reported by Dario.
>>>
>>> Stéphane 
>>>
>>>
>>>> Le 20 juil. 2021 à 22:40, Dario Sanfilippo <sanfilippo.da...@gmail.com>
>>>>  a écrit :
>>>>
>>>> Or you're feeding 0 to a log function. :-)
>>>>
>>>> Try this:
>>>>
>>>> Lk2 = Lk(0),Lk(2) :> 10 * log10(max(ma.EPSILON)) : -(0.691);
>>>>
>>>> Dr Dario Sanfilippo
>>>>
>>>> http://dariosanfilippo.com
>>>>
>>>>
>>>>
>>>> On Tue, 20 Jul 2021 at 22:28, Dario Sanfilippo 
>>>> <sanfilippo.da...@gmail.com>
>>>>  wrote:
>>>> Hello.
>>>>
>>>> On Tue, 20 Jul 2021 at 22:14, Klaus Scheuermann 
>>>> <kla...@posteo.de>
>>>>  wrote:
>>>> Hi Julius,
>>>>
>>>> I don't see a -70db lower limit... where is that?
>>>>
>>>> Besides... because
>>>>
>>>> zi = an.ms_envelope_rect(Tg);
>>>> seems really buggy, I am using Dario's workaround
>>>>
>>>> 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);
>>>> which gives me the 'crash'.
>>>>
>>>>
>>>> Unless Tg is 0 at some point, the crash shouldn't come from there.
>>>>
>>>> The crash happens if you start the process with audio file selected as 
>>>> inputs, hence zeros, so you may be dividing something by the input signals.
>>>>
>>>> Ciao,
>>>> Dario
>>>>
>>>>  
>>>> I cannot switch to double precision in the online faustide, right?
>>>>
>>>> Thanks, Klaus
>>>>
>>>>
>>>>
>>>> On 20.07.21 21:46, Julius Smith wrote:
>>>>
>>>>> Hi Klaus,
>>>>>
>>>>> Thanks for sharing master_me!
>>>>>
>>>>> Your envelope looks safe because of the -70 dB lower limit.
>>>>>
>>>>> You might try running everything in double precision to see if that has 
>>>>> any effect. 
>>>>>
>>>>> - Julius
>>>>>
>>>>> On Tue, Jul 20, 2021 at 3:13 AM Klaus Scheuermann 
>>>>> <kla...@posteo.de>
>>>>>  wrote:
>>>>> When the input lufs meter goes to '-infinity', the audio mutes and some 
>>>>> GUI parts disappear.
>>>>>
>>>>> On July 20, 2021 11:59:57 AM GMT+02:00, "Stéphane Letz" 
>>>>> <l...@grame.fr>
>>>>>  wrote:
>>>>>  «  crash at silence » ? what does that mean exactly?
>>>>>
>>>>> Thanks.
>>>>>
>>>>> Stéphane
>>>>>
>>>>>
>>>>> Le 20 juil. 2021 à 11:55, Klaus Scheuermann <
>>>>> kla...@posteo.de
>>>>>> a écrit :
>>>>>>
>>>>> Good day to all!
>>>>>
>>>>> All my TO-DOs are DONE - woohoo :) Here is the code:
>>>>>
>>>>>
>>>>> https://faustide.grame.fr/?code=https://raw.githubusercontent.com/trummerschlunk/master_me/master/master_me_gui.dsp
>>>>>
>>>>>
>>>>>
>>>>> The only thing that still behaves weird is the envelope in the LUFS 
>>>>> measurement section as it will crash at silence.
>>>>> Would anyone have some time to look into it?
>>>>>
>>>>> Thanks for all your help!
>>>>> Klaus
>>>>>
>>>>> On 17.07.21 18:03, Klaus Scheuermann wrote:
>>>>>
>>>>> Or maybe the 'gating' is better done in my 'leveler' section to keep the 
>>>>> continuous lufs metering specs-compliant?
>>>>>
>>>>> I guess that is a good idea ;)
>>>>> This way I can specify the gating characteristics.
>>>>> (I will probably need some help with this...)
>>>>>
>>>>> my TO-DOs:
>>>>> - slider for target loudness in lufs
>>>>> - new leveler section slowly adapting loudness to target loudness
>>>>> - gating: freeze leveler when silence is detected on input
>>>>>
>>>>> Almost there ;)
>>>>>
>>>>> By the way, does an.ms_envelope_rect() work correctly now?
>>>>>
>>>>> Cheers, Klaus
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On 17.07.21 15:30, Klaus Scheuermann wrote:
>>>>>
>>>>> Dear Juan Carlos,
>>>>>
>>>>> thanks so much for looking into the gating. I agree, we have 'momentary' 
>>>>> (Tg=0.4) and 'short-term' (Tg=3).
>>>>>
>>>>> I read some more about the secs from the EBU and I understood, that 
>>>>> 'integrated' is not quite what I need for 'master_me' as it is specified 
>>>>> with a user interaction of play/pause/reset. (from: 
>>>>>
>>>>> https://tech.ebu.ch/docs/tech/tech3341.pdf
>>>>> )
>>>>>
>>>>>
>>>>> The ‘EBU Mode’ loudness meter shall at least provide functionality that 
>>>>> enables the user to –
>>>>> 1. start/pause/continue the  measurement  of  integrated  loudness  and  
>>>>> Loudness  Range  simultaneously, that is, switch the meter between 
>>>>> ‘running’ and ‘stand-by’ states;
>>>>> 2. reset the  measurement  of  integrated  loudness  and  Loudness  Range 
>>>>>  simultaneously,  regardless of whether the meter is in the ‘running’ and 
>>>>> ‘stand-by’ state.
>>>>>
>>>>> For master_me, I need a 'long-term' with gating. Or even better 
>>>>> 'variable-term' with gating ;)
>>>>>
>>>>> So much for now... Trying to understand your gating code now... :)
>>>>>
>>>>> Thanks, Klaus
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On 16.07.21 21:32, Juan Carlos Blancas wrote:
>>>>>
>>>>> Hi Klaus,
>>>>>
>>>>> Glad to hear the project update with M LUFS meters.
>>>>>
>>>>> I did a little research, scheme and a working sketch in Max, maybe it 
>>>>> helps you somehow but my code in Faust its not working at the moment, 
>>>>> kind of lost with this program, 0 intuitive for me... I’m using ba.if for 
>>>>> the gates, ba.countup+ba.peakhold for resetable counter, and for the 
>>>>> running cumulative average this formula I found in internet; ( (counter * 
>>>>> _ ) + newValue) / (counter+1) )  ~ _; Main issue how to keep track of the 
>>>>> values from the gates and compute the running averages with an 
>>>>> incremental automatic counter until the next manual reset. Second round 
>>>>> soon when get more free time.
>>>>>
>>>>> Cheers,
>>>>> Juan Carlos
>>>>>
>>>>> ////////////////////////////
>>>>> /* 1770-3 scheme
>>>>>
>>>>> (M and I):
>>>>>
>>>>> 1) K-filter (HSF+RLB)—> sliding rect window, integration 400 ms, no gate 
>>>>> —>
>>>>> 2) Update the linear output of the 400 ms sliding rect window every 100 
>>>>> ms (75% overlap, 10Hz refresh) => get Momentary LUFS (power dB, -0.691 
>>>>> correction).
>>>>> 3) Absolute gate: threshold at -70 LUFS, values below are ignored, take 
>>>>> the linear values from the 10Hz updated 400 ms sliding window —>
>>>>> 4) Counting every value above the gate and calculate the running 
>>>>> cumulative average, with a manual reset button for the counter  —>
>>>>> 5) Relative gate: compare the output of the absolute gate with a -10 LU 
>>>>> drop of the previous averaging —>
>>>>> 6) Counting every value above the relative gate and calculate the running 
>>>>> cumulative average, with a manual reset button for the counter  => get 
>>>>> Integrated LUFS (power dB, -0.691 correction).
>>>>>
>>>>> (S and LRA):
>>>>>
>>>>> 1) Sliding rect window, integration 3 sec, no gate —>
>>>>> 2) Update the linear output of the 3 sec sliding rect window every 100 ms 
>>>>> (75% overlap, 10Hz refresh) => get Shorterm LUFS (power dB, -0.691 
>>>>> correction).
>>>>> 3) Calculate LRA …
>>>>> ………
>>>>>
>>>>> */
>>>>>
>>>>> import("stdfaust.lib");
>>>>>
>>>>> A48kHz = ( /* 1.0, */ -1.99004745483398, 0.99007225036621);
>>>>> B48kHz = (1.0, -2.0, 1.0);
>>>>> highpass48kHz = fi.iir(B48kHz,A48kHz);
>>>>> highpass = fi.highpass(2, 40);
>>>>>
>>>>> boostDB = 4;
>>>>> boostFreqHz = 1430;
>>>>> highshelf = fi.high_shelf(boostDB, boostFreqHz);
>>>>>
>>>>> kfilter = highshelf : highpass;
>>>>>
>>>>> MAXN = 262144;
>>>>> Tg = 0.4;
>>>>> Ovlp = 10; // Hz
>>>>>
>>>>> W = ma.SR*0.4;
>>>>> float2fix(n) = *(2^n) : int;
>>>>> fix2float(n) = float : /(2^n);
>>>>>
>>>>> avg400msWindow = kfilter : ^(2) : float2fix(16) <: _,@(W) : - : +~_ : 
>>>>> fix2float(16) : /(W);
>>>>>
>>>>> overlap100ms = ba.if( os.lf_pulsetrain(Ovlp) > 0.5, avg400msWindow, !);
>>>>> dB = (-0.691 + (10*log10(overlap100ms)));
>>>>>
>>>>> reset = button("reset") : ba.impulsify;
>>>>> gateAbsolute = ba.if( dB > -70, overlap100ms, !);
>>>>> counter1  = ba.if( dB > -70.0, 1, 0);
>>>>> sampleHold1 = ba.countup(ma.SR*300, 1-counter1+reset) <: _, 
>>>>> ba.peakhold(1-reset) :> _;
>>>>> cumulativeAverage1 = (((sampleHold1*_)+gateAbsolute)  / (sampleHold1+1))  
>>>>> ~ _;
>>>>>
>>>>> gateRelative = ba.if( (-0.691 + (10*log10(gateAbsolute))) > (-10.691 + 
>>>>> (10*log10(cumulativeAverage1))), overlap100ms, !);
>>>>> counter2 = ba.if( (-0.691 + (10*log10(gateRelative))) > -70.0, 1, 0);
>>>>> sampleHold2 = ba.countup(ma.SR*300, 1-counter2+reset) <: _, 
>>>>> ba.peakhold(1-reset) :> _;
>>>>> cumulativeAverage2 = (((sampleHold2*_)+gateRelative) / (sampleHold2+1)) ~ 
>>>>> _;
>>>>> integratedLUFS = (-0.691 + (10*log10(cumulativeAverage2)));
>>>>>
>>>>> process = _ <: _, ( integratedLUFS : vbargraph("[0]INTEGRATED 
>>>>> LUFS",-70,0.0)) : attach;
>>>>>
>>>>> ////////////////////////////
>>>>>
>>>>>
>>>>>
>>>>> El 16 jul 2021, a las 9:57, Klaus Scheuermann <
>>>>> kla...@posteo.de
>>>>>> escribió:
>>>>>>
>>>>> Hello Juan Carlos,
>>>>>
>>>>> with great help from the list (thanks!) I could implement (momentary) 
>>>>> lufs metering in my project:
>>>>>
>>>>>
>>>>> https://github.com/trummerschlunk/master_me
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> also thinking about how to do the -70 dB gate and most important the 
>>>>> integrated loudness.
>>>>>
>>>>> Did you give this a thought? I am - once again - a bit lost here.
>>>>> The specs say: (
>>>>>
>>>>> https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1770-3-201208-S!!PDF-E.pdf
>>>>> )
>>>>>
>>>>>
>>>>> gating of 400 ms blocks (overlapping by 75%), where two thresholds are 
>>>>> used: 
>>>>> – the first at –70 LKFS; 
>>>>> – the  second  at  –10  dB  relative  to  the  level  measured  after  
>>>>> application  of  the  first  threshold.
>>>>>
>>>>> I guess, the gating can be done with a sliding window too, right? Or is 
>>>>> it done in the same window we use for measurement?
>>>>>
>>>>> How do I gate a variable in two stages?
>>>>>
>>>>> Thanks, Klaus
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On 10.07.21 18:15, Juan Carlos Blancas wrote:
>>>>>
>>>>>
>>>>> El 10 jul 2021, a las 15:31, Klaus Scheuermann <
>>>>> kla...@posteo.de
>>>>>> escribió:
>>>>>>
>>>>> Hello Juan Carlos,
>>>>>
>>>>>
>>>>> Klaus, I’m using Atom+FaustLive, Max and SC to do the tests, but I get 
>>>>> the same crash as you with faustide/editor.
>>>>>
>>>>>
>>>>> https://www.dropbox.com/s/blwtwao7j317db0/test.mov?dl=0
>>>>>
>>>>> cool, thanks!
>>>>>
>>>>>
>>>>> Btw the reading are aprox but not the same as Youlean nor Insight2 for 
>>>>> instance… 
>>>>>
>>>>> great, that’s promising! 
>>>>>
>>>>>
>>>>> also thinking about how to do the -70 dB gate and most important the 
>>>>> integrated loudness.
>>>>>
>>>>> Yes, I was wondering about that too… Just so you have some context, I 
>>>>> don’t want to replicate an lufs meter, but I want to use lufs it in my 
>>>>> project master_me, which is meant to stabilise audio during streaming 
>>>>> events: 
>>>>> https://github.com/trummerschlunk/master_me
>>>>>
>>>>>
>>>>> For that I would like to be able to adjust the agility of the integrated 
>>>>> loudness. Also the gating should be adjustable.
>>>>>
>>>>>
>>>>> Nice project! definitely would be great to add LUFS meters and kind of a 
>>>>> loudness stabilizer with targets.
>>>>> Best,
>>>>> Juan Carlos
>>>>>
>>>>>
>>>>>
>>>>> On 10. Jul 2021, at 14:47, Juan Carlos Blancas <
>>>>> lav...@gmail.com
>>>>>> wrote:
>>>>>>
>>>>> Klaus, I’m using Atom+FaustLive, Max and SC to do the tests, but I get 
>>>>> the same crash as you with faustide/editor.
>>>>>
>>>>>
>>>>> https://www.dropbox.com/s/blwtwao7j317db0/test.mov?dl=0
>>>>>
>>>>>
>>>>>
>>>>> Btw the reading are aprox but not the same as Youlean nor Insight2 for 
>>>>> instance… 
>>>>> also thinking about how to do the -70 dB gate and most important the 
>>>>> integrated loudness.
>>>>>
>>>>> Cheers,
>>>>> Juan Carlos
>>>>>
>>>>>
>>>>> El 10 jul 2021, a las 12:17, Klaus Scheuermann <
>>>>> kla...@posteo.de
>>>>>> escribió:
>>>>>>
>>>>> Thanks, Juan :)
>>>>>
>>>>> Your code crashes my faustide on firefox and on chromium (both linux).
>>>>> Here is the error message:
>>>>>
>>>>> ASSERT : please report this message and the failing DSP file to Faust
>>>>> developers (file: wasm_instructions.hh, line: 918, version: 2.32.16,
>>>>> options: -lang wasm-ib -es 1 -single -ftz 0)
>>>>>
>>>>> When 'realtime compile' is active, the only way to gain control again is
>>>>> to delete all cookies and cache from the site.
>>>>>
>>>>> I'll try Dario's workaround now ;)
>>>>>
>>>>> Cheers, Klaus
>>>>>
>>>>>
>>>>> On 09.07.21 18:08, Juan Carlos Blancas wrote:
>>>>>
>>>>> Hi Klaus, 
>>>>>
>>>>> For me ms_envelope and rms_envelope functions are not working properly. 
>>>>> I’ve done some test in my Mac Pro with High Sierra, porting without 
>>>>> barograph to Max or Supercollider and I get the strange gate behaviour in 
>>>>> low levels.
>>>>>
>>>>> My workaround at the moment is using ba.slidingMeanp instead of 
>>>>> ms_envelope, but it’s 2x cpu intense, so I guess Dario solution of 1plp 
>>>>> filter would be the best for the mean square stage.
>>>>>
>>>>>
>>>>> 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);
>>>>>
>>>>>
>>>>>
>>>>> Cheers,
>>>>> Juan Carlos
>>>>>
>>>>>
>>>>> // Mono Momentary LUFS meter without gate of Julius, using slidingMeanp 
>>>>> instead of ms_envelope
>>>>>
>>>>> import("stdfaust.lib");
>>>>>
>>>>> A48kHz = ( /* 1.0, */ -1.99004745483398, 0.99007225036621);
>>>>> B48kHz = (1.0, -2.0, 1.0);
>>>>> highpass48kHz = fi.iir(B48kHz,A48kHz);
>>>>> highpass = fi.highpass(2, 40);
>>>>>
>>>>> boostDB = 4;
>>>>> boostFreqHz = 1430;
>>>>> highshelf = fi.high_shelf(boostDB, boostFreqHz);
>>>>> kfilter = highshelf : highpass;
>>>>>
>>>>> MAXN = 262144;
>>>>> Tg = 0.4;
>>>>> Lk = kfilter <: _*_ : ba.slidingMeanp(Tg*ma.SR, MAXN) : ba.linear2db : 
>>>>> *(0.5);
>>>>>
>>>>> process = _ <: attach(_, Lk : hbargraph("[1]Momentary LUFS",-70,0));
>>>>>
>>>>> //
>>>>>
>>>>>
>>>>> El 9 jul 2021, a las 16:55, Klaus Scheuermann <
>>>>> kla...@posteo.de
>>>>>> escribió:
>>>>>>
>>>>> Ha, so I was really on to something ;)
>>>>>
>>>>> Is the bug in the meter or in the envelope?
>>>>> Would you have a workaround for me to get on with the lufs analyser?
>>>>>
>>>>> Thanks, Klaus
>>>>>
>>>>> On 08.07.21 19:19, Julius Smith wrote:
>>>>>
>>>>> 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
>>>>> <
>>>>>
>>>>> sanfilippo.da...@gmail.com <mailto:sanfilippo.da...@gmail.com
>>>>>>> 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 removethe hbargraphaltogether, 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(.999999) <: _, _@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 <http://dariosanfilippo.com
>>>>>
>>>>>  On Thu, 8 Jul 2021 at 00:39, Julius Smith <
>>>>>
>>>>> julius.sm...@gmail.com
>>>>>
>>>>>
>>>>>  <mailto:
>>>>>
>>>>> julius.sm...@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.
>>>>>
>>>>>      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.999999) ... etc.
>>>>>
>>>>>      - Julius
>>>>>
>>>>>      On Wed, Jul 7, 2021 at 12:32 PM Dario Sanfilippo
>>>>>      <
>>>>>
>>>>> sanfilippo.da...@gmail.com <mailto: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 <http://dariosanfilippo.com
>>>>>
>>>>>          On Wed, 7 Jul 2021 at 19:25, Stéphane Letz <
>>>>>
>>>>> l...@grame.fr
>>>>>
>>>>>
>>>>>          <mailto:
>>>>>
>>>>> l...@grame.fr
>>>>>>> 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
>>>>>
>>>>> <
>>>>> julius.sm...@gmail.com <mailto:julius.sm...@gmail.com
>>>>> 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
>>>>>
>>>>> <
>>>>> kla...@posteo.de <mailto:kla...@posteo.de
>>>>>>> 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
>>>>>
>>>>> <
>>>>> 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
>>>>>
>>>>> <
>>>>> kla...@posteo.de <mailto:kla...@posteo.de
>>>>> <mailto:kla...@posteo.de <mailto:kla...@posteo.de
>>>>> wrote:
>>>>>
>>>>>
>>>>>    Cheers Julius,
>>>>>
>>>>>
>>>>>
>>>>>    At least I understood the 'attach' primitive now
>>>>>
>>>>> ;) Thanks.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>    This does not show any meter here...
>>>>>    process(x,y) = x,y <: (_,_), attach(x, (Lk2 :
>>>>>
>>>>> vbargraph("LUFS",-90,0)))
>>>>>
>>>>>    : _,_,!;
>>>>>
>>>>>    But this does for some reason (although the
>>>>>
>>>>> output is 3-channel then):
>>>>>
>>>>> process(x,y) = x,y <: (_,_), attach(x, (Lk2 :
>>>>>
>>>>> vbargraph("LUFS",-90,0)))
>>>>>
>>>>>    : _,_,_;
>>>>>
>>>>>    What does the '!' do?
>>>>>
>>>>>
>>>>>
>>>>>    I still don't quite get the gating topic. In my
>>>>>
>>>>> understanding, the meter
>>>>>
>>>>> should hold the current value if the input
>>>>>
>>>>> signal drops below a
>>>>>
>>>>> threshold. In your version, the meter drops to
>>>>>
>>>>> -infinity when very low
>>>>>
>>>>>    volume content is played.
>>>>>
>>>>>    Which part of your code does the gating?
>>>>>
>>>>>    Many thanks,
>>>>>    Klaus
>>>>>
>>>>>
>>>>>
>>>>>    On 05.07.21 18:06, Julius Smith wrote:
>>>>>
>>>>> Hi Klaus,
>>>>>
>>>>> Yes, I agree the filters are close enough.  I
>>>>>
>>>>> bet that the shelf is
>>>>>
>>>>> exactly correct if we determined the exact
>>>>>
>>>>> transition frequency, and
>>>>>
>>>>> that the Butterworth highpass is close enough
>>>>>
>>>>> to the
>>>>>
>>>>> Bessel-or-whatever
>>>>>
>>>>> that is inexplicably not specified as a filter
>>>>>
>>>>> type, leaving it
>>>>>
>>>>> sample-rate dependent.  I would bet large odds
>>>>>
>>>>> that the differences
>>>>>
>>>>> cannot be reliably detected in listening tests.
>>>>>
>>>>> Yes, I just looked again, and there are
>>>>>
>>>>> "gating blocks" defined,
>>>>>
>>>>> each Tg
>>>>>
>>>>> = 0.4 sec long, so that only ungated blocks
>>>>>
>>>>> are averaged to form a
>>>>>
>>>>> longer term level-estimate.  What I wrote
>>>>>
>>>>> gives a "sliding gating
>>>>>
>>>>> block", which can be lowpass filtered further,
>>>>>
>>>>> and/or gated, etc. 
>>>>>
>>>>> Instead of a gate, I would simply replace 0 by
>>>>>
>>>>> ma.EPSILON so that the
>>>>>
>>>>> log always works (good for avoiding denormals
>>>>>
>>>>> as well).
>>>>>
>>>>>
>>>>> I believe stereo is supposed to be handled
>>>>>
>>>>> like this:
>>>>>
>>>>>
>>>>> Lk2 = _,0,_,0,0 : Lk5;
>>>>> process(x,y) = Lk2(x,y);
>>>>>
>>>>> or
>>>>>
>>>>> Lk2 = Lk(0),Lk(2) :> 10 * log10 : -(0.691);
>>>>>
>>>>> but since the center channel is processed
>>>>>
>>>>> identically to left
>>>>>
>>>>> and right,
>>>>>
>>>>> your solution also works.
>>>>>
>>>>> Bypassing is normal Faust, e.g.,
>>>>>
>>>>> process(x,y) = x,y <: (_,_), attach(x, (Lk2 :
>>>>>
>>>>> vbargraph("LUFS",-90,0)))
>>>>>
>>>>> : _,_,!;
>>>>>
>>>>> Cheers,
>>>>> Julius
>>>>>
>>>>>
>>>>> On Mon, Jul 5, 2021 at 1:56 AM Klaus
>>>>>
>>>>> Scheuermann <
>>>>> kla...@posteo.de <mailto:kla...@posteo.de
>>>>> <mailto:kla...@posteo.de <mailto:kla...@posteo.de
>>>>> <mailto:kla...@posteo.de
>>>>> <mailto:kla...@posteo.de> <mailto:kla...@posteo.de
>>>>>
>>>>>
>>>>> <mailto:
>>>>>
>>>>> kla...@posteo.de
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>
>>>>>
>>>>> I can never resist these things!   Faust
>>>>>
>>>>> makes it too
>>>>>
>>>>> enjoyable :-)
>>>>>
>>>>>
>>>>>   Glad you can't ;)
>>>>>
>>>>>   I understood you approximate the filters
>>>>>
>>>>> with standard faust
>>>>>
>>>>> filters.
>>>>>
>>>>>   That is probably close enough for me :)
>>>>>
>>>>>   I also get the part with the sliding
>>>>>
>>>>> window envelope. If I
>>>>>
>>>>> wanted to
>>>>>
>>>>> make the meter follow slowlier, I would
>>>>>
>>>>> just widen the window
>>>>>
>>>>> with Tg.
>>>>>
>>>>>
>>>>>   The 'gating' part I don't understand for
>>>>>
>>>>> lack of mathematical
>>>>>
>>>>> knowledge,
>>>>>
>>>>> but I suppose it is meant differently.
>>>>>
>>>>> When the input signal
>>>>>
>>>>> falls below
>>>>>
>>>>> the gate threshold, the meter should stay
>>>>>
>>>>> at the current
>>>>>
>>>>> value, not drop
>>>>>
>>>>> to -infinity, right? This is so 'silent'
>>>>>
>>>>> parts are not taken into
>>>>>
>>>>>   account.
>>>>>
>>>>>   If I wanted to make a stereo version it
>>>>>
>>>>> would be something like
>>>>>
>>>>>   this, right?
>>>>>
>>>>>   Lk2 = par(i,2, Lk(i)) :> 10 * log10 :
>>>>>
>>>>> -(0.691);
>>>>>
>>>>>   process = _,_ : Lk2 : vbargraph("LUFS",-90,0);
>>>>>
>>>>>   Probably very easy, but how do I attach
>>>>>
>>>>> this to a stereo
>>>>>
>>>>> signal (passing
>>>>>
>>>>>   through the stereo signal)?
>>>>>
>>>>>   Thanks again!
>>>>>   Klaus
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> I made a pass, but there is a small
>>>>>
>>>>> scaling error.  I think
>>>>>
>>>>> it can be
>>>>>
>>>>> fixed by reducing boostFreqHz until the
>>>>>
>>>>> sine_test is nailed.
>>>>>
>>>>> The highpass is close (and not a source
>>>>>
>>>>> of the scale error),
>>>>>
>>>>> but I'm
>>>>>
>>>>> using Butterworth instead of whatever
>>>>>
>>>>> they used.
>>>>>
>>>>> I glossed over the discussion of
>>>>>
>>>>> "gating" in the spec, and
>>>>>
>>>>> may have
>>>>>
>>>>> missed something important there, but
>>>>> I simply tried to make a sliding
>>>>>
>>>>> rectangular window, instead
>>>>>
>>>>> of 75%
>>>>>
>>>>> overlap, etc.
>>>>>
>>>>> If useful, let me know and I'll propose
>>>>>
>>>>> it for analyzers.lib!
>>>>>
>>>>>
>>>>> Cheers,
>>>>> Julius
>>>>>
>>>>> import("stdfaust.lib");
>>>>>
>>>>> // Highpass:
>>>>> // At 48 kHz, this is the right highpass
>>>>>
>>>>> filter (maybe a
>>>>>
>>>>> Bessel or
>>>>>
>>>>> Thiran filter?):
>>>>> A48kHz = ( /* 1.0, */ -1.99004745483398,
>>>>>
>>>>> 0.99007225036621);
>>>>>
>>>>> B48kHz = (1.0, -2.0, 1.0);
>>>>> highpass48kHz = fi.iir(B48kHz,A48kHz);
>>>>> highpass = fi.highpass(2, 40); //
>>>>>
>>>>> Butterworth highpass:
>>>>>
>>>>> roll-off is a
>>>>>
>>>>> little too sharp
>>>>>
>>>>> // High Shelf:
>>>>> boostDB = 4;
>>>>> boostFreqHz = 1430; // a little too high
>>>>>
>>>>> - they should give
>>>>>
>>>>> us this!
>>>>>
>>>>> highshelf = fi.high_shelf(boostDB,
>>>>>
>>>>> boostFreqHz); // Looks
>>>>>
>>>>> very close,
>>>>>
>>>>> but 1 kHz gain has to be nailed
>>>>>
>>>>> kfilter = highshelf : highpass;
>>>>>
>>>>> // Power sum:
>>>>> Tg = 0.4; // spec calls for 75% overlap
>>>>>
>>>>> of successive
>>>>>
>>>>> rectangular
>>>>>
>>>>> windows - we're overlapping MUCH more
>>>>>
>>>>> (sliding window)
>>>>>
>>>>> zi = an.ms_envelope_rect(Tg); // mean
>>>>>
>>>>> square: average power =
>>>>>
>>>>> energy/Tg
>>>>>
>>>>> = integral of squared signal / Tg
>>>>>
>>>>> // Gain vector Gv = (GL,GR,GC,GLs,GRs):
>>>>> N = 5;
>>>>> Gv = (1, 1, 1, 1.41, 1.41); // left
>>>>>
>>>>> GL(-30deg), right GR
>>>>>
>>>>> (30), center
>>>>>
>>>>> GC(0), left surround GLs(-110), right
>>>>>
>>>>> surr. GRs(110)
>>>>>
>>>>> G(i) = *(ba.take(i+1,Gv));
>>>>> Lk(i) = kfilter : zi : G(i); // one
>>>>>
>>>>> channel, before summing
>>>>>
>>>>> and before
>>>>>
>>>>> taking dB and offsetting
>>>>> LkDB(i) = Lk(i) : 10 * log10 : -(0.691);
>>>>>
>>>>> // Use this for a mono
>>>>>
>>>>> input signal
>>>>>
>>>>>
>>>>> // Five-channel surround input:
>>>>> Lk5 = par(i,5,Lk(i)) :> 10 * log10 :
>>>>>
>>>>> -(0.691);
>>>>>
>>>>>
>>>>> // sine_test = os.oscrs(1000); // should
>>>>>
>>>>> give –3.01 LKFS, with
>>>>>
>>>>> GL=GR=GC=1 (0dB) and GLs=GRs=1.41 (~1.5 dB)
>>>>> sine_test = os.osc(1000);
>>>>>
>>>>> process = sine_test : LkDB(0); // should
>>>>>
>>>>> read -3.01 LKFS -
>>>>>
>>>>> high-shelf
>>>>>
>>>>> gain at 1 kHz is critical
>>>>> // process = 0,sine_test,0,0,0 : Lk5; //
>>>>>
>>>>> should read -3.01
>>>>>
>>>>> LKFS for
>>>>>
>>>>> left, center, and right
>>>>> // Highpass test: process = 1-1' <:
>>>>>
>>>>> highpass, highpass48kHz;
>>>>>
>>>>> // fft in
>>>>>
>>>>> Octave
>>>>> // High shelf test: process = 1-1' :
>>>>>
>>>>> highshelf; // fft in Octave
>>>>>
>>>>>
>>>>> On Sat, Jul 3, 2021 at 1:08 AM Klaus
>>>>>
>>>>> Scheuermann
>>>>>
>>>>> <
>>>>> kla...@posteo.de <mailto:kla...@posteo.de
>>>>>
>>>>> -- 
>>>>> Sent from my Android device with K-9 Mail. Please excuse my brevity.
>>>>> _______________________________________________
>>>>> 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
>>>>
>>>> _______________________________________________
>>>> 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
>> _______________________________________________
>> 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