annotate simulateBinauralSignals.m @ 12:c8b0cf96ea44 jabuilder_int

Supply dirname and filename separately (use dirname for temp files too)
author Chris Cannam
date Fri, 28 Feb 2014 13:41:31 +0000
parents 894f57cf9962
children f0e00c212071
rev   line source
tp@8 1 function simulateBinauralSignals(inputstruct)
tp@8 2 %Creates .wav file of 2sec long binaural signals for specific board dimensions and gaussian white noise stimulus
tp@8 3 %
tp@8 4 % INPUTS:
tp@8 5 % The input must be a structure with fields:
tp@8 6 % .dist (1st input argument) is the distance in meters
tp@8 7 % .azim (2nd input argument) is the azimuth in degrees (0 means straight ahead, positive angles are left and negative
tp@8 8 % are right)
tp@8 9 % .orient (3rd input argument) must be either 'horz' or 'angled' corresponding to flat and angled descriptions in
tp@8 10 % Papadopoulos et al. BSPC 2011.
Chris@10 11 % .dirweight (4th input argument) must be a nonnegative real scalar determining what is the relative weight of the
tp@8 12 % emission path to the echo path (i.e. due to directivity focus in the frontal direction of the source, the emission
tp@8 13 % which is directed upwards and backwards in our specific geometry is significantly attenuated, typically by factor in
tp@8 14 % the vicinity of 0.2)
Chris@12 15 % .outdir (5th input argument) must be the directory in which the wave file
Chris@10 16 % is to be written. It may be an absolute path, or relative to the current
Chris@12 17 % directory. Temporary files will be written in the same directory.
Chris@12 18 % .outname (6th input argument) must be the name of the wave file to write, within the outdir, without the .wav suffix (which will be added).
tp@8 19 %
tp@8 20
tp@8 21 %% Internal workings description
tp@8 22 %
tp@8 23 % Center of spherical coordinates system is taken to be the center of head. The azimuth, elevation and distance
tp@8 24 % coordinates are as in matlabs sph2cart function (azimuth and elevation are angular displacements from the positive
tp@8 25 % x-axis and from the x-y plane, respectively) with positive x axis taken to be extending to the right of the head from
tp@8 26 % top view, positive y axis to be extending forward of the head in top view and positive z axis to be extending upwards
tp@8 27 % in top view.
tp@8 28 %
tp@8 29 % Board dimensions are defined as
tp@8 30 % params.board_size_x (width in meters for the 'center' orientation of Papadopoulos et al. BSPC 2011)
tp@8 31 % params.board_size_y (depth in meters for the 'center' orientation of Papadopoulos et al. BSPC 2011)
tp@8 32 % params.board_size_z (height in meters for the 'center' orientation of Papadopoulos et al. BSPC 2011)
tp@8 33 %
tp@8 34 % Board center position is defined as
tp@8 35 % params.board_distance (distance in meters from coords origin to center of board following coordinate system described
tp@8 36 % above), can be row vector.
tp@8 37 % params.board_azim (azimuth in radians of the center of the board following coordinate system described above),
tp@8 38 % can be row vector.
tp@8 39 % params.board_elev (elevation in radians of the center of the board following coordinate system described above),
tp@8 40 % must be scalar
tp@8 41 %
tp@8 42 % params.board_orientation scalar or 1x2 cell with elements 'horz' or/and 'angled'
tp@8 43 % Board is taken to always be vertically positioned (i.e. with its width-height plane vertical to the y coordinate) and
tp@8 44 % two cases of orientation are considered: horizontal and angled corresponding to flat and angled descriptions in
tp@8 45 % Papadopoulos et al. BSPC 2011.
tp@8 46 %
tp@8 47 % params.source_down non-negative scalar in meters
tp@8 48 % params.source_front non-negative scalar in meters
tp@8 49 % The source is assumed to always be in front of the chest and below the head. (params.source_down and
tp@8 50 % params.source_front cannot both be 0)
tp@8 51 %
tp@8 52 %
tp@8 53 % params.horz_disamb string which can be either 'BSPC2011' or 'collocated'. If equal to 'BSPC2011' then board distance
tp@8 54 % for the horizontal (flat) case is as described in Papadopoulos et al. BSPC 2011, i.e. the board
tp@8 55 % distance is the distance between the centre of the head and the PLANE OF THE BOARD.
tp@8 56 % Alternatively, in the 'collocated' case, the board distance in the horizontal (flat) case is taken
tp@8 57 % as the distance between the centre of the head and the centre of the board
tp@8 58 %
tp@8 59 % NOTE: in the 'BSPC2011' case of params.horz_disamb, it is easy to see that the geometry is ill-specified for board
tp@8 60 % positions far away from the median plane.
tp@8 61 %
tp@8 62 % OUTPUTS:
tp@8 63 %
tp@8 64 % --- simulation_data is a structure with the following fields:
tp@8 65 % - simulation_data.echo is a cell of dimensions
tp@8 66 % length(params.board_dist) x length(params.board_azim) x length(params.board_orientation)
tp@8 67 % each element of which is a 2-row matrix with the left (top row) and right (bottom row) ear responses corresponding the
tp@8 68 % echo only.
tp@8 69 %
tp@8 70 % - simulation_data.emission is a cell of dimensions
tp@8 71 % length(params.board_dist) x length(params.board_azim) x length(params.board_orientation)
tp@8 72 % each element of which is a 2-row matrix with the left (top row) and right (bottom row) ear responses corresponding the
tp@8 73 % direct source-to-receiver path only. (NOTE: source term (binaural_irs_emission) does not need to be computed for each
tp@8 74 % different board distance/azimuth/orientation as it is the same irs but containing a different number of trailing zero
tp@8 75 % samples. I include this redundancy because it simplified the computation a bit and also because this way the emission
tp@8 76 % part is always equal in length with the corresponding echo part and can be added easier)
tp@8 77 %
tp@8 78 % Adding any given
tp@8 79 % directivity_weighting * simulation_data.emission{ii,jj,kk}(1,:) + simulation_data.echo{ii,jj,kk}(1,:)
tp@8 80 % for any given ii, jj, kk will give the total left ear IR and the same for right ear by
tp@8 81 % directivity_weighting * simulation_data.emission{ii,jj,kk}(2,:) + simulation_data.echo{ii,jj,kk}(2,:)
tp@8 82 %
tp@8 83 % - simulation_data.params is the stucture params described above
tp@8 84 % - simulation_data.board_coords is an array of dimensions
tp@8 85 % 8 x 3 x length(params.board_dist) x length(params.board_azim) x length(params.board_orientation)
tp@8 86 % containing the x y z coordinates (2nd dimension) of the 8 edges (1st dimension) of the board geometries for different
tp@8 87 % board distances, azimuths and orientations.
tp@8 88 % - simulation_data.azerr and simulation_data.elerr are arrays of dimensions
tp@8 89 % 2 x 1+length(params.board_azim))
tp@8 90 % which contain the error (in degrees) between the azimuth and elevation respectively of the HRTFs that are used (as
tp@8 91 % existing in the CIPIC spherical grid) and the actual board center azimuth and elevation.
tp@8 92 %
tp@8 93 %
tp@8 94 %
tp@8 95 % DEVELOPMENT NOTES
tp@8 96 %
tp@8 97 % TODO: include case of multiple boards and of non-vertically oriented boards (i.e. all cases of pitch, roll, yaw for
tp@8 98 % board orientation)
tp@8 99 %
tp@8 100 % TODO: include geometrical description for all possible positions of the source
tp@8 101 %
tp@8 102 % TODO: include validateattributes for all parameters
tp@8 103 %
tp@8 104 % TODO: include parameter controls for specorder (now set to 1), difforder (now set to 1), elemsize (now set to [1]) and
tp@8 105 % nedgesubs (now set to 2)
tp@8 106 %
tp@8 107 %
tp@8 108
tp@8 109 %% Take inputs args from input structure
tp@8 110 dist = inputstruct.dist;
tp@8 111 azim = inputstruct.azim;
tp@8 112 orient = inputstruct.orient;
tp@8 113 dirweight = inputstruct.dirweight;
Chris@12 114 outdir = inputstruct.outdir;
Chris@12 115 outname = inputstruct.outname;
tp@8 116
tp@8 117 %% Validate attributes
tp@8 118 validateattributes(dist,{'double'},{'scalar','>',0})
tp@8 119 validateattributes(azim,{'double'},{'scalar','<=',90,'>=',-90})
tp@8 120 validateattributes(orient,{'char'},{'nonempty'})
tp@8 121 validateattributes(dirweight,{'double'},{'scalar','>',0})
Chris@12 122 validateattributes(outdir,{'char'},{'nonempty'})
Chris@12 123 validateattributes(outname,{'char'},{'nonempty'})
tp@8 124
tp@8 125 %% Computation parameters (Some fixed, some taken from input arguments)
tp@8 126 params.board_size_x = .55;
tp@8 127 params.board_size_y = .02;
tp@8 128 params.board_size_z = .55;
tp@8 129
tp@8 130 params.board_azim = mod(90+azim,360)*pi/180;
tp@8 131 params.board_elev = 0*pi/180;
tp@8 132 params.board_dist = dist;
tp@8 133 %
tp@8 134 % params.board_azim = mod(90+[-17 17],360)*pi/180; % corresponds to a board 17degress to the right and a board 17
tp@8 135 % degrees to the left. The elements of the vector ([-17 17] in this example) must be in the range (-180,180] and are
tp@8 136 % converted by the line in this example to the coordinate system described in the help preample.
tp@8 137 %
tp@8 138 % params.board_elev = 10*pi/180; % corresponds to a board 10 degrees above the azimuthal plane. The value (0 in this
tp@8 139 % example) must be in the range [-90,90] and is converted by the line in this example to the coordinate system described
tp@8 140 % in the help preample.
tp@8 141 %
tp@8 142 % params.board_dist is in meters and it can be a vector of (strictly positive) distances as needed
tp@8 143
tp@8 144 params.board_orientation = {validatestring(orient,{'horz','angled'})};
tp@8 145
tp@8 146 params.source_down = 0.25; % Take the source to always be directly below the chin.
tp@8 147 params.source_front = 0.05; % Take the source to always be directly in front of chest.
tp@8 148
tp@8 149 params.Fs = 44100;
tp@8 150 params.Cair = 344;
tp@8 151 params.Rhoair = 1.21;
tp@8 152 params.WavDurationSec = 2;
tp@8 153 params.WavScaling = 0.1;
tp@8 154 params.dirweight = dirweight;
tp@8 155
tp@8 156 params.horz_disamb = 'BSPC2011';
Chris@12 157 params.wavfilename = [outdir filesep outname '.wav']
tp@8 158
tp@8 159 %% Compute free field (no head) IRs
tp@8 160
tp@8 161 temp_edges = [
tp@8 162 +params.board_size_x/2 +params.board_size_y/2 +params.board_size_z/2
tp@8 163 -params.board_size_x/2 +params.board_size_y/2 +params.board_size_z/2
tp@8 164 -params.board_size_x/2 -params.board_size_y/2 +params.board_size_z/2
tp@8 165 +params.board_size_x/2 -params.board_size_y/2 +params.board_size_z/2
tp@8 166 +params.board_size_x/2 +params.board_size_y/2 -params.board_size_z/2
tp@8 167 -params.board_size_x/2 +params.board_size_y/2 -params.board_size_z/2
tp@8 168 -params.board_size_x/2 -params.board_size_y/2 -params.board_size_z/2
tp@8 169 +params.board_size_x/2 -params.board_size_y/2 -params.board_size_z/2
tp@8 170 ];
tp@8 171
tp@8 172 FFresp{length(params.board_dist),length(params.board_azim),length(params.board_orientation)} = [];
tp@8 173 binaural_irs_echo{length(params.board_dist),length(params.board_azim),length(params.board_orientation)} = [];
tp@8 174 binaural_irs_emission{length(params.board_dist),length(params.board_azim),length(params.board_orientation)} = [];
tp@8 175 % NOTE: in the above initialisation the source term (binaural_irs_emission) does not need to be computed for each
tp@8 176 % different board distance/azimuth/orientation as it is the same. I include this redundancy so that the emission
tp@8 177 % binaural irs that I compute each time in in a few lines are correct, i.e. I can check that all the binaural responses
tp@8 178 % in the binaural_irs_emission cell are equal.
tp@8 179 board_coords(8,3,length(params.board_dist),length(params.board_azim),length(params.board_orientation)) = 0;
tp@8 180
tp@8 181
tp@8 182 geom.Fs = params.Fs;
tp@8 183 geom.Cair = params.Cair;
tp@8 184 geom.Rhoair = params.Rhoair;
tp@8 185
tp@8 186 geom.source_position = [0 params.source_front -params.source_down];
tp@8 187
tp@8 188 for ii = 1:length(params.board_dist)
tp@8 189 for jj = 1:length(params.board_azim)
tp@8 190 for kk = 1:length(params.board_orientation)
tp@8 191
tp@8 192 if strcmp(params.board_orientation{kk},'angled')
tp@8 193 theta_angled = params.board_azim(jj) - pi/2;
tp@8 194 Rot_mat = [
tp@8 195 cos(theta_angled) -sin(theta_angled) 0
tp@8 196 sin(theta_angled) cos(theta_angled) 0
tp@8 197 0 0 1
tp@8 198 ];
tp@8 199 temp2_edges = ( Rot_mat * temp_edges.' ) .' ;
tp@8 200 % for the rotation matrix see http://en.wikipedia.org/wiki/Rotation_matrix
tp@8 201 [trans_x, trans_y, trans_z] = sph2cart(params.board_azim(jj),params.board_elev,params.board_dist(ii));
tp@8 202 geom.scatterer_edges = ...
tp@8 203 temp2_edges + repmat([trans_x, trans_y, trans_z],8,1);
tp@8 204 board_coords(:,:,ii,jj,kk) = geom.scatterer_edges;
tp@8 205 elseif strcmp(params.board_orientation{kk},'horz')
tp@8 206 temp2_edges = temp_edges;
tp@8 207 if strcmp(params.horz_disamb,'collocated')
tp@8 208 [trans_x, trans_y, trans_z] = sph2cart(params.board_azim(jj),params.board_elev,params.board_dist(ii));
tp@8 209 elseif strcmp(params.horz_disamb,'BSPC2011')
tp@8 210 [trans_x, trans_y, trans_z] = sph2cart(...
tp@8 211 params.board_azim(jj),...
tp@8 212 params.board_elev,...
tp@8 213 params.board_dist(ii)/abs(cos(params.board_azim(jj)-pi/2)));
tp@8 214 else
tp@8 215 error('params.horz_disamb must be set to either ''BSPC2011'' or ''collocated''')
tp@8 216 end
tp@8 217 geom.scatterer_edges = ...
tp@8 218 temp2_edges + repmat([trans_x, trans_y, trans_z],8,1);
tp@8 219 board_coords(:,:,ii,jj,kk) = geom.scatterer_edges;
tp@8 220 end
tp@8 221
tp@8 222 FFresp(ii,jj,kk) = edhrir_single_cuboid(geom);
tp@8 223
tp@8 224 end
tp@8 225 end
tp@8 226 end
tp@8 227
tp@8 228 %% Compute binaural IRs
tp@8 229
tp@8 230 temp = load('hrir_final.mat'); %This is subject_165 CIPIC data
tp@8 231 h3D_lear = temp.hrir_l;
tp@8 232 h3D_rear = temp.hrir_r;
tp@8 233 clear temp
tp@8 234
tp@8 235 cipic_source_az = 0*180/pi;
tp@8 236 cipic_source_el = atan(-params.source_down/params.source_front)*180/pi;
tp@8 237 [source_lear_ir, azerr(1,1+length(params.board_azim)), elerr(1,1+length(params.board_azim))] = ...
tp@8 238 getNearestUCDpulse(cipic_source_az,cipic_source_el,h3D_lear);
tp@8 239 [source_rear_ir, azerr(2,1+length(params.board_azim)), elerr(2,1+length(params.board_azim))] = ...
tp@8 240 getNearestUCDpulse(cipic_source_az,cipic_source_el,h3D_rear);
tp@8 241
tp@8 242 % NOTE: in the following computation the source term (binaural_irs_emission) does not need to be computed for each
tp@8 243 % different board distance/azimuth/orientation as it is the same. I include the redundancy as a check that the geometry
tp@8 244 % modelling and computations are correct, i.e. I can check that all the binaural responses in the binaural_irs_emission
tp@8 245 % cell are equal.
tp@8 246
tp@8 247 for ii = 1:length(params.board_azim)
tp@8 248
tp@8 249 cipic_board_az = 90-params.board_azim(ii)*180/pi;
tp@8 250 cipic_board_el = params.board_elev*180/pi;
tp@8 251 [lear_ir, azerr(1,ii), elerr(1,ii)] = getNearestUCDpulse(cipic_board_az,cipic_board_el,h3D_lear);
tp@8 252 [rear_ir, azerr(2,ii), elerr(2,ii)] = getNearestUCDpulse(cipic_board_az,cipic_board_el,h3D_rear);
tp@8 253
tp@8 254 for jj = 1:length(params.board_dist)
tp@8 255 for kk = 1:length(params.board_orientation)
tp@8 256
tp@8 257 binaural_irs_emission{jj,ii,kk}(1,:) = fftconv(source_lear_ir,FFresp{jj,ii,kk}(2,:)); %source term
tp@8 258 binaural_irs_emission{jj,ii,kk}(2,:) = fftconv(source_rear_ir,FFresp{jj,ii,kk}(2,:)); %source term
tp@8 259
tp@8 260 binaural_irs_echo{jj,ii,kk}(1,:) = fftconv(lear_ir,FFresp{jj,ii,kk}(1,:)+FFresp{jj,ii,kk}(3,:));
tp@8 261 %board echo term
tp@8 262 binaural_irs_echo{jj,ii,kk}(2,:) = fftconv(rear_ir,FFresp{jj,ii,kk}(1,:)+FFresp{jj,ii,kk}(3,:));
tp@8 263 %board echo term
tp@8 264
tp@8 265 end
tp@8 266 end
tp@8 267 end
tp@8 268
tp@8 269 simulation_data.echo = binaural_irs_echo;
tp@8 270 simulation_data.emission =binaural_irs_emission;
tp@8 271 simulation_data.params = params;
tp@8 272 simulation_data.board_coords = board_coords;
tp@8 273 simulation_data.azerr = azerr;
tp@8 274 simulation_data.elerr = elerr;
tp@8 275
tp@8 276 %% Compute binaural signals and save binaural wav file
tp@8 277
tp@8 278 binaural_ir = params.dirweight*simulation_data.emission{1,1,1} + simulation_data.echo{1,1,1};
tp@8 279 stim = params.WavScaling*randn(1,params.WavDurationSec*params.Fs);
tp@8 280 temp = [fftfilt(binaural_ir(1,:),stim);fftfilt(binaural_ir(2,:),stim)].';
tp@8 281 if max(max(abs(temp))) > 1
tp@8 282 warning('wavfile clipped')
tp@8 283 end
tp@8 284 audiowrite(params.wavfilename,temp,params.Fs);
tp@8 285
tp@8 286 %% Subfunctions
tp@8 287
tp@8 288 function [pulse, azerr, elerr] = getNearestUCDpulse(azimuth,elevation,h3D)
tp@8 289 azimuth = pvaldeg(azimuth);
tp@8 290 elevation = pvaldeg(elevation);
tp@8 291
tp@8 292 elmax = 50;
tp@8 293 elindices = 1:elmax;
tp@8 294 elevations = -45 + 5.625*(elindices - 1);
tp@8 295 el = round((elevation + 45)/5.625 + 1);
tp@8 296 el = max(el,1);
tp@8 297 el = min(el,elmax);
tp@8 298 elerr = pvaldeg(elevation - elevations(el));
tp@8 299
tp@8 300 azimuths = [-80 -65 -55 -45:5:45 55 65 80];
tp@8 301 [azerr, az] = min(abs(pvaldeg(abs(azimuths - azimuth))));
tp@8 302
tp@8 303 pulse = squeeze(h3D(az,el,:));
tp@8 304
tp@8 305 function angle = pvaldeg(angle)
tp@8 306 dtr = pi/180;
tp@8 307 angle = atan2(sin(angle*dtr),cos(angle*dtr))/dtr;
tp@8 308 if angle < - 90
tp@8 309 angle = angle + 360;
tp@8 310 end
tp@8 311
tp@8 312 function out=fftconv(in1,in2)
tp@8 313 %
tp@8 314 % Computes the convolution output out of the input vectors in1 and in2
tp@8 315 % either with time-domain convolution (as implemented by conv) or by
tp@8 316 % frequency-domain filtering (as implemented by zero-padded fftfilt).
tp@8 317 %
tp@8 318 % out=fftconv(in1,in2)
tp@8 319 %
tp@8 320 in1=in1(:).';in2=in2(:).';
tp@8 321
tp@8 322 if (length(in1)>100 && length(in2)>100)
tp@8 323 if length(in1)>=length(in2)
tp@8 324 out=fftfilt(in2,[in1 zeros(1,length(in2)-1)]);
tp@8 325 else
tp@8 326 out=fftfilt(in1,[in2 zeros(1,length(in1)-1)]);
tp@8 327 end
tp@8 328 else
tp@8 329 out=conv(in1,in2);
tp@8 330 end
tp@8 331
tp@8 332 function ir_matrix=edhrir_single_cuboid(geom)
tp@8 333 %
tp@8 334 % Matrix of irs for a single cuboid scatterer using EDTB
tp@8 335 %
tp@8 336 % Works for external geometry. Definition of corners and planes in the created CAD file should be pointing outwards (in
tp@8 337 % cartesian coordinates as defined below).
tp@8 338 %
tp@8 339 % x coordinate (increasing to right in top view, right hand thumb)
tp@8 340 % y coordinate (increasing in front in top view, right hand index)
tp@8 341 % z coordinate (increasing upwards in top view, right hand middle)
tp@8 342 %
tp@8 343 % For more details about geometry description see the main help preample.
tp@8 344 %
tp@8 345 % geom input parameter should be a structure with the following fields:
tp@8 346 %
tp@8 347 % geom.scatterer_edges is a 8x3 matrix with elements:
tp@8 348 % x y z coordinates of back right top edge (point 1)
tp@8 349 % x y z coordinates of back left top edge (point 2)
tp@8 350 % x y z coordinates of front left top edge (point 3)
tp@8 351 % x y z coordinates of front right top edge (point 4)
tp@8 352 % x y z coordinates of back right bottom edge (point 1)
tp@8 353 % x y z coordinates of back left bottom edge (point 2)
tp@8 354 % x y z coordinates of front left bottom edge (point 3)
tp@8 355 % x y z coordinates of front right bottom edge (point 4)
tp@8 356 %
tp@8 357 % (or any sequence of rotations of a cuboid with edges as above)
tp@8 358 %
tp@8 359 % geom.source_position (Single) source coordinates in cartesian system defined 1x3 positive real vector. (Single)
tp@8 360 % receiver always taken to be at coordinates origin (0,0,0)
tp@8 361 %
tp@8 362 % geom.Fs
tp@8 363 % geom.Cair
tp@8 364 % geom.Rhoair
tp@8 365 %
tp@8 366
tp@8 367 %% 1
Chris@12 368 temp_filename=[outdir filesep 'a' num2str(now*1e12,'%-24.0f')];
Chris@12 369 cad_filename=[temp_filename '.cad']
tp@8 370
Chris@12 371 fid=fopen(cad_filename,'w');
tp@8 372 % TODO add onCleanup to fclose this file
tp@8 373 fprintf(fid,'%%CORNERS\n\n');
tp@8 374 fprintf(fid,'%.0f %9.6f %9.6f %9.6f\n',...
tp@8 375 1, geom.scatterer_edges(1,1), geom.scatterer_edges(1,2), geom.scatterer_edges(1,3),...
tp@8 376 2, geom.scatterer_edges(2,1), geom.scatterer_edges(2,2), geom.scatterer_edges(2,3),...
tp@8 377 3, geom.scatterer_edges(3,1), geom.scatterer_edges(3,2), geom.scatterer_edges(3,3),...
tp@8 378 4, geom.scatterer_edges(4,1), geom.scatterer_edges(4,2), geom.scatterer_edges(4,3),...
tp@8 379 5, geom.scatterer_edges(5,1), geom.scatterer_edges(5,2), geom.scatterer_edges(5,3),...
tp@8 380 6, geom.scatterer_edges(6,1), geom.scatterer_edges(6,2), geom.scatterer_edges(6,3),...
tp@8 381 7, geom.scatterer_edges(7,1), geom.scatterer_edges(7,2), geom.scatterer_edges(7,3),...
tp@8 382 8, geom.scatterer_edges(8,1), geom.scatterer_edges(8,2), geom.scatterer_edges(8,3));
tp@8 383 fprintf(fid,'\n%%PLANES\n');
tp@8 384 fprintf(fid,'\n1 / /RIGID\n1 2 3 4\n');
tp@8 385 fprintf(fid,'\n2 / /RIGID\n5 8 7 6\n');
tp@8 386 fprintf(fid,'\n3 / /RIGID\n1 4 8 5\n');
tp@8 387 fprintf(fid,'\n4 / /RIGID\n1 5 6 2\n');
tp@8 388 fprintf(fid,'\n5 / /RIGID\n2 6 7 3\n');
tp@8 389 fprintf(fid,'\n6 / /RIGID\n7 8 4 3\n');
tp@8 390 fprintf(fid,'\n%%EOF');
tp@8 391 fclose(fid);
tp@8 392
Chris@12 393 setup_filename = [temp_filename '_setup.m']
luis@9 394
luis@9 395 fid=fopen(setup_filename,'wt');
tp@8 396 % TODO add onCleanup to fclose this file
tp@8 397 fprintf(fid,'\n global FSAMP CAIR RHOAIR SHOWTEXT');
tp@8 398 fprintf(fid,['\n FSAMP = ' num2str(geom.Fs) ';']);
tp@8 399 fprintf(fid,['\n CAIR = ' num2str(geom.Cair) ';']);
tp@8 400 fprintf(fid,['\n RHOAIR = ' num2str(geom.Rhoair) ';']);
tp@8 401 fprintf(fid,'\n SHOWTEXT = 0;');
tp@8 402 fprintf(fid,'\n SUPPRESSFILES = 0;');
tp@8 403 temp = strrep([cd filesep],'\','\\');
tp@8 404 fprintf(fid,['\n Filepath=''''''' temp ''''''';']);
tp@8 405 fprintf(fid,['\n Filestem=''' temp_filename ''';']);
tp@8 406 fprintf(fid,['\n CADfile=''' temp temp_filename '.cad'';']);
tp@8 407 fprintf(fid,'\n open_or_closed_model = ''open'';');
tp@8 408 fprintf(fid,'\n int_or_ext_model = ''ext'';');
tp@8 409 fprintf(fid,'\n EDcalcmethod = ''n'';');
tp@8 410 fprintf(fid,'\n directsound = 1;');
tp@8 411 fprintf(fid,'\n specorder = 1;');
tp@8 412 fprintf(fid,'\n difforder = 1;');
tp@8 413 fprintf(fid,'\n elemsize = [1];');
tp@8 414 fprintf(fid,'\n nedgesubs = 2;');
tp@8 415 fprintf(fid,'\n calcpaths = 1;');
tp@8 416 fprintf(fid,'\n calcirs = 1;');
tp@8 417 fprintf(fid,'\n sources=[');
tp@8 418 for n=1:1
tp@8 419 fprintf(fid,['\n' num2str(geom.source_position(1)) ' ' ...
tp@8 420 num2str(geom.source_position(2)) ' ' ...
tp@8 421 num2str(geom.source_position(3))]);
tp@8 422 end
tp@8 423 fprintf(fid,'\n ];');
tp@8 424 fprintf(fid,'\n receivers=[');
tp@8 425 for n=1:1
tp@8 426 fprintf(fid,'\n 0 0 0');
tp@8 427 end
tp@8 428 fprintf(fid,'\n ];');
tp@8 429 fprintf(fid,'\n skipcorners = 1000000;');
tp@8 430 fprintf(fid,'\n Rstart = 0;');
tp@8 431
tp@8 432 fclose(fid);
tp@8 433
tp@8 434 pause(1);
tp@8 435
luis@9 436 [~, ir_matrix]=myver_edtb(setup_filename);
tp@8 437
Chris@12 438 delete([cad_filename]);
Chris@12 439 delete([setup_filename]);
tp@8 440
tp@8 441 function [ir,varargout]=myver_edtb(EDsetupfile)
tp@8 442 % implements the computation of EDToolbox (by Peter Svensson) with a front-end
tp@8 443 % designed for my needs.
tp@8 444 %
tp@8 445 % Takes one input which a setup file as specified by Svensson and gives
tp@8 446 % either one vector output (which is the irtot output of Svensson's implementation for
tp@8 447 % the first source and first receiver in the input "EDsetupfile" setup file) or
tp@8 448 % two outputs, the first as above and the second being a {NxM} cell (N the number
tp@8 449 % of sources and M the number of receivers) each element of which is a 4xL matrix
tp@8 450 % with its 4 rows being the irdiff, irdirect, irgeom and irtot outputs of Svensson's
tp@8 451 % computation for the corresponding source and receiver.
tp@8 452 %
tp@8 453 % The code deletes all other .mat files created by Svensson's
tp@8 454 % implementation.
tp@8 455 %
tp@8 456 % [ir ir_all_data]=myver_edtb(EDsetupfile);
tp@8 457
tp@8 458 %keep record of files in the current directory before computation
tp@8 459 dir_bef=dir;
tp@8 460 ir=1;
tp@8 461
luis@9 462 disp(['Will call' EDsetupfile])
luis@9 463
tp@8 464 %run computation
tp@8 465 EDB1main(EDsetupfile);
tp@8 466
tp@8 467 %get files list in the current directory after computation
tp@8 468 dir_aft=dir;
tp@8 469
tp@8 470 %get all genuine files (excluding other directories) in current directory
tp@8 471 %after computation
tp@8 472 k=1;
tp@8 473 for n=1:size(dir_aft,1)
tp@8 474 if(~dir_aft(n).isdir)
tp@8 475 names_aft{k}=dir_aft(n).name;k=k+1; %#ok<AGROW>
tp@8 476 end
tp@8 477 end
tp@8 478
tp@8 479 %get all genuine files (excluding other directories) in current directory
tp@8 480 %before computation
tp@8 481 k=1;
tp@8 482 for n=1:size(dir_bef,1)
tp@8 483 if(~dir_bef(n).isdir)
tp@8 484 names_bef{k}=dir_bef(n).name;k=k+1; %#ok<AGROW>
tp@8 485 end
tp@8 486 end
tp@8 487
tp@8 488 %get irtot for 1st source 1st receiver and delete files created by
tp@8 489 %computation.
tp@8 490 % for n=1:length(names_aft)
tp@8 491 % if ~strcmp(names_aft(n),names_bef)
tp@8 492 % if ~isempty(strfind(names_aft{n},'_1_1_ir.mat'))
tp@8 493 % temp=load(names_aft{n});
tp@8 494 % ir=full(temp.irtot);
tp@8 495 % clear temp
tp@8 496 % end
tp@8 497 % delete(names_aft{n})
tp@8 498 % end
tp@8 499 % end
tp@8 500 for n=1:length(names_aft)
tp@8 501 if ~strcmp(names_aft(n),names_bef)
tp@8 502 if ~isempty(strfind(names_aft{n},'_1_1_ir.mat'))
tp@8 503 temp=load(names_aft{n});
tp@8 504 ir=full(temp.irtot);
tp@8 505 clear temp
tp@8 506 end
tp@8 507 if nargout>1
tp@8 508 if ~isempty(strfind(names_aft{n},'_ir.mat'))
tp@8 509 temp=load(names_aft{n});
tp@8 510 temp2=regexp(regexp(names_aft{n},'_\d*_\d*_','match'),'\d*','match');
tp@8 511 temp3{str2double(temp2{1}(1)),str2double(temp2{1}(2))}(4,:)=full(temp.irtot); %#ok<AGROW>
tp@8 512 temp3{str2double(temp2{1}(1)),str2double(temp2{1}(2))}(1,:)=full(temp.irdiff); %#ok<AGROW>
tp@8 513 temp3{str2double(temp2{1}(1)),str2double(temp2{1}(2))}(2,:)=full(temp.irdirect); %#ok<AGROW>
tp@8 514 temp3{str2double(temp2{1}(1)),str2double(temp2{1}(2))}(3,:)=full(temp.irgeom); %#ok<AGROW>
tp@8 515 clear temp temp2
tp@8 516 end
tp@8 517 end
tp@8 518 delete(names_aft{n})
tp@8 519 end
tp@8 520 end
tp@8 521 if nargout>1
tp@8 522 varargout(1)={temp3};
tp@8 523 end
tp@8 524