> I'm not sure I understand what you mean by allocating a delay line for the sliding mean, but I'll look into it.
Here's an example implementation in Faust. The "small test" allocates a length 8 delay line. The full test takes too long to compile, but you can see the pattern, so it's easy to just write it. import("stdfaust.lib"); // Small test: durSamples = 8; DUR_SAMPLES_MAX = durSamples*2; // What we really need (but takes a LONG time to compile): // DUR_SAMPLES_MAX = 2^16; // durSamples = int(0.5 + 0.4 * ma.SR); sliding_mean(durSamples) = _ <: par(i,DUR_SAMPLES_MAX,ba.if(i<durSamples,@(i),0)) :> /(durSamples); process = sliding_mean(durSamples); On Sat, Jul 10, 2021 at 1:12 AM Dario Sanfilippo <sanfilippo.da...@gmail.com> wrote: > Dear Julius, thanks for putting it nicely. :) > > I'm not sure I understand what you mean by allocating a delay line for the > sliding mean, but I'll look into it. > > A quick improvement to the slidingMean function could be to put the > integrator after the difference. With a sliding window of .4 sec at 48 kHz, > we should have about 60 dBs of dynamic range when feeding a full-amp > constant. It should be even better with close-to-zero-mean signals. > > import("stdfaust.lib"); > slidingSum(n) = _ <: _, _@int(max(0,n)) : - : fi.pole(1); > slidingMean(n) = slidingSum(n)/rint(n); > t=.4; > process = ba.if(ba.time < ma.SR * 1, 1.0, .001) <: slidingMean(t*ma.SR) , > ba.slidingMean(t*ma.SR) : ba.linear2db , ba.linear2db; > > Ciao, > Dr Dario Sanfilippo > http://dariosanfilippo.com > > > On Sat, 10 Jul 2021 at 00:27, Julius Smith <julius.sm...@gmail.com> wrote: > >> Hi Dario, >> >> Ok, I see what you're after now. (I was considering only the VU meter >> display issue up to now.) >> >> There's only 23 bits of mantissa in 32-bit floating point, and your test >> counts up to ~100k, which soaks up about 17 bits, and then you hit it with >> ~1/1024, or 2^(-10), which is then a dynamic range swing of 27 bits. We >> can't add numbers separated by 27 bits of dynamic level using a mantissa >> (or integer) smaller than 27 bits. Yes, double precision will fix that >> (52-bit mantissas), but even TIIR methods can't solve this problem. When >> adding x and y, the wordlength must be on the order of at least >> |log2(|x|/|y|)|. >> >> The situation is not so dire with a noise input, since it should be zero >> mean (and if not, a dcblocker will fix it). However, the variance of >> integrated squared white noise does grow linearly, so TIIR methods are >> needed for anything long term, and double-precision allows the TIIR resets >> to be much farther separated, and maybe not even needed in a given >> application. >> >> Note, by the way (Hey Klaus!), we can simply allocate a 0.4 second delay >> line for the sliding mean and be done with all this recursive-filter >> dynamic range management. It can be a pain, but it also can be managed. >> That said, 0.4 seconds at 96 kHz is around 15 bits worth >> (log2(0.4*96000)=15.2), so single-precision seems to me like enough for a >> simple level meter (e.g., having a 3-digit display), given a TIIR reset >> every 0.4 seconds. Since this works out so neatly, I wouldn't be surprised >> if 0.4 seconds was chosen for the gated-measurement duration for that >> reason. >> >> Cheers, >> Julius >> >> >> On Fri, Jul 9, 2021 at 1:54 PM Dario Sanfilippo < >> sanfilippo.da...@gmail.com> wrote: >> >>> Thanks, Julius. >>> >>> So it appears that the issue I was referring to is in that architecture >>> too. >>> >>> To isolate the problem with ba.slidingMean, we can see that we also get >>> 0 when transitioning from a constant input of 1 to .001 (see code below). >>> Double-precision solves the issue. Perhaps we could advise using DP for >>> this function and the others involving it. >>> >>> Ciao, >>> Dario >>> >>> import("stdfaust.lib"); >>> lp1p(cf, x) = fi.pole(b, x * (1 - b)) >>> with { >>> b = exp(-2 * ma.PI * cf / ma.SR); >>> }; >>> sig = ba.if(ba.time > ma.SR * 2, .001, 1.0); >>> t = .4; >>> process = sig <: ba.slidingMean(t * ma.SR) , lp1p(1.0 / t) , ba.time; >>> >>> On Fri, 9 Jul 2021 at 22:40, Julius Smith <julius.sm...@gmail.com> >>> wrote: >>> >>>> I get the zero but not the other: >>>> >>>> octave:2> format long >>>> octave:3> faustout(115200,:) >>>> ans = >>>> >>>> 0 -2.738748490000000e-02 5.555857930000000e-05 >>>> >>>> >>>> On Fri, Jul 9, 2021 at 1:03 PM Dario Sanfilippo < >>>> sanfilippo.da...@gmail.com> wrote: >>>> >>>>> Thanks, Julius. >>>>> >>>>> I don't have Octave installed, and I can't see it myself, sorry; if >>>>> you can inspect the generated values, can you also see if at sample >>>>> #115200 >>>>> (48 kHz SR) you get 0 for ms_rec, and, 0.000658808684 for the lowpass? >>>>> >>>>> Yes, I might have done something wrong, but the leaky integrator >>>>> doesn't work well. >>>>> >>>>> Ciao, >>>>> Dario >>>>> >>>>> On Fri, 9 Jul 2021 at 21:49, Julius Smith <julius.sm...@gmail.com> >>>>> wrote: >>>>> >>>>>> Here is a longer run that shows Dario's latest test more completely. >>>>>> I don't think zi_leaky looks right at the end, but the other two look >>>>>> reasonable to me. >>>>>> >>>>>> Here is the Octave magic for the plot: >>>>>> >>>>>> plot(faustout,'linewidth',2); >>>>>> legend('zi','zi\_leaky','zi\_lp','location','southeast'); >>>>>> grid; >>>>>> >>>>>> I had to edit faust2octave to change the process duration, it's >>>>>> hardwired. Length option needed! (Right now no options can take an >>>>>> argument.) >>>>>> >>>>>> Cheers, >>>>>> - Julius >>>>>> >>>>>> On Fri, Jul 9, 2021 at 12:01 PM Julius Smith <julius.sm...@gmail.com> >>>>>> wrote: >>>>>> >>>>>>> Hi Dario, >>>>>>> >>>>>>> I tried your latest test and it looks plausible in faust2octave (see >>>>>>> plot attached). >>>>>>> >>>>>>> TIIR filters present a nice, juicy Faust puzzle :-) >>>>>>> I thought about a TIIR sliding average, but haven't implemented >>>>>>> anything yet. >>>>>>> You basically want to switch between two moving-average filters, >>>>>>> clearing the state of the unused one, and bringing it back to steady >>>>>>> state >>>>>>> before switching it back in. >>>>>>> In the case of an.ms_envelope_rect, the switching period can be >>>>>>> anything greater than the rectangular-window length (which is the "warm >>>>>>> up >>>>>>> time" of the moving-average filter). >>>>>>> >>>>>>> Cheers, >>>>>>> - Julius >>>>>>> >>>>>>> On Fri, Jul 9, 2021 at 10:49 AM Dario Sanfilippo < >>>>>>> sanfilippo.da...@gmail.com> wrote: >>>>>>> >>>>>>>> Dear Julius, I just pulled and installed Faust 2.33.0. >>>>>>>> >>>>>>>> I'm running the test below on caqt and csvplot and I see the same >>>>>>>> problem: when large inputs are fed in an.ms_envelope_rect, small >>>>>>>> inputs are truncated to zero afterwards. >>>>>>>> >>>>>>>> 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 * ba.if(ba.time > ma.SR * 2, .01, 1.0); >>>>>>>> process = sig <: zi , zi_leaky , zi_lp , ba.time; >>>>>>>> >>>>>>>> I'll look into TIIR filters or have you already implemented those >>>>>>>> in Faust? >>>>>>>> >>>>>>>> Ciao, >>>>>>>> Dr Dario Sanfilippo >>>>>>>> http://dariosanfilippo.com >>>>>>>> >>>>>>>> >>>>>>>> On Thu, 8 Jul 2021 at 19:19, Julius Smith <julius.sm...@gmail.com> >>>>>>>> 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> wrote: >>>>>>>>> >>>>>>>>>> Hi, Julius. >>>>>>>>>> >>>>>>>>>> I must be missing something, but I couldn't see the behaviour >>>>>>>>>> that you described, that is, the gating behaviour happening only for >>>>>>>>>> the >>>>>>>>>> display and not for the output. >>>>>>>>>> >>>>>>>>>> If a remove the hbargraph altogether, I can still see the >>>>>>>>>> strange behaviour. Just so we're all on the same page, the strange >>>>>>>>>> behaviour we're referring to is the fact that, after going back to >>>>>>>>>> low >>>>>>>>>> input gains, the displayed levels are -inf instead of some low, >>>>>>>>>> quantifiable ones, right? >>>>>>>>>> >>>>>>>>>> Using a leaky integrator makes the calculations rather >>>>>>>>>> inaccurate. I'd say that, if one needs to use single-precision, >>>>>>>>>> averaging >>>>>>>>>> with a one-pole lowpass would be best: >>>>>>>>>> >>>>>>>>>> import("stdfaust.lib"); >>>>>>>>>> zi = an.ms_envelope_rect(Tg); >>>>>>>>>> slidingSum(n) = fi.pole(.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 >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On Thu, 8 Jul 2021 at 00:39, Julius Smith <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> wrote: >>>>>>>>>>> >>>>>>>>>>>> I think that the problem is in an.ms_envelope_rect, >>>>>>>>>>>> particularly the fact that it has a non-leaky integrator. I assume >>>>>>>>>>>> that >>>>>>>>>>>> when large values recirculate in the integrator, the smaller ones, >>>>>>>>>>>> after >>>>>>>>>>>> pushing the gain down, are truncated to 0 due to single-precision. >>>>>>>>>>>> As a >>>>>>>>>>>> matter of fact, compiling the code in double precision looks fine >>>>>>>>>>>> here. >>>>>>>>>>>> >>>>>>>>>>>> Ciao, >>>>>>>>>>>> Dr Dario Sanfilippo >>>>>>>>>>>> http://dariosanfilippo.com >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On Wed, 7 Jul 2021 at 19:25, Stéphane Letz <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> 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> wrote: >>>>>>>>>>>>> > Hi all, >>>>>>>>>>>>> > I did some testing and >>>>>>>>>>>>> > >>>>>>>>>>>>> > an.ms_envelope_rect() >>>>>>>>>>>>> > >>>>>>>>>>>>> > seems to show some strange behaviour (at least to me). Here >>>>>>>>>>>>> is a video >>>>>>>>>>>>> > of the test: >>>>>>>>>>>>> > https://cloud.4ohm.de/s/64caEPBqxXeRMt5 >>>>>>>>>>>>> > >>>>>>>>>>>>> > The audio is white noise and the testing code is: >>>>>>>>>>>>> > >>>>>>>>>>>>> > import("stdfaust.lib"); >>>>>>>>>>>>> > Tg = 0.4; >>>>>>>>>>>>> > zi = an.ms_envelope_rect(Tg); >>>>>>>>>>>>> > process = _ : zi : ba.linear2db : hbargraph("test",-95,0); >>>>>>>>>>>>> > >>>>>>>>>>>>> > Could you please verify? >>>>>>>>>>>>> > >>>>>>>>>>>>> > Thanks, Klaus >>>>>>>>>>>>> > >>>>>>>>>>>>> > >>>>>>>>>>>>> > >>>>>>>>>>>>> > On 05.07.21 20:16, Julius Smith wrote: >>>>>>>>>>>>> > > Hmmm, '!' means "block the signal", but attach should save >>>>>>>>>>>>> the bargraph >>>>>>>>>>>>> > > from being optimized away as a result. Maybe I >>>>>>>>>>>>> misremembered the >>>>>>>>>>>>> > > argument order to attach? While it's very simple in >>>>>>>>>>>>> concept, it can be >>>>>>>>>>>>> > > confusing in practice. >>>>>>>>>>>>> > > >>>>>>>>>>>>> > > I chose not to have a gate at all, but you can grab one >>>>>>>>>>>>> from >>>>>>>>>>>>> > > misceffects.lib if you like. Low volume should not give >>>>>>>>>>>>> -infinity, >>>>>>>>>>>>> > > that's a bug, but zero should, and zero should become MIN >>>>>>>>>>>>> as I mentioned >>>>>>>>>>>>> > > so -infinity should never happen. >>>>>>>>>>>>> > > >>>>>>>>>>>>> > > Cheers, >>>>>>>>>>>>> > > Julius >>>>>>>>>>>>> > > >>>>>>>>>>>>> > > >>>>>>>>>>>>> > > On Mon, Jul 5, 2021 at 10:39 AM Klaus Scheuermann < >>>>>>>>>>>>> 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>>> >>>>>>>>>>>>> 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> >>>>>>>>>>>>> > > > <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: >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > Hello everyone :) >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > Would someone be up for helping me >>>>>>>>>>>>> implement an LUFS >>>>>>>>>>>>> > > loudness >>>>>>>>>>>>> > > > analyser >>>>>>>>>>>>> > > > > in faust? >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > Or has someone done it already? >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > LUFS (aka LKFS) is becoming more and more >>>>>>>>>>>>> the standard for >>>>>>>>>>>>> > > > loudness >>>>>>>>>>>>> > > > > measurement in the audio industry. >>>>>>>>>>>>> Youtube, Spotify and >>>>>>>>>>>>> > > broadcast >>>>>>>>>>>>> > > > > stations use the concept to normalize >>>>>>>>>>>>> loudness. A very >>>>>>>>>>>>> > > > positive side >>>>>>>>>>>>> > > > > effect is, that loudness-wars are >>>>>>>>>>>>> basically over. >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > I looked into it, but my programming >>>>>>>>>>>>> skills clearly >>>>>>>>>>>>> > > don't match >>>>>>>>>>>>> > > > > the level for implementing this. >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > Here is some resource about the topic: >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > https://en.wikipedia.org/wiki/LKFS >>>>>>>>>>>>> > > <https://en.wikipedia.org/wiki/LKFS> >>>>>>>>>>>>> > > > <https://en.wikipedia.org/wiki/LKFS >>>>>>>>>>>>> > > <https://en.wikipedia.org/wiki/LKFS>> >>>>>>>>>>>>> > > > <https://en.wikipedia.org/wiki/LKFS >>>>>>>>>>>>> > > <https://en.wikipedia.org/wiki/LKFS> >>>>>>>>>>>>> > > > <https://en.wikipedia.org/wiki/LKFS >>>>>>>>>>>>> > > <https://en.wikipedia.org/wiki/LKFS>>> >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > Specifications (in Annex 1): >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > >>>>>>>>>>>>> > > >>>>>>>>>>>>> https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1770-3-201208-S!!PDF-E.pdf >>>>>>>>>>>>> > > < >>>>>>>>>>>>> https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1770-3-201208-S!!PDF-E.pdf >>>>>>>>>>>>> > >>>>>>>>>>>>> > > > >>>>>>>>>>>>> > > < >>>>>>>>>>>>> https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1770-3-201208-S!!PDF-E.pdf >>>>>>>>>>>>> > > < >>>>>>>>>>>>> https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1770-3-201208-S!!PDF-E.pdf >>>>>>>>>>>>> >> >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > >>>>>>>>>>>>> > > < >>>>>>>>>>>>> https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1770-3-201208-S!!PDF-E.pdf >>>>>>>>>>>>> > > < >>>>>>>>>>>>> https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1770-3-201208-S!!PDF-E.pdf >>>>>>>>>>>>> > >>>>>>>>>>>>> > > > >>>>>>>>>>>>> > > < >>>>>>>>>>>>> https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1770-3-201208-S!!PDF-E.pdf >>>>>>>>>>>>> > > < >>>>>>>>>>>>> https://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1770-3-201208-S!!PDF-E.pdf >>>>>>>>>>>>> >>> >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > An implementation by 'klangfreund' in JUCE >>>>>>>>>>>>> / C: >>>>>>>>>>>>> > > > > https://github.com/klangfreund/LUFSMeter >>>>>>>>>>>>> > > <https://github.com/klangfreund/LUFSMeter> >>>>>>>>>>>>> > > > <https://github.com/klangfreund/LUFSMeter >>>>>>>>>>>>> > > <https://github.com/klangfreund/LUFSMeter>> >>>>>>>>>>>>> > > > > <https://github.com/klangfreund/LUFSMeter >>>>>>>>>>>>> > > <https://github.com/klangfreund/LUFSMeter> >>>>>>>>>>>>> > > > <https://github.com/klangfreund/LUFSMeter >>>>>>>>>>>>> > > <https://github.com/klangfreund/LUFSMeter>>> >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > There is also a free LUFS Meter in JS / >>>>>>>>>>>>> Reaper by >>>>>>>>>>>>> > > Geraint Luff. >>>>>>>>>>>>> > > > > (The code can be seen in reaper, but I >>>>>>>>>>>>> don't know if I >>>>>>>>>>>>> > > should >>>>>>>>>>>>> > > > paste it >>>>>>>>>>>>> > > > > here.) >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > Please let me know if you are up for it! >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > Take care, >>>>>>>>>>>>> > > > > Klaus >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> _______________________________________________ >>>>>>>>>>>>> > > > > Faudiostream-users mailing list >>>>>>>>>>>>> > > > > Faudiostream-users@lists.sourceforge.net >>>>>>>>>>>>> > > <mailto:Faudiostream-users@lists.sourceforge.net> >>>>>>>>>>>>> > > > <mailto:Faudiostream-users@lists.sourceforge.net >>>>>>>>>>>>> > > <mailto:Faudiostream-users@lists.sourceforge.net>> >>>>>>>>>>>>> > > > > <mailto: >>>>>>>>>>>>> Faudiostream-users@lists.sourceforge.net >>>>>>>>>>>>> > > <mailto:Faudiostream-users@lists.sourceforge.net> >>>>>>>>>>>>> > > > <mailto:Faudiostream-users@lists.sourceforge.net >>>>>>>>>>>>> > > <mailto:Faudiostream-users@lists.sourceforge.net>>> >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > >>>>>>>>>>>>> > > >>>>>>>>>>>>> https://lists.sourceforge.net/lists/listinfo/faudiostream-users >>>>>>>>>>>>> > > < >>>>>>>>>>>>> https://lists.sourceforge.net/lists/listinfo/faudiostream-users >>>>>>>>>>>>> > >>>>>>>>>>>>> > > > >>>>>>>>>>>>> > > < >>>>>>>>>>>>> https://lists.sourceforge.net/lists/listinfo/faudiostream-users >>>>>>>>>>>>> > > < >>>>>>>>>>>>> https://lists.sourceforge.net/lists/listinfo/faudiostream-users >>>>>>>>>>>>> >> >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > >>>>>>>>>>>>> > > < >>>>>>>>>>>>> https://lists.sourceforge.net/lists/listinfo/faudiostream-users >>>>>>>>>>>>> > > < >>>>>>>>>>>>> https://lists.sourceforge.net/lists/listinfo/faudiostream-users >>>>>>>>>>>>> > >>>>>>>>>>>>> > > > >>>>>>>>>>>>> > > < >>>>>>>>>>>>> https://lists.sourceforge.net/lists/listinfo/faudiostream-users >>>>>>>>>>>>> > > < >>>>>>>>>>>>> https://lists.sourceforge.net/lists/listinfo/faudiostream-users >>>>>>>>>>>>> >>> >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > >>>>>>>>>>>>> > > > > -- >>>>>>>>>>>>> > > > > "Anybody who knows all about nothing knows >>>>>>>>>>>>> everything" -- >>>>>>>>>>>>> > > Leonard >>>>>>>>>>>>> > > > Susskind >>>>>>>>>>>>> > > > >>>>>>>>>>>>> > > > >>>>>>>>>>>>> > > > >>>>>>>>>>>>> > > > -- >>>>>>>>>>>>> > > > "Anybody who knows all about nothing knows >>>>>>>>>>>>> everything" -- Leonard >>>>>>>>>>>>> > > Susskind >>>>>>>>>>>>> > > >>>>>>>>>>>>> > > >>>>>>>>>>>>> > > >>>>>>>>>>>>> > > -- >>>>>>>>>>>>> > > "Anybody who knows all about nothing knows everything" -- >>>>>>>>>>>>> Leonard Susskind >>>>>>>>>>>>> > >>>>>>>>>>>>> > >>>>>>>>>>>>> > -- >>>>>>>>>>>>> > "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 >>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> -- >>>>>>>>>>> "Anybody who knows all about nothing knows everything" -- >>>>>>>>>>> Leonard Susskind >>>>>>>>>>> >>>>>>>>>> >>>>>>>>> >>>>>>>>> -- >>>>>>>>> "Anybody who knows all about nothing knows everything" -- Leonard >>>>>>>>> Susskind >>>>>>>>> >>>>>>>> >>>>>>> >>>>>>> -- >>>>>>> "Anybody who knows all about nothing knows everything" -- Leonard >>>>>>> Susskind >>>>>>> >>>>>> >>>>>> >>>>>> -- >>>>>> "Anybody who knows all about nothing knows everything" -- Leonard >>>>>> Susskind >>>>>> >>>>> >>>> >>>> -- >>>> "Anybody who knows all about nothing knows everything" -- Leonard >>>> Susskind >>>> >>> >> >> -- >> "Anybody who knows all about nothing knows everything" -- Leonard Susskind >> > -- "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