Old 03-13-2013, 06:51 PM   #1
plush2
Human being with feelings
 
Join Date: May 2006
Location: Saskatoon, Canada
Posts: 1,826
Default Ambisonic Visualizer...I've gone as far as I can

This is a request for some assistance from the knowledgeable folks here. I've set out to create an ambisonic meter/visualizer that, at a glance can show soundfield location, intensity and frequency content of a b-format signal. I've definitely achieved the first goal. With test tones and actual recordings the visualizer can display the location of audio activity in 3d space.

mono pink noise azimuth 325deg elevation 46deg


mono sine wave azimuth 325deg elevation 46deg


There's quite a bit of noise in the plot but the actual location seems quite accurate and responsive.

As for the color based indication of frequency content goal I have tried and mostly...well just tried.

Anyways, I know that there are many oddities to my code so please go easy on me. This is my first (somewhat succesful) foray into FFT so I only half know what's actually going on. I would ask a specific question but I don't really even know what that would be. I suppose reducing the noise and increasing the accuracy would be two hopeful goals.

Play around with it, let me know what you think, feel free to suggest changes and/or make them and repost.

Code:
desc:Analyzer for B-Format Ambisonic signals
filename:0,AmbisonicAnalyzer.png
slider1:1<1,20,1>gate (dB)
@init
cDenorm=10^-30;
fftsize=64;
gfx_clear=-1;
off=fftsize;
off2=off*2;
nsamples=off;
b=i=0;
phrate=srate;

//memory function
function memfft(b1,b2,bpos,spl)(
  t=b1+bpos;
  this.p0=t[pos];
  t[pos]=spl * (0.35875-0.48829*(cos(2*$pi*pos/fftsize-1))+0.14128*(cos(4*$pi*pos/fftsize-1))-0.01168*(cos(6*$pi*pos/fftsize-1)));
  t=b2+bpos;//fftsize+bpos;
  this.p1=t[pos] * (0.35875-0.48829*(cos(2*$pi*pos/fftsize-1))+0.14128*(cos(4*$pi*pos/fftsize-1))-0.01168*(cos(6*$pi*pos/fftsize-1)));
  this.t[pos]=spl;
);

//function to weight fft
function wghtFFT(bwt)(
  bwt=(0.35875-0.48829*(cos(2*bwt))+0.14128*(cos(4*bwt))-0.01168*(cos(6*bwt)));
);

// function to plot points
function plotFFT(wr,xr,yr,zr,wi,xi,yi,zi)(
  // @ angles
  radius=sqrt((xi^2+xr^2)^2+(yi^2+yr^2)^2+(zi^2+zr^2)^2);
  rphi=atan2(zr,sqrt(xr^2+yr^2));
  rtheta=atan2(yr,xr);
  //center the display of values on the graph
  rtheta >= 0 || rtheta = rtheta + ($pi * 2);
  rphi >= 0 || rphi = rphi + ($pi);
  phi=(rphi*(180/$pi));
  phi > 90 ? phi = phi -90 : phi = phi + 90;
  theta=(rtheta*(180/$pi));
  theta != 360 || theta = 0 & 360;
  theta != 0 || theta = 0 & 360;
  // replace these brute force workarounds with actual latitudinal scaling
  phi < 0 ? theta = 0;
  phi > 180 ? theta = 180;
  this.radius = radius;
  this.phi = (phi*2);
  this.theta = (theta*2);
  b <= fftsize ? this.off2[b]=b+=1 : b=0;
);


@slider
bufpos=bi1=0;
bufpos2=bi3=fftsize*3;
bufpos3=bi5=fftsize*5;
bufpos4=bi7=fftsize*7;
bi2=fftsize*2;
bi4=fftsize*4;
bi6=fftsize*6;
bi8=fftsize*8;
minvol=slider1/10000; // squared
scale=1/fftsize;
// @ precision
prec=1;
// @ scale
vscale=100000;

@block

@sample

//regular position detection
W=spl0*0.707107;
X=spl1;
Y=spl2;
Z=spl3;
//ntzro=rand(0.000001);

// determine which quadrant the audio is in
xp=abs(W+X);xn=abs(W-X);yp=abs(W+Y);yn=abs(W-Y);zp=abs(W+Z);zn=abs(W-Z);
xp >= xn || X = abs(X); 
xp < xn || X = -abs(X);
yp <= yn || Y = abs(Y); 
yp > yn || Y = -abs(Y);
zp <= zn || Z = -abs(Z);
zp > zn || Z = abs(Z);


W.memfft(bi1,bi2,bufpos,W);
X.memfft(bi3,bi4,bufpos2,X);
Y.memfft(bi5,bi6,bufpos3,Y);
Z.memfft(bi7,bi8,bufpos4,Z);


bufpos+=1; bufpos2+=1; bufpos3+=1; bufpos4+=1;

