sfstoolbox / sfs-matlab

SFS Toolbox for Matlab/Octave
https://sfs-matlab.readthedocs.io
MIT License
98 stars 39 forks source link

New NFC-HOA line source driving function for the mono-chromatic case #54

Closed hagenw closed 8 years ago

hagenw commented 8 years ago

Hi Nara.

This is the code I implemented after your 138th AES Convention paper: http://spatialaudio.net/virtual-cylindrical-waves/ We talked about it some time ago, but I'm not 100% sure about the current status. Could you check if it is ok and merge it into master.

narahahn commented 8 years ago

Great. I think the driving functions are implemented correctly. So far, there is nothing new. One thing I want to discuss is how to treat the line source position. Currently, we are considering line sources that are vertically aligned. For 2D and 2.5D, this is not a big deal since we do not use the z coordinate component. But in 3D cases, the driving function includes the azimuth angle alpha, so the result will be wrong if a line source is defined off the xy-plane. There are some possibilities to avoid this.

  1. Check the position of xs. If it's not on the horizontal plane, (a) return error. (b) project xs onto the xy-plane and then convert it to spherical coordinate.
  2. Use the polar angle phi in the cylindrical coordinate instead of alpha. The result will be the same as 1(b). But we do not need to check the z component. Also no need for cart2sph. Though it may look strange as phi and alpha0 appear together.

Once this is resolved, I think we are good to merge.

hagenw commented 8 years ago

The 3D case is indeed interesting. A few more questions from my side, before proposing a solution:

  1. 3D case means also in this case that we have a spherical array with point source characteristics of the secondary sources?
  2. If this is the case then we should be able to align the desired line source to every orientation we would like? But when I have a look at (20) from your paper it seems indeed to be the case that a line source in the horizontal plane is considered at position (r, alpha, 0)?

It's always a little bit confusing when talking about virtual sources that have characteristics that are not compatible with the underlying secondary sources ;)

narahahn commented 8 years ago

YES and YES. The current driving function can be used for 3D NFC-HOA (using spherical distribution of secondary point sources), only if the line source is parallel to the z-axis.

In order to specify an arbitrarily oriented line source, we need a position vector and an orientation vector. The degree of freedom is 5. Would it be OK to allow xs to have higher dimension? If yes, I think the driving functions can be obtained by applying a rotational operation on the sphere.

hagenw commented 8 years ago

In principle it is possible to have xs with higher dimensions. The focused source uses xs with 6 entries, first 3 for its position and the last 3 for its traveling direction. At the moment we check xs to have a length of 3 or 6, see isargxs().

In the case of 3D NFC-HOA and the line source we should ask if it would be of advantage to have the possibility to orient the line source to arbitrary directions. If you have only one line source, then it is not needed as the array is completely symmetrical and you can adjust the axis accordingly. The only case where it might be of interest is when you want to use more than one line source simultaneously and they should have different orientations (for whatever reasons). Is the implementation/formula a lot more complicated by allowing free orientations?

As I have not really an opinion on this, you can decide what you would prefer.

fietew commented 8 years ago

If think, the degrees of freedom for the position + orientation of an infinitely long line source in 4. Its orientation can be defined by two angles or a unit vector (2 DOFs) and its position is given by any point being part of the line (2 DOFs). However, I think that we should stick to the nomenclature of 6 entries, i.e. orientation vector + position vector, as Hagen mentioned.

fietew commented 8 years ago

Maybe we should just rotate the coordinate system, i.e. the position of the secondary sources and the line source, such that the line source is always aligned with the z-axis. This could be done inherently within the function, which computes the driving function.

trettberg commented 8 years ago

If you have only one line source, then it is not needed as the array is completely symmetrical

I think this does not hold for discrete arrays.

hagenw commented 8 years ago

At the starting point of this discussion we were talking about 3D spherical arrays only, so I guess in infinite array is not really considered here. But I agree that due to the sampling process of the sphere the symmetry might be lost in the discrete case.

trettberg commented 8 years ago

I think a 3-entry xs that restricts line sources to the z-direction is cumbersome: For a different orientation, the array would have to be rotated manually.

Since all xs use cartesian coordinates up to to now, a line source definition in terms of a point xs(1:3) and a vector along the line xs(4:6) seems most reasonable to me.

The question remains what to do in the 2D case if something else than xs = [x,y,0, 0,0,z] is requested. Projection or error?

hagenw commented 8 years ago

I would say we use now xs for line sources with 6 entries, the first three for the position and the last three for the orientation as proposed.

I prepared the WFS monochromatic driving functions for this. @trettberg could you start implementing the proposed solution for WFS in driving_function_mono_wfs_ls(). Everything is prepared and the driving function is expecting a xs with 6 entries (but it is not checked for the correct size yet). For the 2D and 2.5D case I propose that we do an automatic projection and raise a warning if we had to do this. There remains only one question for the 2D and 2.5D case where I'm not sure what are the consequences. The secondary source selection happens independently from the driving functions and in the 2D and 2.5D case the xs vector with the first three entries without projection is used. So I guess we have to integrate the projection there too, or maybe all together at an earlier stage. It's too late now to think clearly ;)

@narahahn could you implement your proposed solution for NFC-HOA?

narahahn commented 8 years ago

Yes, I will implement the NFC-HOA driving function for arbitrary line sources.

trettberg commented 8 years ago

WFS line source should be okay now. (To avoid code duplication, it might be desirable to handle the 2D case with the 3D case. But for now they are left separated.)

For easier visual inspection, here's a planar array:

