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