//fft stuff
bufpos >= fftsize*2 ? (
  // swap b1 and b2
  W.t=bi1; bi1=bi2; bi2=W.t;
  X.t=bi3; bi3=bi4; bi4=X.t;
  Y.t=bi5; bi5=bi6; bi6=Y.t;
  Z.t=bi7; bi7=bi8; bi8=Z.t;
  // we hit our FFT size here
  fft(bi1,fftsize); fft(bi3,fftsize); fft(bi5,fftsize); fft(bi7,fftsize);
  fft_permute(bi1,fftsize); fft_permute(bi3,fftsize); fft_permute(bi5,fftsize); fft_permute(bi7,fftsize);
  loop(fftsize,
    i <= fftsize ?(
    wr=bi1[i]; xr=bi3[i]; yr=bi5[i]; zr=bi7[i];
    wi=bi1[i+1]; xi=bi3[i+1]; yi=bi5[i+1]; zi=bi7[i+1];
    all.plotFFT(wr,xr,yr,zr,wi,xi,yi,zi);
    alpha=pow(2,all.radius);
    gfx_a=alpha*0.9;    
    lp = fftsize/16; 
    all.theta<=720 ? avgtheta=all.theta : avgtheta=null;
    all.phi<=360 ? avgphi=all.phi : avgphi=null;           
    
    i <= lp ? (
      gfx_x=avgtheta;
      gfx_y=avgphi;
      cr=0;cg=0;cb=0;crc=0;cgc=0;cbc=0;
      all.off2[i]==0?gfx_setpixel(cr,cg,cb):gfx_setpixel(crc,cgc,cbc);
      );   
    i <= fftsize-(fftsize/4)*3 && i > lp ? (
      gfx_x=avgtheta;
      gfx_y=avgphi;
      cr=0.25;cg=1;cb=1;crc=0.25;cgc=1;cbc=1;
      all.off2[i]==0?gfx_setpixel(cr,cg,cb):gfx_setpixel(crc,cgc,cbc);
      );
    i > fftsize-(fftsize/4)*3 && i <= fftsize-fftsize/4 ? (
      gfx_x=avgtheta;
      gfx_y=avgphi;
      cr=1;cg=1;cb=1;crc=0;cgc=1;cbc=1;
      all.off2[i]==0?gfx_setpixel(cr,cg,cb):gfx_setpixel(crc,cgc,cbc);
      );
    i > fftsize-fftsize/4 ? (
      gfx_x=avgtheta;
      gfx_y=avgphi;
      cr=1;cg=1;cb=0;crc=1;cgc=1;cbc=0;
      all.off2[i]==0?gfx_setpixel(cr,cg,cb):gfx_setpixel(crc,cgc,cbc);
      );
    );
    
    i+=2;
  );
  i=0;
  fft_ipermute(bi1,fftsize); fft_ipermute(bi3,fftsize); fft_ipermute(bi5,fftsize); fft_ipermute(bi7,fftsize);
  ifft(bi1,fftsize); ifft(bi3,fftsize); ifft(bi5,fftsize); ifft(bi7,fftsize);
  bufpos=0; bufpos2=0; bufpos3=0; bufpos4=0;
);

@gfx 720 360

// @ clear plot
(mouse_cap) ? (
  gfx_r=gfx_g=gfx_b=gfx_x=gfx_y=0;
  gfx_a=1;
  gfx_rectto(gfx_w,gfx_h);
);
    




// @ get dimensions
coordinatelist=1000000; // use memory slots 1000000-1000009
gfx_a=1;
gfx_r=gfx_g=gfx_b=1;
 //set up and draw the background graphics
  coordinatelist[0]=0;      //left-most pixel location for source
  coordinatelist[1]=0;      //top-most pixel location for source
  coordinatelist[2]=720;    //width of source
  coordinatelist[3]=360;    //height of source
  coordinatelist[4]=0;      //left-most pixel location of destination
  coordinatelist[5]=0;      //top-most pixel location of destination
  coordinatelist[6]=720;    //width of destination to fill
  coordinatelist[7]=360;    //height of destination to fill
  coordinatelist[8]=0; //represents offset from center of image
  coordinatelist[9]=0; //represents offset from center of image
  gfx_blitext(0,coordinatelist,0);
  
  
// @ fade out
gfx_r=gfx_g=gfx_b=0;gfx_a=0.1;
gfx_x=gfx_y=0;
gfx_rectto(gfx_w,gfx_h);
gfx_blurto(gfx_w,gfx_h);
You'll need this .png image to get the grid background.

AmbisonicAnalyzer.png
__________________
mymusic - http://music.darylpierce.com
mywork - http://production.darylpierce.com

Last edited by plush2; 11-22-2016 at 12:13 PM.
plush2 is offline   Reply With Quote
Old 03-13-2013, 06:58 PM   #2
plush2
Human being with feelings
 
Join Date: May 2006
Location: Saskatoon, Canada
Posts: 1,826
Default

Attached is a test fx chain with a pink noise generator, a tone generator, one of the excellent WigWare Ambisonic Panners, and the Ambisonic Analyzer.

The slider at the top of the analyzer was a vestige of a previous attempt at gating out low level noise. Currently it serves no function but an aesthetic one (much like glasses can make someone look smart whether they are needed or not).
Attached Images
File Type: png AmbisonicAnalyzer.png (5.7 KB, 170 views)
Attached Files
File Type: rfxchain AmbisonicAnalyzerTest.RfxChain (310 Bytes, 84 views)
__________________
mymusic - http://music.darylpierce.com
mywork - http://production.darylpierce.com

Last edited by plush2; 03-14-2013 at 04:18 AM. Reason: added AmbisonicAnalyzer.png
plush2 is offline   Reply With Quote
Old 03-14-2013, 02:20 AM   #3
witti
Human being with feelings
 
witti's Avatar
 
Join Date: May 2012
Posts: 1,186
Default

Hi, nice plugin !

I tested it. The gui is flickering and sometimes after a while it freezes.
I wanted to post a gif, but licecap doesn't capture it.
When i open the plugin with the editor i can see that some calculation is going on,
even when the plugin is not running. Could be the reason.

(you forgot to post the AmbisonicAnalyzer.png)

regards

w
witti is offline   Reply With Quote
Old 03-14-2013, 04:23 AM   #4
plush2
Human being with feelings
 
Join Date: May 2006
Location: Saskatoon, Canada
Posts: 1,826
Default

Thanks witti, I forgot to add that this is very much a work in progress. I've added AmbisonicAnalyzer to the attachments on the 2nd post. You are absolutely right. It does flicker and sometimes freeze. I think it has to do with memory management but I'm not sure. I think it has the potential to be a very useful tool for those of us using Ambisonics in Reaper but I've realized over the last few months of tinkering that I am currently not able to fix it enough to be ready for everyday use.
  • Flickering and freezing GUI

We'll start a bug list.
__________________
mymusic - http://music.darylpierce.com
mywork - http://production.darylpierce.com
plush2 is offline   Reply With Quote
Old 03-14-2013, 05:46 AM   #5
witti
Human being with feelings
 