conf = SFS_config();

%% construct a square array in the y=0.5 plane
conf.secondary_sources.geometry = 'line';
conf.secondary_sources.number = 31;
x0_line = secondary_source_positions(conf);
M = size(x0_line,1);
dx = abs(x0_line(2,1) - x0_line(1,1))
x0 = repmat(x0_line,[M,1]);
for z = 1:M
    x0((z-1)*M+1:z*M,3) = (z-1)*dx;
end
x0(:,2) = 0.5;
conf.secondary_sources.x0 = x0;
conf.secondary_sources.geometry = 'custom';
conf.secondary_sources.number = 31^2;

%%
conf.dimension = '3D';
conf.usetapwin = 0;
xs = [0,2,0,0,0,1];
f = 1000;
sound_field_mono_wfs([-2,2],[-3,1],0,xs,'ls',f,conf);
sound_field_mono_wfs(0,[-3,1],[-0.5,3.5],xs,'ls',f,conf); 

vls_top vls_side

narahahn commented 8 years ago

Now virtual line sources with arbitrary alignment can be synthesized using NFC-HOA.

SFS_start;
conf = SFS_config;
conf.dimension = '3D';
conf.secondary_sources.number = 169;
conf.secondary_sources.geometry = 'sphere';
conf.resolution = 100;
conf.plot.normalisation = 'center';
X = randi([-1000 1000],125000,1)/2000;
Y = randi([-1000 1000],125000,1)/2000;
Z = randi([-1000 1000],125000,1)/2000;

% vertical line source
xs = [0 1.7 0, ...  % position
      0 0 1];       % orientation
src = 'ls';
f = 750;
sound_field_mono_nfchoa(X,Y,Z,xs,src,f,conf);
% print('-dpng','linesource_vertical')

% horizontal line source
xs = [1.7 0 0, ...  % position
       0 1 0];      % orientation
src = 'ls';
f = 750;
sound_field_mono_nfchoa(X,Y,Z,xs,src,f,conf);
% print('-dpng','linesource_horizontal')

% tilted line source
xs = [-2 -2 0, ...  % position
       1 1 1];      % orientation
src = 'ls';
f = 750;
sound_field_mono_nfchoa(X,Y,Z,xs,src,f,conf);
% print('-dpng','linesource_tilted')

linesource_vertical linesource_horizontal linesource_tilted

hagenw commented 8 years ago

Nice! I started testing it and the first obvious difference I encountered between WFS and NFC-HOA is the following:

In WFS for 2D and 2.5D we restrict the orientation of the line source to be [0 0 1] for all cases. For NFC-HOA you are allowed to use arbitrary orientations. Are the calculations for these orientations correct in NFC-HOA? And if so, would be nice to have that also for WFS? Here are a few examples:

conf = SFS_config;
conf.plot.normalisation = 'center';
sound_field_mono_wfs([-2 2],[-2 2],0,[0 2.5 0 0 0 1],'ls',1000,conf);

wfs_ls

sound_field_mono_nfchoa([-2 2],[-2 2],0,[0 2.5 0 0 1 1],'ls',1000,conf);

nfchoa_ls_yz

sound_field_mono_nfchoa([-2 2],[-2 2],0,[0 2.5 0 1 0 1],'ls',1000,conf);

nfchoa_ls_xz

sound_field_mono_nfchoa([-2 2],[-2 2],0,[0 2.5 0 1 1 0],'ls',1000,conf);

nfchoa_ls_xy

narahahn commented 8 years ago

To be honest, I was concentrating too much on 3D cases and forgot to take care of 2D and 2.5D synthesis. I would say a virtual line source always has to be parallel to the z-axis in 2D and 2.5D NFC-HOA. I will take care of this problem.

hagenw commented 8 years ago

No problem, you could do it exactly like @trettberg did for the WFS line source

narahahn commented 8 years ago

2D and 2.5D NFC-HOA now use cylindrical coordinate representation of line source position xs and secondary source positions x00. Only 3D NFC-HOA uses the spherical coordinate system, and applies rotation to xs and x00.

hagenw commented 8 years ago

Perfect, now we have the same behavior for WFS and NFC-HOA. I made a few more updates:

1) You can now use a [1x3] position vector in the 2D or 2.5D case 2) I implemented an additional function get_position_and_orientation_ls(xs,conf) that handles all this and returns warning messages if you use a xs with the wrong size. 3) I cleaned up driving_function_mono_wfs_ls and driving_function_mono_nfchoa_ls to use only 5 input args as all the other driving functions (the splitting of xs is performed inside the driving functions)

There is only one position in the code left that is not so nice yet, see secondary_source_selection. If we want to use get_position_and_orientation_ls there we would have to add conf as additional parameter to secondary_source_selection. I'm not sure if we should do that.

Beside this small question everything should be fine now.

trettberg commented 8 years ago

This raises a somewhat abstruse issue for the 2D and 2.5D case:

The secondary source selection uses xs as is, while the driving function uses only the z component. This is not a problem unless the array itself has "wrong" normal vectors, that is x0(:,6) ~= 0. The result is most likely wrong anyway, but in this case it is "inconsistently wrong".

Personally I don't think that's an issue and would leave it this way.

But if this is undesirable, conf could be passed to secondary_source_selection.

hagenw commented 8 years ago

I also don't think that this is an issue. I added a NOTE to the corresponding section in the secondary_source_selection() function, that is stating what you are saying, so if someone really has a problem, that might be a hint what could be wrong.

I'm going to merge this pull request now.