Works like a charm, thanks!! Again, I learned a lot. My new test-file now includes audio for mono-invert, stereo-invert, mono-half-left-invert, mono-half-right-invert: https://cloud.4ohm.de/s/bsbAA4Jk3NBPLRD
I included cases for corr = -1 and corr between -1 and 0. I also added volume compensation for corr = 1 and corr = -1. And hey, it works! ;) I would be happy if you find a minute to review. (and maybe improve) (or comment on clumsiness) ;) Comments / todo: - On the way, I lost is fading between the cases. Probably doable with smoo'ing all corr_ cases? - I guess volume compensation could be improved by checking the panning when corr = 1 or corr = -1. but for now I am happy. Klaus import("stdfaust.lib"); avg(t,x)= fi.pole(p,(1- p)* x)// 1-pole lowpass as average with{ p= exp((((-2.0* ma.PI)/ t)/ ma.SR)); }; var(t,x)= avg(t,(x- avg(t,x))^ 2);// variance sd(t,x)= sqrt(var(t,x));// standard deviation cov(t,x1,x2)= avg(t,(x1- avg(t,x1))* (x2- avg(t,x2)));// covariance corr(t,x1,x2)= cov(t,x1,x2)/ max(ma.ma.EPSILON,(sd(t,x1)* sd(t,x2)));// correlation t= .1;// averaging period in seconds correlate_meter(x,y)= x,y<:x,attach(y,(corr(t):hbargraph("corr",-1,1))):_,_; correlate_correct(t,l,r)= out_pos1,out_neg1,out_0,out_pos,out_neg:>_,_with{ th=.001; corr_pos1= avg(t,(corr(t,l,r)>(1-th))); corr_neg1= avg(t,corr(t,l,r)<(-1+th)); corr_0= avg(t,((corr(t,l,r)<th)& (corr(t,l,r)>(0-th)))); corr_pos= avg(t,((corr(t,l,r)>(0+th))& (corr(t,l,r)<(1-th)))); corr_neg= avg(t,((corr(t,l,r)>(-1+th))& (corr(t,l,r)<(0-th)))); out_pos1= ((l* corr_pos1+ r* corr_pos1)/2),((l* corr_pos1+ r* corr_pos1)/2); out_neg1= ((l* corr_neg1+ (-r)* corr_neg1)/2),((l* corr_neg1+ (-r)* corr_neg1)/2); out_0= (l* corr_0+ r* corr_0),(l* corr_0+ r* corr_0); out_pos= l* corr_pos,r* corr_pos; out_neg= l* corr_neg,(0-(r* corr_neg)); }; process= _,_:correlate_meter:ba.bypass2(hslider("bypass",0,0,1,1),correlate_correct(t)); On 09.08.21 18:26, Dario Sanfilippo wrote: > Hi, Klaus. > > From the top of my head, maybe something like this: > > import("stdfaust.lib"); > avg(t, x) = fi.pole(p, (1 - p) * x) // 1-pole lowpass as average > with { > p = exp((((-2.0 * ma.PI) / t) / ma.SR)); > }; > var(t, x) = avg(t, (x - avg(t, x)) ^ 2); // variance > sd(t, x) = sqrt(var(t, x)); // standard deviation > cov(t, x1, x2) = avg(t, (x1 - avg(t, x1)) * (x2 - avg(t, x2))); // > covariance > corr(t, x1, x2) = cov(t, x1, x2) / max(ma.ma.EPSILON, (sd(t, x1) * > sd(t, x2))); // correlation > t = .1; // averaging period in seconds > correlate_meter(x,y) = x,y <: x , attach(y, (corr(t) : > hbargraph("corr",-1,1))) : _,_; > correlate_correct(t,l,r) = (l + r) * mSmoo + l * stSmoo , (l + r) * > mSmoo + r * stSmoo > with { > th = .001; > isMono = (corr(t,l,r) > (1 - th)) | ((corr(t,l,r) < th) & ((avg(t, l * > l) < th) | ((avg(t, r * r) < th)))); > mSmoo = avg(t, isMono); > stSmoo = 1.0 - mSmoo; > }; > process = _,_ : correlate_meter : correlate_correct(t); > > I think that several non-mono cases can result in a correlation that > is close to zero so I'd add another condition to check if either of > the two channels is really quiet. > > Ciao, > Dr Dario Sanfilippo > http://dariosanfilippo.com <http://dariosanfilippo.com> > > > On Mon, 9 Aug 2021 at 09:44, Klaus Scheuermann <kla...@posteo.de > <mailto:kla...@posteo.de>> wrote: > > Dear Julius, dear Dario, > > thanks - again ! > > @Julius: > > ba.if(1>corr(t,l,r)>0,l,(l+r)) > > was my clumsy way of saying 'if corr is smaller than 1 AND greater > than 0'. Or if you turn it around 'if corr ==0 OR corr ==1'. What > would be the most elegant way to do this in faust? > You are right about the L == -R case... I did not look into > out-of-phase cases yet. Probably then the condition should be 'if > corr nears -1 OR 0 OR 1', right? > > @Dario, the code works very nicely and the smoothing sounds > delicious ;) > By explaining my clumsy ba.if statement, you will understand, that > I'd like mono-left and mono-right (which result in corr=0) to be > centered, too. If corr nears 0 or 1, the result should be in the > center. Same question: how to do an elegant OR condition? > > Another thing I was thinking about is, if it makes more sense to > convert the stereo signal to M-S and regulate the S channel for > mono or stereo. But it's probably the same result as smoothing > between l+r,l+r and l,r. > > Cheers, > Klaus > > On 09.08.21 00:56, Dario Sanfilippo wrote: >> Hi, Klaus; nice to hear from you, Julius. :) >> >> As Julius points out, I also think that you'd need less demanding >> thresholds: even for identical channels, the average using a >> one-pole lp will oscillate and it might not be reliable if >> checking against the corner case. >> >> I'd go with something like this, but Julius also has a point >> about phase-inverted mono signals. Also, you may want to >> normalise when you sum L and R. It was necessary to guard against >> division by 0 too. I've included a smoother to avoid clicks when >> switching. >> >> I've tested that with your audio example and it's all mono >> except mono-left, mono-right, and stereo. Is that correct? >> >> import("stdfaust.lib"); >> avg(t, x) = fi.pole(p, (1 - p) * x) // 1-pole lowpass as average >> with { >> p = exp((((-2.0 * ma.PI) / t) / ma.SR)); >> }; >> var(t, x) = avg(t, (x - avg(t, x)) ^ 2); // variance >> sd(t, x) = sqrt(var(t, x)); // standard deviation >> cov(t, x1, x2) = avg(t, (x1 - avg(t, x1)) * (x2 - avg(t, x2))); >> // covariance >> corr(t, x1, x2) = cov(t, x1, x2) / max(ma.ma.EPSILON, (sd(t, x1) >> * sd(t, x2))); // correlation >> t = .5; // averaging period in seconds >> correlate_meter(x,y) = x,y <: x , attach(y, (corr(t) : >> hbargraph("corr",-1,1))) : _,_; >> correlate_correct(t,l,r) = (l + r) * mSmoo + l * stSmoo ,(l + r) >> * mSmoo + r * stSmoo >> with { >> isMono = corr(t,l,r) > .999; >> mSmoo = avg(.05, isMono); >> stSmoo = 1.0 - mSmoo; >> }; >> process = _,_ : correlate_meter : correlate_correct(t); >> >> Ciao, >> Dr Dario Sanfilippo >> http://dariosanfilippo.com <http://dariosanfilippo.com> >> >> >> On Mon, 9 Aug 2021 at 00:25, Julius Smith <julius.sm...@gmail.com >> <mailto:julius.sm...@gmail.com>> wrote: >> >> And of course I mean "cross-correlation coefficient" >> >> On Sun, Aug 8, 2021 at 3:22 PM Julius Smith >> <julius.sm...@gmail.com <mailto:julius.sm...@gmail.com>> wrote: >> >> Hi Klaus, >> >> I am late to this (just read some of the thread with >> interest), and I have a question: what do you mean by "1 >> > corr(t,l,r) > 0" ? It appears to be "parsed" left to >> right, so that the 2nd ">" only sees "1>0" most (all?) of >> the time, which is always true (1) of course (so no >> "else" activated). Maybe you want something like >> "abs(corr(t,l,r)) > 0.95" ? (i.e., 95% correlation >> deemed to be "panned mono"). I'm taking the absolute >> value because I assume you don't care if the left channel >> is merely the negative of the right (unless that's an >> accepted cheezy "stereoizer" of sorts). >> >> FYI, this is what we call a time-domain "normalized >> cross-correlation" or "correlation coefficient" >> measurement (official buzzwords) >> >> Cheers, >> Julius >> >> >> On Sun, Aug 8, 2021 at 10:07 AM Klaus Scheuermann >> <kla...@posteo.de <mailto:kla...@posteo.de>> wrote: >> >> Dear Dario, >> >> cool, your corr function gives me the desired >> results. At least when feeding it to a meter. >> >> Here is my test audio which contains vocals in >> mono-mid, mono-left, mono-right, mono-half-left, >> mono-half-right, stereo: >> https://cloud.4ohm.de/s/y9oZzqFGyrZT5ej >> <https://cloud.4ohm.de/s/y9oZzqFGyrZT5ej> >> >> For mono-mid, mono-half-left, mono-half-right it shows 1. >> For mono-left, mono-right it shows 0. >> For stereo it shows values between 0 and 1. >> >> I would like to detect mono signals that are not >> exactly in the middle and put them there. Stereo >> signals should be unchanged. >> >> My code is here, but for some reason it does not work >> correctly. Especially when corr shows 0, ba.if does >> not go to the else-path. >> >> import("stdfaust.lib"); >> avg(t,x)= fi.pole(p,(1- p)* x)// 1-pole lowpass as >> average >> with{ >> p= exp((((-2.0* ma.PI)/ t)/ ma.SR)); >> }; >> var(t,x)= avg(t,(x- avg(t,x))^ 2);// variance >> sd(t,x)= sqrt(var(t,x));// standard deviation >> cov(t,x1,x2)= avg(t,(x1- avg(t,x1))* (x2- >> avg(t,x2)));// covariance >> corr(t,x1,x2)= cov(t,x1,x2)/ (sd(t,x1)* >> sd(t,x2)):_;// correlation >> t= 0.5;// averaging period in seconds >> correlate_meter(x,y)= >> x,y<:x,attach(y,(corr(t):hbargraph("corr",-1,1))):_,_; >> correlate_correct(t,l,r)= >> >> ba.if(1>corr(t,l,r)>0,l,(l+r)),ba.if(1>corr(t,l,r)>0,r,(l+r)); >> process= _,_:correlate_meter:correlate_correct(t); >> >> Am I doing the ba.if wrong? >> >> Thank s very much, >> Klaus >> >> >> On 04.08.21 18:25, Dario Sanfilippo wrote: >>> I had implemented a few statistics function a while >>> back, kindly taken from Wikipedia, and they seem to >>> produce the expected values mentioned on the >>> webpage. I hope that these can be useful. >>> >>> Ciao, >>> Dr Dario Sanfilippo >>> http://dariosanfilippo.com <http://dariosanfilippo.com/> >>> >>> import("stdfaust.lib"); >>> avg(t, x) = fi.pole(p, (1 - p) * x) // 1-pole >>> lowpass as average >>> with { >>> p = exp((((-2.0 * ma.PI) / t) / ma.SR)); >>> }; >>> var(t, x) = avg(t, (x - avg(t, x)) ^ 2); // variance >>> sd(t, x) = sqrt(var(t, x)); // standard deviation >>> cov(t, x1, x2) = avg(t, (x1 - avg(t, x1)) * (x2 - >>> avg(t, x2))); // covariance >>> corr(t, x1, x2) = cov(t, x1, x2) / (sd(t, x1) * >>> sd(t, x2)); // correlation >>> ph0 = os.phasor(2.0 * ma.PI, 200); >>> red = sin(ph0) + .35 * sin(ph0 * 3.0) + .91 * >>> sin(ph0 * 5.0); >>> blue = sin(ph0) + .5 * sin(ph0 * 3.0) - .5 * sin(ph0 >>> * 5.0); >>> red1 = sin(ph0) + sin(ph0 * 3.0); >>> blue1 = sin(ph0) - sin(ph0 * 3.0) / 3.0; >>> t = 1.0; // averaging period in seconds >>> process = (red , blue : corr(t)) , (red1 , blue1 : >>> corr(t)); >>> >>> >>> >>> On Wed, 4 Aug 2021 at 16:52, Klaus Scheuermann >>> <kla...@posteo.de <mailto:kla...@posteo.de>> wrote: >>> >>> Thanks Giuseppe, >>> >>> I checked it out, but somehow it still does not >>> give me the desired result... >>> I did some more research and found this, which >>> indicates that it can be done with arctan more >>> easily. >>> >>>> The way this is done on phase (correlation) >>>> meters in audio equipment is rather simple: >>>> >>>> Phase = arctan(L/R) >>>> >>>> With phase of 45 or 225 = 1, and phase of 135 >>>> and 315 (-45) is -1. >>>> >>>> Essentially, the Y Axis is the L, and the X >>>> axis is the R. The phase is simply the polar >>>> angle of the vector between the two. >>>> >>>> This type of meters will show 1 if the signal >>>> is mono, and -1 if the left and right are >>>> perfectly phase inverted. >>>> >>>> Notice however, that phase meters of this type >>>> also account for the magnitude in the polar >>>> coordinates. So: >>>> >>>> Magnitude = (L^2 + R^2)^1/2 >>>> >>>> Thus the actual meter display is a normalised >>>> version of: >>>> >>>> Correlation = Phase * Magnitude >>>> >>>> I'm not sure that satisfies your requirements, >>>> but this answers the question in the subject. >>>> >>> So I transfered this to faust, but it still >>> behaves weired... >>> >>> import("stdfaust.lib"); >>> phase(l,r)= (l/r):aa.arctan; >>> magnitude(l,r)= (l^2+ r^2)^1/2; >>> correlate(l,r)= phase(l,r)* magnitude(l,r); >>> correlate_meter(x,y)= >>> x,y<:x,attach(y,(correlate:hbargraph("corr",-1,1))):_,_; >>> process= _,_:correlate_meter:_,_; >>> >>> Any ideas? >>> >>> Klaus >>> >>> On 03.08.21 14:48, Giuseppe Silvi wrote: >>>> Hi Klaus, >>>> The filters are necessary to obtain a -1 +1 range, I >>>> think. >>>> >>>> import("stdfaust.lib"); >>>> >>>> correlate(l,r) = l*l ,r*r , l*r : par(i,3, >>>> si.smooth(0.9)) : sqrt, sqrt, _ : *,_ : /; >>>> correlate_meter(x,y) = x,y <: x , attach(y, (correlate >>>> : hbargraph("corr”,-1,1))); >>>> >>>> process = correlate_meter; >>>> >>>> Try playing with the si.smooth coefficient. >>>> >>>> best, >>>> giuseppe >>>> >>>>> On 3 Aug 2021, at 14:09, Klaus Scheuermann >>>>> <kla...@posteo.de> <mailto:kla...@posteo.de> wrote: >>>>> >>>>> Could it be something like this? >>>>> >>>>> (according to the 'correct' algorithm in >>>>> https://www.beis.de/Elektronik/Correlation/CorrelationCorrectAndWrong.html >>>>> >>>>> <https://www.beis.de/Elektronik/Correlation/CorrelationCorrectAndWrong.html> >>>>> ) >>>>> import("stdfaust.lib"); >>>>> >>>>> correlate(l,r) = l*l ,r*r , l*r : sqrt, sqrt, _ : *,_ >>>>> : / :_; >>>>> correlate_meter(x,y) = x,y <: x , attach(y, >>>>> (correlate : hbargraph("corr",-1,1))) : _,_; >>>>> >>>>> process = _,_ : correlate_meter: _,_; >>>>> >>>>> I am not sure about the lowpass filters though. Maybe >>>>> not needed in the digital domain? >>>>> >>>>> Also, my code only returns -1 or 1 while it should be >>>>> returning a range of -1 and 1, right? >>>>>> The correlation is either expressed in % from -100% >>>>>> to +100% or as the correlation factor, which ranges from -1 to +1. Note >>>>>> that due to the correlation algorithm the level of both signals does not >>>>>> matter, i.e., it does not influence the measured result. >>>>>> >>>>>> When a mono source is used for a stereo signal both >>>>>> stereo channels will be +100% correlated. When e.g. in a stereo signal >>>>>> both channels contain completely different signals, e.g. left (and only >>>>>> left) is the trumpet and right (and only right) is the guitar these >>>>>> stereo channels will be 0% correlated. With a third instrument appearing >>>>>> in both channels, the correlation will be somewhere between 0 and +100%. >>>>>> >>>>> Ideas? >>>>> Danke :) >>>>> Klaus >>>>> >>>>> >>>>> >>>>> >>>>> On 03.08.21 12:48, Klaus Scheuermann wrote: >>>>>> Hello List, >>>>>> >>>>>> I just wondered, if anyone has implemented a stereo >>>>>> audio correlation >>>>>> meter/analyser in faust? >>>>>> >>>>>> If yes - great! >>>>>> If no - I have another project :) >>>>>> >>>>>> Here is what I found about the algorithm(s): >>>>>> >>>>>> >>>>>> https://www.beis.de/Elektronik/Correlation/CorrelationCorrectAndWrong.html >>>>>> >>>>>> <https://www.beis.de/Elektronik/Correlation/CorrelationCorrectAndWrong.html> >>>>>> >>>>>> >>>>>> I never learned analog electronic schematics, but it >>>>>> seems it should not >>>>>> be extremely hard to transfer to faust. >>>>>> >>>>>> Cheers, Klaus >>>>>> >>>>>> >>>>>> >>>>>> _______________________________________________ >>>>>> Faudiostream-users mailing list >>>>>> >>>>>> 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> >>>>> _______________________________________________ >>>>> Faudiostream-users mailing list >>>>> 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> >>> _______________________________________________ >>> Faudiostream-users mailing list >>> 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> >>> >> _______________________________________________ >> Faudiostream-users mailing list >> 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> >> >> >> >> -- >> "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