Waveguide 3D cubical waveguide model



3D cubical waveguide model. 

The input 3-dimensional coefficients matrix is used to calculate the three reflection matrices (direction dependent). Each different coefficient defines a different "material" in the 3D space. Boundaries between different materials are total reflecting. 

This model was used to sonify the percolation features of a QCD Lattice model. 

A user-defined excitation is applyed to one of the six faces. If the 3D lattice defined by the coefficients percolates (that means that "tunnels" of a same material reach from one side to the other) the sound could be heared arriving at the opposite face. If the model does not percolate the sound never arrives at the opposite face. From the qualities of the sound (for example resonances) arriving on the opposite face one could deduce characteristics of the space in between. 

The Waveguide class was developed and programmed during the QCD-audio project at IEM (Katherina Vogt, David Pirrò, Robert Höldrich).


Warning! The Calculation is computationally intensive!! Will not work in real-time.


Class Method



*new (size, coef, bound, state)

Instantiate a new waveguide model

size - Integer. Side length of the 3D cube.

coef - 3D coefficients matrix used to calculate the reflection matrices.

bound - Float. Bounderies conditions at the edges of the cube: 0.0 means sound is absorbed, -1.0 means sound is totally reflected into the mesh.

state - Which coefficient should be looked for at the end. That means when looking at the arriving sound on one of the faces only one "material" is looked for.


Instance Methods



applyEx (inEx, plane)

Apply Excitation on one of the faces of the cube.

inEx - 2D matrix of qith same side size of the 3D waveguide model.

plane - Symbol determines on which face the excitation should be applyed: can be \N, \S, \E, \W, \U or \D.



calc (server, samples)

Start the calculation. Computationally intensive. 

One sample is calculated by taking the values in the mesh (only the sites with coefficient equal to the state factor, see the *new method described before) on one face, multiplying the obtained 2D matrix by a random mask (to avoid eventual phase cancellation), then summing up all the values in the matrix.

As result the method will return an array of six Buffers one for each face, containing the samples calculated. The Buffers are:

[Buffer North, Buffer South, Buffer East, Buffer West, Buffer Up, Buffer Down].

server - Server.

samples - Number of samples for the calculation should be performed.



play (sampleRate, plane)

sampleRate - Samplerate at which the buffer should be played.

plane - Which plane


plot

Plot the results.



free

Manually free the internal buffers.



Examples


q = ();


q.msize = 10;


q.limit = 0.66666667;

q.state = 0;



///// Generate a 3D coeffiecients array

q.coef = Array.fillND([q.msize,q.msize,q.msize], {arg r,c,p; var ra = 1.0.rand; 

if (ra >= (q.limit)) {1} {

if (ra < (q.limit)) {0}

};

});

///// Instantiate a Waveguide model

q.waveg = Waveguide.new(q.msize,q.coef,-0.9,q.state); 


///// Generate a 2D random matrix to be used as excitation on one face

q.ex = Array.fill2D(q.msize, q.msize, {arg r, c; (((1.0.rand)-0.5)*2)});


///// Apply excitation on the south face

q.waveg.applyEx(q.ex,\S);


///// Caluculate 2000 samples

q.waveg.calc(s,2000);


///// Hear the resluts on the opposing (North) face

q.waveg.play(2000, \N);


///// Plot results

q.waveg.plot;



///// Other Tests

////// Create a test data set: a 3D matrix with a small tunnel going from north to south


q.testdata = Array.fillND([q.msize, q.msize, q.msize], 0);


q.tunnelheight = 2;

q.tunnelwidth = 2;

q.whichheight = 2;

q.whichwidth = 2;


q.testdata.do{|rows, r|

rows.do{|cols, c|

cols.do{|pos, p|

if(c<(q.whichheight + q.tunnelheight) 

  and:{c>(q.whichheight - q.tunnelheight)}

  and:{p<(q.whichwidth + q.tunnelwidth)} 

  and:{p>(q.whichwidth - q.tunnelwidth)})

{q.testdata[r][c][p] = 1} {};

}}};


////// Reflection paramenter for cube boundaries

q.bParam = 1.0.neg; 


////// Instantiate model

q.tunneltest = Waveguide.new(q.msize, q.testdata, q.bParam, 1); 


////// Apply excitation on the south face

q.tunneltest.applyEx(q.ex,\S);


////// Calcultate 4000 samples

q.tunneltest.calc(s,4000);


///// Hear the resluts on the opposing (North) face

q.tunneltest.play(4000, \N);


///// Plot results

q.tunneltest.plot;