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