witti's Avatar
 
Join Date: May 2012
Posts: 1,186
Default

In the @sample section , everywhere i saw some gfx code, i moved it to the @gfx section. Now there is no more flickering. Don't know if i have destroyed something. Needs some testing.

Code:
desc:Analyzer for B-Format Ambisonic signals

filename:0,AmbisonicAnalyzer.png

slider1:1<1,20,1>gate (dB)

@init
cDenorm=10^-30;
fftsize=64;
gfx_clear=-1;
off=fftsize;
off2=off*2;
nsamples=off;
b=i=0;
phrate=srate;

//memory function
function memfft(b1,b2,bpos,spl)(
t=b1+bpos;
this.p0=t[pos];
t[pos]=spl * (0.35875-0.48829*(cos(2*$pi*pos/fftsize-1))+0.14128*(cos(4*$pi*pos/fftsize-1))-0.01168*(cos(6*$pi*pos/fftsize-1)));
t=b2+bpos;//fftsize+bpos;
this.p1=t[pos] * (0.35875-0.48829*(cos(2*$pi*pos/fftsize-1))+0.14128*(cos(4*$pi*pos/fftsize-1))-0.01168*(cos(6*$pi*pos/fftsize-1)));
this.t[pos]=spl;
);

//function to weight fft
function wghtFFT(bwt)(
bwt=(0.35875-0.48829*(cos(2*bwt))+0.14128*(cos(4*bwt))-0.01168*(cos(6*bwt)));
);

// function to plot points
function plotFFT(wr,xr,yr,zr,wi,xi,yi,zi)(
// @ angles
radius=sqrt((xi^2+xr^2)^2+(yi^2+yr^2)^2+(zi^2+zr^2)^2);
rphi=atan2(zr,sqrt(xr^2+yr^2));
rtheta=atan2(yr,xr);
//center the display of values on the graph
rtheta >= 0 || rtheta = rtheta + ($pi * 2);
rphi >= 0 || rphi = rphi + ($pi);
phi=(rphi*(180/$pi));
phi > 90 ? phi = phi -90 : phi = phi + 90;
theta=(rtheta*(180/$pi));
theta != 360 || theta = 0 & 360;
theta != 0 || theta = 0 & 360;
// replace these brute force workarounds with actual latitudinal scaling
phi < 0 ? theta = 0;
phi > 180 ? theta = 180;
this.radius = radius;
this.phi = (phi*2);
this.theta = (theta*2);
b <= fftsize ? this.off2[b]=b+=1 : b=0;
);

@slider
bufpos=bi1=0;
bufpos2=bi3=fftsize*3;
bufpos3=bi5=fftsize*5;
bufpos4=bi7=fftsize*7;
bi2=fftsize*2;
bi4=fftsize*4;
bi6=fftsize*6;
bi8=fftsize*8;
minvol=slider1/10000; // squared
scale=1/fftsize;
// @ precision
prec=1;
// @ scale
vscale=100000;

@block

@sample

//regular position detection
W=spl0*0.707107;
X=spl1;
Y=spl2;
Z=spl3;
//ntzro=rand(0.000001);

// determine which quadrant the audio is in
xp=abs(W+X);xn=abs(W-X);yp=abs(W+Y);yn=abs(W-Y);zp=abs(W+Z);zn=abs(W-Z);
xp >= xn || X = abs(X); 
xp < xn || X = -abs(X);
yp <= yn || Y = abs(Y); 
yp > yn || Y = -abs(Y);
zp <= zn || Z = -abs(Z);
zp > zn || Z = abs(Z);

W.memfft(bi1,bi2,bufpos,W);
X.memfft(bi3,bi4,bufpos2,X);
Y.memfft(bi5,bi6,bufpos3,Y);
Z.memfft(bi7,bi8,bufpos4,Z);

bufpos+=1; bufpos2+=1; bufpos3+=1; bufpos4+=1;

//fft stuff
bufpos >= fftsize*2 ? (
// swap b1 and b2
W.t=bi1; bi1=bi2; bi2=W.t;
X.t=bi3; bi3=bi4; bi4=X.t;
Y.t=bi5; bi5=bi6; bi6=Y.t;
Z.t=bi7; bi7=bi8; bi8=Z.t;
// we hit our FFT size here
fft(bi1,fftsize); fft(bi3,fftsize); fft(bi5,fftsize); fft(bi7,fftsize);
fft_permute(bi1,fftsize); fft_permute(bi3,fftsize); fft_permute(bi5,fftsize); fft_permute(bi7,fftsize);

//-----------cut-----------//

i=0;
fft_ipermute(bi1,fftsize); fft_ipermute(bi3,fftsize); fft_ipermute(bi5,fftsize); fft_ipermute(bi7,fftsize);
ifft(bi1,fftsize); ifft(bi3,fftsize); ifft(bi5,fftsize); ifft(bi7,fftsize);
bufpos=0; bufpos2=0; bufpos3=0; bufpos4=0;
);

@gfx 720 360
//----------paste----------//
loop(fftsize,
i <= fftsize ?(
wr=bi1[i]; xr=bi3[i]; yr=bi5[i]; zr=bi7[i];
wi=bi1[i+1]; xi=bi3[i+1]; yi=bi5[i+1]; zi=bi7[i+1];
all.plotFFT(wr,xr,yr,zr,wi,xi,yi,zi);
alpha=pow(2,all.radius);
gfx_a=alpha*0.9;    
lp = fftsize/16; 
all.theta<=720 ? avgtheta=all.theta : avgtheta=null;
all.phi<=360 ? avgphi=all.phi : avgphi=null;           

i <= lp ? (
gfx_x=avgtheta;
gfx_y=avgphi;
cr=0;cg=0;cb=0;crc=0;cgc=0;cbc=0;
all.off2[i]==0?gfx_setpixel(cr,cg,cb):gfx_setpixel(crc,cgc,cbc);
);   
i <= fftsize-(fftsize/4)*3 && i > lp ? (
gfx_x=avgtheta;
gfx_y=avgphi;
cr=0.25;cg=1;cb=1;crc=0.25;cgc=1;cbc=1;
all.off2[i]==0?gfx_setpixel(cr,cg,cb):gfx_setpixel(crc,cgc,cbc);
);
i > fftsize-(fftsize/4)*3 && i <= fftsize-fftsize/4 ? (
gfx_x=avgtheta;
gfx_y=avgphi;
cr=1;cg=1;cb=1;crc=0;cgc=1;cbc=1;
all.off2[i]==0?gfx_setpixel(cr,cg,cb):gfx_setpixel(crc,cgc,cbc);
);
i > fftsize-fftsize/4 ? (
gfx_x=avgtheta;
gfx_y=avgphi;
cr=1;cg=1;cb=0;crc=1;cgc=1;cbc=0;
all.off2[i]==0?gfx_setpixel(cr,cg,cb):gfx_setpixel(crc,cgc,cbc);
);
);
i+=2;
);
//--------------------------------

