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

Reply via email to