sfstoolbox / sfs-matlab

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

Relative Source position for SimpleFreeFieldHRIR in get_ir #161

Closed fietew closed 7 years ago

fietew commented 7 years ago

Regarding https://github.com/sfstoolbox/sfs-matlab/blob/master/SFS_ir/get_ir.m#L123-L133

xs = xs-X+X_sofa;

This first makes xs relative to X by xs-X but then adds X_sofa. If X_sofa is not [0 0 0], then this is not the source position relative to the listener, anymore. The combination of head orientation and relative source position is not correct for this case:

% Combine head orientation and desired direction of source (see note above)
[xs(1),xs(2),xs(3)] = cart2sph(xs(1),xs(2),xs(3));
xs(1) = correct_azimuth(xs(1)-head_orientation(1));
xs(2) = correct_elevation(xs(2)-head_orientation(2));
[xs(1),xs(2),xs(3)] = sph2cart(xs(1),xs(2),xs(3));

Furthermore, functions like findconvexcone assume the x0 and xs to be centered around the listener. Fix? X_sofa can be incorporated by applying it to the measured positions x0,

% For SimpleFreeFieldHRIR only the relative position between listener
% position and source position is of relevance.
xs = xs-X;
% Get measured loudspeaker positions
x0 = sofa_get_secondary_sources(header,'cartesian');
x0 = bsxfun(@minus, x0(:,1:3), X_sofa);
hagenw commented 7 years ago

I agree, this is a bug. xs = xs-X+X_sofa only works if we don't use it for calculating the direction from it.

Your second point is not so obvious. Let's assume we had xs = xs-X at the beginning. Would you expect that the following two commands would return different results then?

[idx,weights] = point_selection(x0,xs+X_sofa,conf);
[idx,weights] = point_selection(bsxfun(@minus,x0,X_sofa),xs,conf);
fietew commented 7 years ago

Yes, they will due to the assumptions made by the point selection method.

For findnearestneighbor since does not make a difference, since it is based on metrics for the euclidean space, which are shift invariant. Example: norm(x0 - (xs + X_sofa)) == norm((x0 - X_sofa) - xs)

However, for findconvexcone and the planned Voronoi Interpolation in #151 we assume that x_s and x_0 are somehow centred at the coordinates origin. Example: Assuming an HRIR dataset was recorded on a sphere around X_sofa (which is not [0,0,0]) the points in x_0 do not have the same distance to the coordinates origin (I know this case might be rare, but maybe a coordinate system was chosen during the measurement, where the listener was not at [0,0,0]). Hence, the first function call with findconvexcone as the selection method would yield an error due to https://github.com/sfstoolbox/sfs-matlab/blob/master/SFS_general/findconvexcone.m#L67-L69, which is correct, as this method cannot handle this case without information about the centre of the sphere. The second function call first shifts the points in x_0, so that they are centered around the origin afterwards.

hagenw commented 7 years ago

OK, in this case your proposed solution of x0 = bsxfun(@minus, x0(:,1:3), X_sofa) would fix the problem.

But what happens for off-center measurements. Let's assume the worst case: the measurement was done with a sphere with slightly varying radius centered at [0, 1, 0]. The dummy head (X_sofa) was placed at an off-center position at [1, 1, 0], that would be 1m left of the center of the sphere. I guess in this case we have to adjust x0 by [0, -1, 0] and xs by [1, 0, 0]? And we would have to add an mechanism to first find the center position.

fietew commented 7 years ago

No, that's not how it works. The measurements have been done with X_sofa = [1,1,0] and x0 on a sphere with the center [0, 1, 0]. Hence, the source positions relative to the listener, for which HRIRs are available, are x0 - X_sofa. This is the "database" we have for our interpolation. So we adjust x0 = x0 - X_sofa and xs = xs - X. Now we have both the datapoints x0 and the query point xs relative to the measured and the desired listener position, respectively. Afterwards the point selection has to handle everything else. I can at least say for the Voronoi-Interpolation, that all points will be projected on a unit sphere, so that the point selection is only based on the apparent source azimuth and elevation angle.

hagenw commented 7 years ago

This makes sense. As I don't know any HRTF measurements with off-center dummy head positions its maybe not a big problem that at the moment we cannot handle such a case with findconvexcone. But even better if this will work with the Voronoi-Interpolation.

I created a small pull request including your suggested solution from above: #165