// @ clear plot
(mouse_cap) ? (
gfx_r=gfx_g=gfx_b=gfx_x=gfx_y=0;
gfx_a=1;
gfx_rectto(gfx_w,gfx_h);
);

// @ get dimensions
coordinatelist=1000000; // use memory slots 1000000-1000009
gfx_a=1;
gfx_r=gfx_g=gfx_b=1;
//set up and draw the background graphics
coordinatelist[0]=0;      //left-most pixel location for source
coordinatelist[1]=0;      //top-most pixel location for source
coordinatelist[2]=720;    //width of source
coordinatelist[3]=360;    //height of source
coordinatelist[4]=0;      //left-most pixel location of destination
coordinatelist[5]=0;      //top-most pixel location of destination
coordinatelist[6]=720;    //width of destination to fill
coordinatelist[7]=360;    //height of destination to fill
coordinatelist[8]=0; //represents offset from center of image
coordinatelist[9]=0; //represents offset from center of image
gfx_blitext(0,coordinatelist,0);

// @ fade out
gfx_r=gfx_g=gfx_b=0;gfx_a=0.1;
gfx_x=gfx_y=0;
gfx_rectto(gfx_w,gfx_h);
gfx_blurto(gfx_w,gfx_h);
witti is offline   Reply With Quote
Old 03-14-2013, 01:34 PM   #6
plush2
Human being with feelings
 
Join Date: May 2006
Location: Saskatoon, Canada
Posts: 1,826
Default

That seems to be the way to fix the flickering. I actually played around with this. My one reason for having all those gfx draws in from the fft bins outside the @gfx section was I liked the speed of the drawn content. It seems more sparse and less responsive in the 30fps @gfx section...although much less flickery.
__________________
mymusic - http://music.darylpierce.com
mywork - http://production.darylpierce.com
plush2 is offline   Reply With Quote
Old 03-14-2013, 08:44 PM   #7
plush2
Human being with feelings
 
Join Date: May 2006
Location: Saskatoon, Canada
Posts: 1,826
Default

I must apologize...on closer inspection I have greatly oversimplified what you are proposing. I'm taking a closer look now at the new structure, trying to wrap my thinking around it. The most interesting part is you seem to suggest that I was wrong in thinking I needed to keep my fft permute and ipermute stuff inside of my processing loop (which has the graphics stuff in it).

I don't suppose you'd have any suggestions of how we could clarify the existing location points so they indicate actual events a bit better? I'll upload a 4 channel ogg ambisonic recording with some sparse sounds to play around with tomorrow morning. That will be a better real world accuracy test than these tones.
__________________
mymusic - http://music.darylpierce.com
mywork - http://production.darylpierce.com
plush2 is offline   Reply With Quote
Old 03-15-2013, 05:05 PM   #8
witti
Human being with feelings
 
witti's Avatar
 
Join Date: May 2012
Posts: 1,186
Default

It's always hard to follow someone elses code
and my bad english doesn't allow to go into deep discussions.

When i saw your code i just found it a little strange to find some gfx code in the @sample section, so this was just some trial and error.
Maybe someone else has some better solutions ?

I'm quite sure that there is only some little detail missing to make your plugin running smooth.

Last edited by witti; 03-15-2013 at 05:18 PM.
witti is offline   Reply With Quote
Old 03-15-2013, 06:29 PM   #9
plush2
Human being with feelings
 
Join Date: May 2006
Location: Saskatoon, Canada
Posts: 1,826
Default

witti, I thank you for taking the time to look at my code. It was not your english, it was just my lack of attention. I assumed I knew what you were doing instead of actually looking at the code.

As promised, here is a more interesting 4 channel ogg file recording of myself walking from street level up to my appartment. It provides a bunch of real-world localized sounds that should make the successes and flaws of the analyzer more apparent.

The main functional deficit in the design currently is that it plots a correlation of the b-format signals. Since it's plotting fast it can appear to present multiple discrete points but I think a lot of the noise is the intermediary relationships. Does anyone know how to plot multiple discrete locations...similar to how QuikQuak Mashtactic seems to?
__________________
mymusic - http://music.darylpierce.com
mywork - http://production.darylpierce.com
plush2 is offline   Reply With Quote
Old 11-05-2016, 07:44 AM   #10
eviluess
Human being with feelings
 
eviluess's Avatar
 
Join Date: Dec 2015
Location: Guangzhou, China
Posts: 121
Default

Quote:
Originally Posted by plush2 View Post
This is a request for some assistance from the knowledgeable folks here. I've set out to create an ambisonic meter/visualizer that, at a glance can show soundfield location, intensity and frequency content of a b-format signal. I've definitely achieved the first goal. With test tones and actual recordings the visualizer can display the location of audio activity in 3d space.

mono pink noise azimuth 325deg elevation 46deg


mono sine wave azimuth 325deg elevation 46deg


There's quite a bit of noise in the plot but the actual location seems quite accurate and responsive.

As for the color based indication of frequency content goal I have tried and mostly...well just tried.

Anyways, I know that there are many oddities to my code so please go easy on me. This is my first (somewhat succesful) foray into FFT so I only half know what's actually going on. I would ask a specific question but I don't really even know what that would be. I suppose reducing the noise and increasing the accuracy would be two hopeful goals.

Play around with it, let me know what you think, feel free to suggest changes and/or make them and repost.

Code:
desc:Analyzer for B-Format Ambisonic signals
filename:0,AmbisonicAnalyzer.png
slider1:1<1,20,1>gate (dB)
@init
cDenorm=10^-30;
fftsize=64;
gfx_clear=-1;
off=fftsize;
off2=off*2;
nsamples=off;
b=i=0;
phrate=srate;

//memory function
function memfft(b1,b2,bpos,spl)(
  t=b1+bpos;
  this.p0=t[pos];
  t[pos]=spl * (0.35875-0.48829*(cos(2*$pi*pos/fftsize-1))+0.14128*(cos(4*$pi*pos/fftsize-1))-0.01168*(cos(6*$pi*pos/fftsize-1)));
  t=b2+bpos;//fftsize+bpos;
  this.p1=t[pos] * (0.35875-0.48829*(cos(2*$pi*pos/fftsize-1))+0.14128*(cos(4*$pi*pos/fftsize-1))-0.01168*(cos(6*$pi*pos/fftsize-1)));
  this.t[pos]=spl;
);

//function to weight fft
function wghtFFT(bwt)(
  bwt=(0.35875-0.48829*(cos(2*bwt))+0.14128*(cos(4*bwt))-0.01168*(cos(6*bwt)));
);

// function to plot points
function plotFFT(wr,xr,yr,zr,wi,xi,yi,zi)(
  // @ angles
  radius=sqrt((xi^2+xr^2)^2+(yi^2+yr^2)^2+(zi^2+zr^2)^2);
  rphi=atan2(zr,sqrt(xr^2+yr^2));
  rtheta=atan2(yr,xr);
  //center the display of values on the graph
  rtheta >= 0 || rtheta = rtheta + ($pi * 2);
  rphi >= 0 || rphi = rphi + ($pi);
  phi=(rphi*(180/$pi));
  phi > 90 ? phi = phi -90 : phi = phi + 90;
  theta=(rtheta*(180/$pi));
  theta != 360 || theta = 0 & 360;
  theta != 0 || theta = 0 & 360;
  // replace these brute force workarounds with actual latitudinal scaling
  phi < 0 ? theta = 0;
  phi > 180 ? theta = 180;
  this.radius = radius;
  this.phi = (phi*2);
  this.theta = (theta*2);
  b <= fftsize ? this.off2[b]=b+=1 : b=0;
);


@slider
bufpos=bi1=0;
bufpos2=bi3=fftsize*3;
bufpos3=bi5=fftsize*5;
bufpos4=bi7=fftsize*7;
bi2=fftsize*2;
bi4=fftsize*4;
bi6=fftsize*6;
bi8=fftsize*8;
minvol=slider1/10000; // squared
scale=1/fftsize;
// @ precision
prec=1;
// @ scale
vscale=100000;

@block

@sample

//regular position detection
W=spl0*0.707107;
X=spl1;
Y=spl2;
Z=spl3;
//ntzro=rand(0.000001);

// determine which quadrant the audio is in
xp=abs(W+X);xn=abs(W-X);yp=abs(W+Y);yn=abs(W-Y);zp=abs(W+Z);zn=abs(W-Z);
xp >= xn || X = abs(X); 
xp < xn || X = -abs(X);
yp <= yn || Y = abs(Y); 
yp > yn || Y = -abs(Y);
zp <= zn || Z = -abs(Z);
zp > zn || Z = abs(Z);


W.memfft(bi1,bi2,bufpos,W);
X.memfft(bi3,bi4,bufpos2,X);
Y.memfft(bi5,bi6,bufpos3,Y);
Z.memfft(bi7,bi8,bufpos4,Z);


bufpos+=1; bufpos2+=1; bufpos3+=1; bufpos4+=1;

//fft stuff
bufpos >= fftsize*2 ? (
  // swap b1 and b2
  W.t=bi1; bi1=bi2; bi2=W.t;
  X.t=bi3; bi3=bi4; bi4=X.t;
  Y.t=bi5; bi5=bi6; bi6=Y.t;
  Z.t=bi7; bi7=bi8; bi8=Z.t;
  // we hit our FFT size here
  fft(bi1,fftsize); fft(bi3,fftsize); fft(bi5,fftsize); fft(bi7,fftsize);
  fft_permute(bi1,fftsize); fft_permute(bi3,fftsize); fft_permute(bi5,fftsize); fft_permute(bi7,fftsize);
  loop(fftsize,
    i <= fftsize ?(
    wr=bi1[i]; xr=bi3[i]; yr=bi5[i]; zr=bi7[i];
    wi=bi1[i+1]; xi=bi3[i+1]; yi=bi5[i+1]; zi=bi7[i+1];
    all.plotFFT(wr,xr,yr,zr,wi,xi,yi,zi);
    alpha=pow(2,all.radius);
    gfx_a=alpha*0.9;    
    lp = fftsize/16; 
    all.theta<=720 ? avgtheta=all.theta : avgtheta=null;
    all.phi<=360 ? avgphi=all.phi : avgphi=null;           
    
    i <= lp ? (
      gfx_x=avgtheta;
      gfx_y=avgphi;
      cr=0;cg=0;cb=0;crc=0;cgc=0;cbc=0;
      all.off2[i]==0?gfx_setpixel(cr,cg,cb):gfx_setpixel(crc,cgc,cbc);
      );   
    i <= fftsize-(fftsize/4)*3 && i > lp ? (
      gfx_x=avgtheta;
      gfx_y=avgphi;
      cr=0.25;cg=1;cb=1;crc=0.25;cgc=1;cbc=1;
      all.off2[i]==0?gfx_setpixel(cr,cg,cb):gfx_setpixel(crc,cgc,cbc);
      );
    i > fftsize-(fftsize/4)*3 && i <= fftsize-fftsize/4 ? (
      gfx_x=avgtheta;
      gfx_y=avgphi;
      cr=1;cg=1;cb=1;crc=0;cgc=1;cbc=1;
      all.off2[i]==0?gfx_setpixel(cr,cg,cb):gfx_setpixel(crc,cgc,cbc);
      );
    i > fftsize-fftsize/4 ? (
      gfx_x=avgtheta;
      gfx_y=avgphi;
      cr=1;cg=1;cb=0;crc=1;cgc=1;cbc=0;
      all.off2[i]==0?gfx_setpixel(cr,cg,cb):gfx_setpixel(crc,cgc,cbc);
      );
    );
    
    i+=2;
  );
  i=0;
  fft_ipermute(bi1,fftsize); fft_ipermute(bi3,fftsize); fft_ipermute(bi5,fftsize); fft_ipermute(bi7,fftsize);
  ifft(bi1,fftsize); ifft(bi3,fftsize); ifft(bi5,fftsize); ifft(bi7,fftsize);
  bufpos=0; bufpos2=0; bufpos3=0; bufpos4=0;
);

@gfx 720 360

// @ clear plot
(mouse_cap) ? (
  gfx_r=gfx_g=gfx_b=gfx_x=gfx_y=0;
  gfx_a=1;
  gfx_rectto(gfx_w,gfx_h);
);
    




// @ get dimensions
coordinatelist=1000000; // use memory slots 1000000-1000009
gfx_a=1;
gfx_r=gfx_g=gfx_b=1;
 //set up and draw the background graphics
  coordinatelist[0]=0;      //left-most pixel location for source
  coordinatelist[1]=0;      //top-most pixel location for source
  coordinatelist[2]=720;    //width of source
  coordinatelist[3]=360;    //height of source
  coordinatelist[4]=0;      //left-most pixel location of destination
  coordinatelist[5]=0;      //top-most pixel location of destination
  coordinatelist[6]=720;    //width of destination to fill
  coordinatelist[7]=360;    //height of destination to fill
  coordinatelist[8]=0; //represents offset from center of image
  coordinatelist[9]=0; //represents offset from center of image
  gfx_blitext(0,coordinatelist,0);
  
  
// @ fade out
gfx_r=gfx_g=gfx_b=0;gfx_a=0.1;
gfx_x=gfx_y=0;
gfx_rectto(gfx_w,gfx_h);
gfx_blurto(gfx_w,gfx_h);

It's not showing anything except the Background PNG.
Could you please post the latest version again?

Thanks!
eviluess is offline   Reply With Quote
Old 11-05-2016, 01:50 PM   #11
plush2
Human being with feelings
 
Join Date: May 2006
Location: Saskatoon, Canada
Posts: 1,826
Default

Hi eviluess, I haven't worked on this much since but this version is working (such as it is) on my system. Let me know how you get on or if you have ideas to improve it.

Code:
desc:Analyzer for B-Format Ambisonic signals
filename:0,AmbisonicAnalyzer.png
@init
cDenorm=10^-30;
fftsize=8192;
gfx_clear=-1;
off=fftsize;
off2=off*2;
nsamples=off;
b=i=0;
phrate=1/srate;
//memory function
function memfft(b1,b2,bpos,spl)(
t=b1+bpos;
this.p0=t[pos];
spl=spl*phrate;
t[pos]=spl * (0.35875-0.48829*(cos(2*$pi*pos/fftsize-1))+0.14128*(cos(4*$pi*pos/fftsize-1))-0.01168*(cos(6*$pi*pos/fftsize-1)));
t=b2+bpos;fftsize+bpos;
this.p1=t[pos] * (0.35875-0.48829*(cos(2*$pi*pos/fftsize-1))+0.14128*(cos(4*$pi*pos/fftsize-1))-0.01168*(cos(6*$pi*pos/fftsize-1)));
this.t[pos]=spl/phrate;
);
// function to plot points
function plotFFT(wr,xr,yr,zr,wi,xi,yi,zi)(
// @ angles
radius=sqrt(spl0^2+spl1^2+spl2^2+spl3^2);
//radius=sqrt((xi^2+xr^2)^2+(yi^2+yr^2)^2+(zi^2+zr^2)^2);
rphi=atan2(zr,sqrt(xr^2+yr^2));
rtheta=atan2(yr,xr);
//center the display of values on the graph
rtheta >= 0 || rtheta = rtheta + ($pi * 2);
rphi >= 0 || rphi = rphi + ($pi);
phi=(rphi*(180/$pi));
phi > 90 ? phi = phi -90 : phi = phi + 90;
theta=(rtheta*(180/$pi));
theta != 360 || theta = 0 & 360;
theta != 0 || theta = 0 & 360;
// replace these brute force workarounds with actual latitudinal scaling
phi < 0 ? theta = 0;
phi > 180 ? theta = 180;
this.radius = radius;
this.phi = (phi*2);
this.theta = (theta*2);
b <= fftsize ? this.off2[b]=b+=1 : b=0;
);
@slider
bufpos=bi1=0;
bufpos2=bi3=fftsize*3;
bufpos3=bi5=fftsize*5;
bufpos4=bi7=fftsize*7;
bi2=fftsize*2;
bi4=fftsize*4;
bi6=fftsize*6;
bi8=fftsize*8;
@block
@sample
//regular position detection
W=spl0*0.707107;
X=spl1;
Y=spl2;
Z=spl3;
// determine which quadrant the audio is in
xp=abs(W+X);xn=abs(W-X);yp=abs(W+Y);yn=abs(W-Y);zp=abs(W+Z);zn=abs(W-Z);
xp >= xn || X = abs(X); 
xp < xn || X = -abs(X);
yp <= yn || Y = abs(Y); 
yp > yn || Y = -abs(Y);
zp <= zn || Z = -abs(Z);
zp > zn || Z = abs(Z);
W.memfft(bi1,bi2,bufpos,W);
X.memfft(bi3,bi4,bufpos2,X);
Y.memfft(bi5,bi6,bufpos3,Y);
Z.memfft(bi7,bi8,bufpos4,Z);
bufpos+=1; bufpos2+=1; bufpos3+=1; bufpos4+=1;
//fft stuff
bufpos >= fftsize ? (
// swap b1 and b2
W.t=bi1; bi1=bi2; bi2=W.t;
X.t=bi3; bi3=bi4; bi4=X.t;
Y.t=bi5; bi5=bi6; bi6=Y.t;
Z.t=bi7; bi7=bi8; bi8=Z.t;
// we hit our FFT size here
fft(bi1,fftsize); fft(bi3,fftsize); fft(bi5,fftsize); fft(bi7,fftsize);
fft_permute(bi1,fftsize); fft_permute(bi3,fftsize); fft_permute(bi5,fftsize); fft_permute(bi7,fftsize);
//-----------cut-----------//
i=0;
fft_ipermute(bi1,fftsize); fft_ipermute(bi3,fftsize); fft_ipermute(bi5,fftsize); fft_ipermute(bi7,fftsize);
ifft(bi1,fftsize); ifft(bi3,fftsize); ifft(bi5,fftsize); ifft(bi7,fftsize);
bufpos=0; bufpos2=0; bufpos3=0; bufpos4=0;
);
@gfx 720 360
//----------paste----------//
loop(fftsize,
  i <= fftsize ?(
    wr=bi1[i]; xr=bi3[i]; yr=bi5[i]; zr=bi7[i];
    wi=bi1[i+1]; xi=bi3[i+1]; yi=bi5[i+1]; zi=bi7[i+1];
    all.plotFFT(wr,xr,yr,zr,wi,xi,yi,zi);
    apoint=all.radius*1000;
    alpha=pow(2,all.radius0);
    //gfx_a=alpha*.1;    
    lp = fftsize/16; 
    all.theta<=720 ? avgtheta=all.theta : avgtheta=null;
    all.phi<=360 ? avgphi=all.phi : avgphi=null;
    color=fftsize-i/fftsize;
    cr=color;cb=0;cg=color;crc=1;cbc=1;
    gfx_x=avgtheta;
    gfx_y=avgphi;
    gfx_a=apoint;
    gfx_rectto(gfx_x,gfx_y);
    all.off2[i]==0?gfx_setpixel(cr,cg,cb):gfx_setpixel(crc,cgc,cbc)
  );
  i+=1;
);
//--------------------------------
// @ clear plot
(mouse_cap) ? (
gfx_r=gfx_g=gfx_b=gfx_x=gfx_y=0;
gfx_a=1;
gfx_rectto(gfx_w,gfx_h);
);
// @ get dimensions
coordinatelist=1000000; // use memory slots 1000000-1000009
gfx_a=1;
//gfx_r=gfx_g=gfx_b=1;
//set up and draw the background graphics
coordinatelist[0]=0;      //left-most pixel location for source
coordinatelist[1]=0;      //top-most pixel location for source
coordinatelist[2]=720;    //width of source
coordinatelist[3]=360;    //height of source
coordinatelist[4]=0;      //left-most pixel location of destination
coordinatelist[5]=0;      //top-most pixel location of destination
coordinatelist[6]=720;    //width of destination to fill
coordinatelist[7]=360;    //height of destination to fill
coordinatelist[8]=0; //represents offset from center of image
coordinatelist[9]=0; //represents offset from center of image
gfx_blitext(0,coordinatelist,0);
// @ fade out
gfx_r=gfx_g=gfx_b=0;gfx_a=0.09;
gfx_x=gfx_y=0;
gfx_rectto(gfx_w,gfx_h);
//gfx_blurto(gfx_w,gfx_h);
__________________
mymusic - http://music.darylpierce.com
mywork - http://production.darylpierce.com
plush2 is offline   Reply With Quote
Old 02-09-2017, 12:03 AM   #12
eviluess
Human being with feelings
 
eviluess's Avatar
 
Join Date: Dec 2015
Location: Guangzhou, China
Posts: 121
Default

Quote:
Originally Posted by plush2 View Post
Hi eviluess, I haven't worked on this much since but this version is working (such as it is) on my system. Let me know how you get on or if you have ideas to improve it.

Code:
desc:Analyzer for B-Format Ambisonic signals
filename:0,AmbisonicAnalyzer.png
@init
cDenorm=10^-30;
fftsize=8192;
gfx_clear=-1;
off=fftsize;
off2=off*2;
nsamples=off;
b=i=0;
phrate=1/srate;
//memory function
function memfft(b1,b2,bpos,spl)(
t=b1+bpos;
this.p0=t[pos];
spl=spl*phrate;
t[pos]=spl * (0.35875-0.48829*(cos(2*$pi*pos/fftsize-1))+0.14128*(cos(4*$pi*pos/fftsize-1))-0.01168*(cos(6*$pi*pos/fftsize-1)));
t=b2+bpos;fftsize+bpos;
this.p1=t[pos] * (0.35875-0.48829*(cos(2*$pi*pos/fftsize-1))+0.14128*(cos(4*$pi*pos/fftsize-1))-0.01168*(cos(6*$pi*pos/fftsize-1)));
this.t[pos]=spl/phrate;
);
// function to plot points
function plotFFT(wr,xr,yr,zr,wi,xi,yi,zi)(
// @ angles
radius=sqrt(spl0^2+spl1^2+spl2^2+spl3^2);
//radius=sqrt((xi^2+xr^2)^2+(yi^2+yr^2)^2+(zi^2+zr^2)^2);
rphi=atan2(zr,sqrt(xr^2+yr^2));
rtheta=atan2(yr,xr);
//center the display of values on the graph
rtheta >= 0 || rtheta = rtheta + ($pi * 2);
rphi >= 0 || rphi = rphi + ($pi);
phi=(rphi*(180/$pi));
phi > 90 ? phi = phi -90 : phi = phi + 90;
theta=(rtheta*(180/$pi));
theta != 360 || theta = 0 & 360;
theta != 0 || theta = 0 & 360;
// replace these brute force workarounds with actual latitudinal scaling
phi < 0 ? theta = 0;
phi > 180 ? theta = 180;
this.radius = radius;
this.phi = (phi*2);
this.theta = (theta*2);
b <= fftsize ? this.off2[b]=b+=1 : b=0;
);
@slider
bufpos=bi1=0;
bufpos2=bi3=fftsize*3;
bufpos3=bi5=fftsize*5;
bufpos4=bi7=fftsize*7;
bi2=fftsize*2;
bi4=fftsize*4;
bi6=fftsize*6;
bi8=fftsize*8;
@block
@sample
//regular position detection
W=spl0*0.707107;
X=spl1;
Y=spl2;
Z=spl3;
// determine which quadrant the audio is in
xp=abs(W+X);xn=abs(W-X);yp=abs(W+Y);yn=abs(W-Y);zp=abs(W+Z);zn=abs(W-Z);
xp >= xn || X = abs(X); 
xp < xn || X = -abs(X);
yp <= yn || Y = abs(Y); 
yp > yn || Y = -abs(Y);
zp <= zn || Z = -abs(Z);
zp > zn || Z = abs(Z);
W.memfft(bi1,bi2,bufpos,W);
X.memfft(bi3,bi4,bufpos2,X);
Y.memfft(bi5,bi6,bufpos3,Y);
Z.memfft(bi7,bi8,bufpos4,Z);
bufpos+=1; bufpos2+=1; bufpos3+=1; bufpos4+=1;
//fft stuff
bufpos >= fftsize ? (
// swap b1 and b2
W.t=bi1; bi1=bi2; bi2=W.t;
X.t=bi3; bi3=bi4; bi4=X.t;
Y.t=bi5; bi5=bi6; bi6=Y.t;
Z.t=bi7; bi7=bi8; bi8=Z.t;
// we hit our FFT size here
fft(bi1,fftsize); fft(bi3,fftsize); fft(bi5,fftsize); fft(bi7,fftsize);
fft_permute(bi1,fftsize); fft_permute(bi3,fftsize); fft_permute(bi5,fftsize); fft_permute(bi7,fftsize);
//-----------cut-----------//
i=0;
fft_ipermute(bi1,fftsize); fft_ipermute(bi3,fftsize); fft_ipermute(bi5,fftsize); fft_ipermute(bi7,fftsize);
ifft(bi1,fftsize); ifft(bi3,fftsize); ifft(bi5,fftsize); ifft(bi7,fftsize);
bufpos=0; bufpos2=0; bufpos3=0; bufpos4=0;
);
@gfx 720 360
//----------paste----------//
loop(fftsize,
  i <= fftsize ?(
    wr=bi1[i]; xr=bi3[i]; yr=bi5[i]; zr=bi7[i];
    wi=bi1[i+1]; xi=bi3[i+1]; yi=bi5[i+1]; zi=bi7[i+1];
    all.plotFFT(wr,xr,yr,zr,wi,xi,yi,zi);
    apoint=all.radius*1000;
    alpha=pow(2,all.radius0);
    //gfx_a=alpha*.1;    
    lp = fftsize/16; 
    all.theta<=720 ? avgtheta=all.theta : avgtheta=null;
    all.phi<=360 ? avgphi=all.phi : avgphi=null;
    color=fftsize-i/fftsize;
    cr=color;cb=0;cg=color;crc=1;cbc=1;
    gfx_x=avgtheta;
    gfx_y=avgphi;
    gfx_a=apoint;
    gfx_rectto(gfx_x,gfx_y);
    all.off2[i]==0?gfx_setpixel(cr,cg,cb):gfx_setpixel(crc,cgc,cbc)
  );
  i+=1;
);
//--------------------------------
// @ clear plot
(mouse_cap) ? (
gfx_r=gfx_g=gfx_b=gfx_x=gfx_y=0;
gfx_a=1;
gfx_rectto(gfx_w,gfx_h);
);
// @ get dimensions
coordinatelist=1000000; // use memory slots 1000000-1000009
gfx_a=1;
//gfx_r=gfx_g=gfx_b=1;
//set up and draw the background graphics
coordinatelist[0]=0;      //left-most pixel location for source
coordinatelist[1]=0;      //top-most pixel location for source
coordinatelist[2]=720;    //width of source
coordinatelist[3]=360;    //height of source
coordinatelist[4]=0;      //left-most pixel location of destination
coordinatelist[5]=0;      //top-most pixel location of destination
coordinatelist[6]=720;    //width of destination to fill
coordinatelist[7]=360;    //height of destination to fill
coordinatelist[8]=0; //represents offset from center of image
coordinatelist[9]=0; //represents offset from center of image
gfx_blitext(0,coordinatelist,0);
// @ fade out
gfx_r=gfx_g=gfx_b=0;gfx_a=0.09;
gfx_x=gfx_y=0;
gfx_rectto(gfx_w,gfx_h);
//gfx_blurto(gfx_w,gfx_h);

Hey, sorry for my late reply.

I've made it working because I expected it can view in 3D mode.
For it's current 2D displaying mode, it really worked right!

Thanks for your work.

And do you plan to post a 3D version of this?
eviluess is offline   Reply With Quote
Old 02-10-2017, 07:30 PM   #13
plush2
Human being with feelings
 
Join Date: May 2006
Location: Saskatoon, Canada
Posts: 1,826
Default

I had not thought of doing that. Perhaps I (or someone else) could try borrowing from the Reaper 360 viewer code to treat it as an equirectangular projection.

Probably won't happen for a while but I'll think on it.
__________________
mymusic - http://music.darylpierce.com
mywork - http://production.darylpierce.com
plush2 is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 08:21 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, vBulletin Solutions Inc.