0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124 function [interpHRTFset, HRTF_L_ip, HRTF_R_ip] = supdeq_interpHRTF(HRTFset, ipSamplingGrid, ppMethod, ipMethod, mc, headRadius, tikhEps, limitMC, mcKnee, mcMinPhase, limFade)
0125
0126
0127 if nargin < 3 || isempty(ppMethod)
0128 ppMethod = 'SUpDEq';
0129 end
0130
0131 if nargin < 4 || isempty(ipMethod)
0132 ipMethod = 'SH';
0133 end
0134
0135 if nargin < 5 || isempty(mc)
0136 mc = inf;
0137 end
0138
0139 if nargin < 6 || isempty(headRadius)
0140 headRadius = 0.0875;
0141 end
0142
0143 if nargin < 7 || isempty(tikhEps)
0144 tikhEps = 0;
0145 end
0146
0147 if nargin < 8 || isempty(limitMC)
0148 limitMC = true;
0149 end
0150
0151 if nargin < 9 || isempty(mcKnee)
0152 mcKnee = 0;
0153 end
0154
0155 if nargin < 10 || isempty(mcMinPhase)
0156 mcMinPhase = true;
0157 end
0158
0159 if nargin < 11 || isempty(limFade)
0160 limFade = 'fadeDown';
0161 end
0162
0163
0164
0165 fs = HRTFset.f(end)*2;
0166 f = HRTFset.f;
0167 NFFT = length(HRTFset.f)*2-2;
0168 samplingGrid = HRTFset.samplingGrid;
0169 HRTF_L = HRTFset.HRTF_L;
0170 HRTF_R = HRTFset.HRTF_R;
0171 c = 343;
0172
0173
0174
0175 HRIR_L = AKsingle2bothSidedSpectrum(HRTF_L.');
0176 HRIR_R = AKsingle2bothSidedSpectrum(HRTF_R.');
0177
0178 HRIR_L = real(ifft(HRIR_L));
0179 HRIR_R = real(ifft(HRIR_R));
0180 hrirLength = size(HRIR_L,1)/HRTFset.FFToversize;
0181
0182
0183
0184 switch ppMethod
0185 case 'SUpDEq'
0186 disp('Preprocessing: SUpDEq')
0187
0188
0189
0190 eqDataset = supdeq_getEqDataset(44,2*headRadius,NFFT,fs);
0191
0192
0193 [eqTF_L,eqTF_R] = supdeq_getEqTF(eqDataset,samplingGrid,'DEG',2,'ak',false);
0194 pHRTF_L = HRTF_L./eqTF_L;
0195 pHRTF_R = HRTF_R./eqTF_R;
0196
0197 case 'SUpDEq_Lim'
0198 disp('Preprocessing: SUpDEq_Lim')
0199
0200
0201
0202 eqDataset = supdeq_getEqDataset(44,2*headRadius,NFFT,fs);
0203
0204
0205
0206 eqDataset = supdeq_limitEqDataset(eqDataset,HRTFset.Nmax,headRadius);
0207
0208
0209 [eqTF_L,eqTF_R] = supdeq_getEqTF(eqDataset,samplingGrid,'DEG',2,'ak',false);
0210 pHRTF_L = HRTF_L./eqTF_L;
0211 pHRTF_R = HRTF_R./eqTF_R;
0212
0213 case 'SUpDEq_AP'
0214 disp('Preprocessing: SUpDEq_AP')
0215
0216
0217
0218 eqDataset = supdeq_getEqDataset(44,2*headRadius,NFFT,fs);
0219
0220
0221 [eqTF_L,eqTF_R] = supdeq_getEqTF(eqDataset,samplingGrid,'DEG',2,'ak',true);
0222 pHRTF_L = HRTF_L./eqTF_L;
0223 pHRTF_R = HRTF_R./eqTF_R;
0224
0225 case 'SUpDEq_Lim_AP'
0226 disp('Preprocessing: SUpDEq_Lim_AP')
0227
0228
0229
0230 eqDataset = supdeq_getEqDataset(44,2*headRadius,NFFT,fs);
0231
0232
0233
0234 eqDataset = supdeq_limitEqDataset(eqDataset,HRTFset.Nmax,headRadius);
0235
0236
0237 [eqTF_L,eqTF_R] = supdeq_getEqTF(eqDataset,samplingGrid,'DEG',2,'ak',true);
0238 pHRTF_L = HRTF_L./eqTF_L;
0239 pHRTF_R = HRTF_R./eqTF_R;
0240
0241 case 'PC'
0242 disp('Preprocessing: PC')
0243
0244
0245
0246 k = 2*pi*f/c; k = k.';
0247
0248
0249 sg = samplingGrid * pi / 180;
0250
0251
0252 cosThetaL = cos(sg(:,2)')*cos(pi/2) + sin(sg(:,2)')*sin(pi/2) .* cos(sg(:,1)'-pi/2);
0253 phaseCorL = exp(-1j*headRadius * k .* cosThetaL);
0254 cosThetaR = cos(sg(:,2)')*cos(pi/2) + sin(sg(:,2)')*sin(pi/2) .* cos(sg(:,1)'+pi/2);
0255 phaseCorR = exp(-1j*headRadius * k .* cosThetaR);
0256
0257
0258 pHRTF_L = HRTF_L .* phaseCorL.';
0259 pHRTF_R = HRTF_R .* phaseCorR.';
0260
0261 case 'OBTA'
0262 disp('Preprocessing: OBTA')
0263
0264
0265
0266 toa_L = AKonsetDetect(HRIR_L, 10, -20, 'rel', [3e3 fs]);
0267 toa_R = AKonsetDetect(HRIR_R, 10, -20, 'rel', [3e3 fs]);
0268
0269
0270 pHRIR_L = AKfractionalDelayCyclic(HRIR_L, -toa_L);
0271 pHRIR_R = AKfractionalDelayCyclic(HRIR_R, -toa_R);
0272
0273
0274 pHRTF_L = AKboth2singleSidedSpectrum (fft(pHRIR_L)).';
0275 pHRTF_R = AKboth2singleSidedSpectrum (fft(pHRIR_R)).';
0276
0277 case 'MagPhase'
0278 disp('Preprocessing: MagPhase')
0279
0280 pHRTF_L = abs(HRTF_L);
0281 pHRTF_R = abs(HRTF_R);
0282 pHRTF_L_ph = unwrap(angle(HRTF_L).').';
0283 pHRTF_R_ph = unwrap(angle(HRTF_R).').';
0284
0285 case 'None'
0286 disp('Preprocessing: None')
0287
0288
0289 pHRTF_L = HRTF_L;
0290 pHRTF_R = HRTF_R;
0291 end
0292
0293
0294 interpHRTFset.p.pHRTF_L = pHRTF_L;
0295 interpHRTFset.p.pHRTF_R = pHRTF_R;
0296 if strcmp(ppMethod,'OBTA')
0297 interpHRTFset.p.toa_L = toa_L;
0298 interpHRTFset.p.toa_R = toa_R;
0299 end
0300 if strcmp(ppMethod,'MagPhase')
0301 interpHRTFset.p.pHRTF_L_ph = pHRTF_L_ph;
0302 interpHRTFset.p.pHRTF_R_ph = pHRTF_R_ph;
0303 end
0304
0305
0306
0307 switch ipMethod
0308 case 'SH'
0309 disp('HRTF Interpolation: SH')
0310
0311
0312
0313 pHRTF_L_nm = AKsht(pHRTF_L.',false,samplingGrid,HRTFset.Nmax,'complex',fs,false,'complex',tikhEps);
0314 pHRTF_R_nm = AKsht(pHRTF_R.',false,samplingGrid,HRTFset.Nmax,'complex',fs,false,'complex',tikhEps);
0315
0316
0317 pHRTF_L_ip = AKisht(pHRTF_L_nm,false,ipSamplingGrid(:,1:2),'complex').';
0318 pHRTF_R_ip = AKisht(pHRTF_R_nm,false,ipSamplingGrid(:,1:2),'complex').';
0319
0320
0321 if strcmp(ppMethod,'OBTA')
0322
0323
0324
0325 toa_L_nm = AKsht(toa_L,false,samplingGrid,HRTFset.Nmax,'complex',fs,false,'real',tikhEps);
0326 toa_R_nm = AKsht(toa_R,false,samplingGrid,HRTFset.Nmax,'complex',fs,false,'real',tikhEps);
0327
0328
0329 toa_L_ip = AKisht(toa_L_nm, false, ipSamplingGrid(:,1:2), 'complex', false, false, 'real');
0330 toa_R_ip = AKisht(toa_R_nm, false, ipSamplingGrid(:,1:2), 'complex', false, false, 'real');
0331
0332 end
0333
0334
0335 if strcmp(ppMethod,'MagPhase')
0336
0337
0338
0339 pHRTF_L_ph_nm = AKsht(pHRTF_L_ph.',false,samplingGrid,HRTFset.Nmax,'complex',fs,false,'complex',tikhEps);
0340 pHRTF_R_ph_nm = AKsht(pHRTF_R_ph.',false,samplingGrid,HRTFset.Nmax,'complex',fs,false,'complex',tikhEps);
0341
0342
0343 pHRTF_L_ph_ip = AKisht(pHRTF_L_ph_nm,false,ipSamplingGrid(:,1:2),'complex').';
0344 pHRTF_R_ph_ip = AKisht(pHRTF_R_ph_nm,false,ipSamplingGrid(:,1:2),'complex').';
0345
0346 end
0347
0348 case 'NN'
0349 disp('HRTF Interpolation: NN')
0350
0351
0352 [samplingGrid_cart(:,1), samplingGrid_cart(:,2), samplingGrid_cart(:,3)] = sph2cart(samplingGrid(:,1)/360*2*pi, pi/2-samplingGrid(:,2)/360*2*pi,1);
0353 [ipSamplingGrid_cart(:,1), ipSamplingGrid_cart(:,2), ipSamplingGrid_cart(:,3)] = sph2cart(ipSamplingGrid(:,1)/360*2*pi, pi/2-ipSamplingGrid(:,2)/360*2*pi,1);
0354
0355
0356 pHRTF_L_ip = zeros(length(ipSamplingGrid),length(f));
0357 pHRTF_R_ip = zeros(length(ipSamplingGrid),length(f));
0358
0359 for nPoint = 1:size(ipSamplingGrid,1)
0360
0361 [idx_voronoi,w_voronoi] = findvoronoi(samplingGrid_cart,ipSamplingGrid_cart(nPoint,:));
0362
0363 for n = 1:length(idx_voronoi)
0364 pHRTF_L_ip(nPoint,:) = pHRTF_L_ip(nPoint,:) + w_voronoi(n)*pHRTF_L(idx_voronoi(n),:);
0365 pHRTF_R_ip(nPoint,:) = pHRTF_R_ip(nPoint,:) + w_voronoi(n)*pHRTF_R(idx_voronoi(n),:);
0366 end
0367 end
0368
0369
0370 if strcmp(ppMethod,'OBTA')
0371
0372 toa_L_ip = zeros(1,length(ipSamplingGrid));
0373 toa_R_ip = zeros(1,length(ipSamplingGrid));
0374
0375 for nPoint = 1:size(ipSamplingGrid,1)
0376
0377 [idx_voronoi,w_voronoi] = findvoronoi(samplingGrid_cart,ipSamplingGrid_cart(nPoint,:));
0378
0379 for n = 1:length(idx_voronoi)
0380 toa_L_ip(1,nPoint) = toa_L_ip(1,nPoint) + w_voronoi(n)*toa_L(1,idx_voronoi(n));
0381 toa_R_ip(1,nPoint) = toa_R_ip(1,nPoint) + w_voronoi(n)*toa_R(1,idx_voronoi(n));
0382 end
0383 end
0384 end
0385
0386
0387 if strcmp(ppMethod,'MagPhase')
0388
0389 pHRTF_L_ph_ip = zeros(length(ipSamplingGrid),length(f));
0390 pHRTF_R_ph_ip = zeros(length(ipSamplingGrid),length(f));
0391
0392 for nPoint = 1:size(ipSamplingGrid,1)
0393
0394 [idx_voronoi,w_voronoi] = findvoronoi(samplingGrid_cart,ipSamplingGrid_cart(nPoint,:));
0395
0396 for n = 1:length(idx_voronoi)
0397 pHRTF_L_ph_ip(nPoint,:) = pHRTF_L_ph_ip(nPoint,:) + w_voronoi(n)*pHRTF_L_ph(idx_voronoi(n),:);
0398 pHRTF_R_ph_ip(nPoint,:) = pHRTF_R_ph_ip(nPoint,:) + w_voronoi(n)*pHRTF_R_ph(idx_voronoi(n),:);
0399 end
0400 end
0401 end
0402
0403
0404 case 'Bary'
0405 disp('HRTF Interpolation: Bary')
0406
0407
0408 [samplingGrid_cart(:,1), samplingGrid_cart(:,2), samplingGrid_cart(:,3)] = sph2cart(samplingGrid(:,1)/360*2*pi, pi/2-samplingGrid(:,2)/360*2*pi,1);
0409 [ipSamplingGrid_cart(:,1), ipSamplingGrid_cart(:,2), ipSamplingGrid_cart(:,3)] = sph2cart(ipSamplingGrid(:,1)/360*2*pi, pi/2-ipSamplingGrid(:,2)/360*2*pi,1);
0410
0411
0412 convHullIdx = convhull(samplingGrid_cart(:,1), samplingGrid_cart(:,2), samplingGrid_cart(:,3), 'simplify', true);
0413
0414
0415 convHullHRTF_A = samplingGrid_cart(convHullIdx(:,1),:);
0416 convHullHRTF_B = samplingGrid_cart(convHullIdx(:,2),:);
0417 convHullHRTF_C = samplingGrid_cart(convHullIdx(:,3),:);
0418
0419
0420
0421
0422
0423 orig = [0 0 0];
0424 pHRTF_L_ip = zeros(length(ipSamplingGrid),length(f));
0425 pHRTF_R_ip = zeros(length(ipSamplingGrid),length(f));
0426
0427 for nPoint = 1:size(ipSamplingGrid,1)
0428
0429 [intersect, ~, u, v, ~] = TriangleRayIntersection(orig, ipSamplingGrid_cart(nPoint,:), convHullHRTF_A, convHullHRTF_B, convHullHRTF_C, 'border', 'inclusive');
0430 intersectIdx = find(intersect, 1, 'first');
0431 u = u(intersectIdx); v = v(intersectIdx); w = 1-u-v;
0432 bw = [w u v];
0433 idx_bw = convHullIdx(intersectIdx,:);
0434
0435 for n = 1:3
0436 pHRTF_L_ip(nPoint,:) = pHRTF_L_ip(nPoint,:) + bw(n)*pHRTF_L(idx_bw(n),:);
0437 pHRTF_R_ip(nPoint,:) = pHRTF_R_ip(nPoint,:) + bw(n)*pHRTF_R(idx_bw(n),:);
0438 end
0439 end
0440
0441
0442 if strcmp(ppMethod,'OBTA')
0443
0444 toa_L_ip = zeros(1,length(ipSamplingGrid));
0445 toa_R_ip = zeros(1,length(ipSamplingGrid));
0446
0447 for nPoint = 1:size(ipSamplingGrid,1)
0448
0449 [intersect, ~, u, v, ~] = TriangleRayIntersection(orig, ipSamplingGrid_cart(nPoint,:), convHullHRTF_A, convHullHRTF_B, convHullHRTF_C, 'border', 'inclusive');
0450 intersectIdx = find(intersect, 1, 'first');
0451 u = u(intersectIdx); v = v(intersectIdx); w = 1-u-v;
0452 bw = [w u v];
0453 idx_bw = convHullIdx(intersectIdx,:);
0454
0455 for n = 1:3
0456 toa_L_ip(1,nPoint) = toa_L_ip(1,nPoint) + bw(n)*toa_L(1,idx_bw(n));
0457 toa_R_ip(1,nPoint) = toa_R_ip(1,nPoint) + bw(n)*toa_R(1,idx_bw(n));
0458 end
0459 end
0460 end
0461
0462
0463 if strcmp(ppMethod,'MagPhase')
0464
0465 pHRTF_L_ph_ip = zeros(length(ipSamplingGrid),length(f));
0466 pHRTF_R_ph_ip = zeros(length(ipSamplingGrid),length(f));
0467
0468 for nPoint = 1:size(ipSamplingGrid,1)
0469
0470 [intersect, ~, u, v, ~] = TriangleRayIntersection(orig, ipSamplingGrid_cart(nPoint,:), convHullHRTF_A, convHullHRTF_B, convHullHRTF_C, 'border', 'inclusive');
0471 intersectIdx = find(intersect, 1, 'first');
0472 u = u(intersectIdx); v = v(intersectIdx); w = 1-u-v;
0473 bw = [w u v];
0474 idx_bw = convHullIdx(intersectIdx,:);
0475
0476 for n = 1:3
0477 pHRTF_L_ph_ip(nPoint,:) = pHRTF_L_ph_ip(nPoint,:) + bw(n)*pHRTF_L_ph(idx_bw(n),:);
0478 pHRTF_R_ph_ip(nPoint,:) = pHRTF_R_ph_ip(nPoint,:) + bw(n)*pHRTF_R_ph(idx_bw(n),:);
0479 end
0480 end
0481 end
0482
0483 end
0484
0485
0486 interpHRTFset.p.pHRTF_L_ip = pHRTF_L_ip;
0487 interpHRTFset.p.pHRTF_R_ip = pHRTF_R_ip;
0488 if strcmp(ppMethod,'OBTA')
0489 interpHRTFset.p.toa_L_ip = toa_L_ip;
0490 interpHRTFset.p.toa_R_ip = toa_R_ip;
0491 end
0492 if strcmp(ppMethod,'MagPhase')
0493 interpHRTFset.p.pHRTF_L_ph_ip = pHRTF_L_ph_ip;
0494 interpHRTFset.p.pHRTF_R_ph_ip = pHRTF_R_ph_ip;
0495 end
0496
0497
0498
0499 switch ppMethod
0500 case 'SUpDEq'
0501 disp('Postprocessing: SUpDEq')
0502
0503
0504
0505 [deqTF_L,deqTF_R] = supdeq_getEqTF(eqDataset,ipSamplingGrid,'DEG',2,'ak',false);
0506
0507
0508 HRTF_L_ip = pHRTF_L_ip.*deqTF_L;
0509 HRTF_R_ip = pHRTF_R_ip.*deqTF_R;
0510
0511 case 'SUpDEq_Lim'
0512 disp('Postprocessing: SUpDEq_Lim')
0513
0514
0515
0516 [deqTF_L,deqTF_R] = supdeq_getEqTF(eqDataset,ipSamplingGrid,'DEG',2,'ak',false);
0517
0518
0519 HRTF_L_ip = pHRTF_L_ip.*deqTF_L;
0520 HRTF_R_ip = pHRTF_R_ip.*deqTF_R;
0521
0522 case 'SUpDEq_AP'
0523 disp('Postprocessing: SUpDEq_AP')
0524
0525
0526
0527 [deqTF_L,deqTF_R] = supdeq_getEqTF(eqDataset,ipSamplingGrid,'DEG',2,'ak',true);
0528
0529
0530 HRTF_L_ip = pHRTF_L_ip.*deqTF_L;
0531 HRTF_R_ip = pHRTF_R_ip.*deqTF_R;
0532
0533 case 'SUpDEq_Lim_AP'
0534 disp('Postprocessing: SUpDEq_Lim_AP')
0535
0536
0537
0538 [deqTF_L,deqTF_R] = supdeq_getEqTF(eqDataset,ipSamplingGrid,'DEG',2,'ak',true);
0539
0540
0541 HRTF_L_ip = pHRTF_L_ip.*deqTF_L;
0542 HRTF_R_ip = pHRTF_R_ip.*deqTF_R;
0543
0544 case 'PC'
0545 disp('Postprocessing: PC')
0546
0547
0548
0549 sg = ipSamplingGrid * pi / 180;
0550
0551
0552 cosThetaL = cos(sg(:,2)')*cos(pi/2) + sin(sg(:,2)')*sin(pi/2) .* cos(sg(:,1)'-pi/2);
0553
0554 phaseCorL = exp(1j*headRadius * k .* cosThetaL);
0555 cosThetaR = cos(sg(:,2)')*cos(pi/2) + sin(sg(:,2)')*sin(pi/2) .* cos(sg(:,1)'+pi/2);
0556
0557 phaseCorR = exp(1j*headRadius * k .* cosThetaR);
0558
0559
0560 HRTF_L_ip = pHRTF_L_ip .* phaseCorL.';
0561 HRTF_R_ip = pHRTF_R_ip .* phaseCorR.';
0562
0563 case 'OBTA'
0564 disp('Postprocessing: OBTA')
0565
0566
0567
0568 pHRIR_L_ip = AKsingle2bothSidedSpectrum(pHRTF_L_ip.');
0569 pHRIR_R_ip = AKsingle2bothSidedSpectrum(pHRTF_R_ip.');
0570 pHRIR_L_ip = real(ifft(pHRIR_L_ip));
0571 pHRIR_R_ip = real(ifft(pHRIR_R_ip));
0572
0573
0574 HRIR_L_ip = AKfractionalDelayCyclic(pHRIR_L_ip, toa_L_ip);
0575 HRIR_R_ip = AKfractionalDelayCyclic(pHRIR_R_ip, toa_R_ip);
0576
0577
0578 HRTF_L_ip = AKboth2singleSidedSpectrum(fft(HRIR_L_ip)).';
0579 HRTF_R_ip = AKboth2singleSidedSpectrum(fft(HRIR_R_ip)).';
0580
0581 case 'MagPhase'
0582 disp('Postprocessing: MagPhase')
0583
0584
0585 HRTF_L_ip = pHRTF_L_ip.*exp(1i*pHRTF_L_ph_ip);
0586 HRTF_R_ip = pHRTF_R_ip.*exp(1i*pHRTF_R_ph_ip);
0587
0588 case 'None'
0589 disp('Postprocessing: None')
0590
0591
0592 HRTF_L_ip = pHRTF_L_ip;
0593 HRTF_R_ip = pHRTF_R_ip;
0594 end
0595
0596
0597
0598 if ~isnan(mc)
0599
0600 disp('MC postprocessing');
0601
0602
0603 interpHRTFset.p.HRTF_L_ip_noMC = HRTF_L_ip;
0604 interpHRTFset.p.HRTF_R_ip_noMC = HRTF_R_ip;
0605
0606
0607 fLowErb = 50;
0608 [cl,ferb] = AKerbErrorPersistent(HRIR_L(1:hrirLength,:),AKdirac(hrirLength),[fLowErb fs/2],fs);
0609 [cr] = AKerbErrorPersistent(HRIR_R(1:hrirLength,:),AKdirac(hrirLength),[fLowErb fs/2],fs);
0610
0611
0612 switch ipMethod
0613 case 'SH'
0614
0615
0616
0617 cl_nm = AKsht(cl, false, samplingGrid, HRTFset.Nmax, 'complex', fs, false, 'real',tikhEps);
0618 cr_nm = AKsht(cr, false, samplingGrid, HRTFset.Nmax, 'complex', fs, false, 'real',tikhEps);
0619
0620
0621 cl_ip = AKisht(cl_nm, false, ipSamplingGrid(:,1:2), 'complex', false, false, 'real');
0622 cr_ip = AKisht(cr_nm, false, ipSamplingGrid(:,1:2), 'complex', false, false, 'real');
0623
0624 case 'NN'
0625
0626
0627 [samplingGrid_cart(:,1), samplingGrid_cart(:,2), samplingGrid_cart(:,3)] = sph2cart(samplingGrid(:,1)/360*2*pi, pi/2-samplingGrid(:,2)/360*2*pi,1);
0628 [ipSamplingGrid_cart(:,1), ipSamplingGrid_cart(:,2), ipSamplingGrid_cart(:,3)] = sph2cart(ipSamplingGrid(:,1)/360*2*pi, pi/2-ipSamplingGrid(:,2)/360*2*pi,1);
0629
0630
0631 cl_ip = zeros(length(ferb),length(ipSamplingGrid));
0632 cr_ip = zeros(length(ferb),length(ipSamplingGrid));
0633
0634 for nPoint = 1:size(ipSamplingGrid,1)
0635
0636 [idx_voronoi,w_voronoi] = findvoronoi(samplingGrid_cart,ipSamplingGrid_cart(nPoint,:));
0637
0638 for n = 1:length(idx_voronoi)
0639 cl_ip(:,nPoint) = cl_ip(:,nPoint) + w_voronoi(n)*cl(:,idx_voronoi(n));
0640 cr_ip(:,nPoint) = cr_ip(:,nPoint) + w_voronoi(n)*cr(:,idx_voronoi(n));
0641 end
0642 end
0643
0644 case 'Bary'
0645
0646
0647 [samplingGrid_cart(:,1), samplingGrid_cart(:,2), samplingGrid_cart(:,3)] = sph2cart(samplingGrid(:,1)/360*2*pi, pi/2-samplingGrid(:,2)/360*2*pi,1);
0648 [ipSamplingGrid_cart(:,1), ipSamplingGrid_cart(:,2), ipSamplingGrid_cart(:,3)] = sph2cart(ipSamplingGrid(:,1)/360*2*pi, pi/2-ipSamplingGrid(:,2)/360*2*pi,1);
0649
0650
0651 convHullIdx = convhull(samplingGrid_cart(:,1), samplingGrid_cart(:,2), samplingGrid_cart(:,3), 'simplify', true);
0652
0653
0654 convHullHRTF_A = samplingGrid_cart(convHullIdx(:,1),:);
0655 convHullHRTF_B = samplingGrid_cart(convHullIdx(:,2),:);
0656 convHullHRTF_C = samplingGrid_cart(convHullIdx(:,3),:);
0657
0658
0659
0660
0661
0662 orig = [0 0 0];
0663 cl_ip = zeros(length(ferb),length(ipSamplingGrid));
0664 cr_ip = zeros(length(ferb),length(ipSamplingGrid));
0665
0666 for nPoint = 1:size(ipSamplingGrid,1)
0667
0668 [intersect, ~, u, v, ~] = TriangleRayIntersection(orig, ipSamplingGrid_cart(nPoint,:), convHullHRTF_A, convHullHRTF_B, convHullHRTF_C, 'border', 'inclusive');
0669 intersectIdx = find(intersect, 1, 'first');
0670 u = u(intersectIdx); v = v(intersectIdx); w = 1-u-v;
0671 bw = [w u v];
0672 idx_bw = convHullIdx(intersectIdx,:);
0673
0674 for n = 1:3
0675 cl_ip(:,nPoint) = cl_ip(:,nPoint) + bw(n)*cl(:,idx_bw(n));
0676 cr_ip(:,nPoint) = cr_ip(:,nPoint) + bw(n)*cr(:,idx_bw(n));
0677 end
0678 end
0679 end
0680
0681
0682 c_ip(:,:,1) = cl_ip;
0683 c_ip(:,:,2) = cr_ip;
0684
0685
0686 HRIR_L_ip = AKsingle2bothSidedSpectrum(HRTF_L_ip.');
0687 HRIR_R_ip = AKsingle2bothSidedSpectrum(HRTF_R_ip.');
0688 HRIR_ip(:,:,1) = real(ifft(HRIR_L_ip));
0689 HRIR_ip(:,:,2) = real(ifft(HRIR_R_ip));
0690 HRIR_ip = HRIR_ip(1:hrirLength,:,:);
0691
0692 c_hrir_ip = AKerbErrorPersistent(HRIR_ip,AKdirac(size(HRIR_ip,1)),[fLowErb fs/2],fs);
0693
0694
0695 corrFilt = c_ip-c_hrir_ip;
0696
0697 corrFilt_l = AKinterpolateSpectrum( squeeze(corrFilt(:,:,1)), ferb, NFFT, {'nearest' 'spline' 'nearest'}, fs);
0698 corrFilt_r = AKinterpolateSpectrum( squeeze(corrFilt(:,:,2)), ferb, NFFT, {'nearest' 'spline' 'nearest'}, fs);
0699
0700
0701 if limitMC
0702
0703
0704 fA = HRTFset.Nmax*c/2/pi/headRadius;
0705
0706 disp(['MC postprocessing limited to f > fA, with fA = ',num2str(round(fA,2)),'Hz']);
0707
0708 if strcmp(limFade,'fadeDown')
0709
0710 disp('MC fade downwards');
0711
0712
0713 fAt = fA/2^(1/3);
0714
0715
0716 [~,fA_bin] = min(abs(HRTFset.f-fA));
0717 [~,fAt_bin] = min(abs(HRTFset.f-fAt));
0718 ramp = linspace(0,1,abs(fA_bin-fAt_bin)+1);
0719 corrFilt_l(1:fAt_bin-1,:) = 0;
0720 corrFilt_l(fAt_bin:fA_bin,:) = corrFilt_l(fAt_bin:fA_bin,:).*ramp.';
0721 corrFilt_r(1:fAt_bin-1,:) = 0;
0722 corrFilt_r(fAt_bin:fA_bin,:) = corrFilt_r(fAt_bin:fA_bin,:).*ramp.';
0723 end
0724
0725 if strcmp(limFade,'fadeUp')
0726
0727 disp('MC fade upwards');
0728
0729
0730 fAt = fA*2^(1/3);
0731
0732
0733 [~,fA_bin] = min(abs(HRTFset.f-fA));
0734 [~,fAt_bin] = min(abs(HRTFset.f-fAt));
0735 ramp = linspace(0,1,abs(fAt_bin-fA_bin)+1);
0736 corrFilt_l(1:fA_bin-1,:) = 0;
0737 corrFilt_l(fA_bin:fAt_bin,:) = corrFilt_l(fA_bin:fAt_bin,:).*ramp.';
0738 corrFilt_r(1:fA_bin-1,:) = 0;
0739 corrFilt_r(fA_bin:fAt_bin,:) = corrFilt_r(fA_bin:fAt_bin,:).*ramp.';
0740 end
0741
0742 end
0743
0744
0745 corrFilt_l = 10.^(corrFilt_l/20);
0746 corrFilt_r = 10.^(corrFilt_r/20);
0747
0748 if ~isinf(mc)
0749
0750 disp(['MC maximum boost: ',num2str(mc),'dB'])
0751 disp(['MC soft-limiting knee: ',num2str(mcKnee),'dB'])
0752
0753 corrFilt_l_lim = AKsoftLimit(corrFilt_l, mc, mcKnee,[0 fs/2], fs, true);
0754 corrFilt_r_lim = AKsoftLimit(corrFilt_r, mc, mcKnee,[0 fs/2], fs, true);
0755
0756 else
0757
0758 disp('MC maximum boost: inf')
0759
0760 corrFilt_l_lim = corrFilt_l;
0761 corrFilt_r_lim = corrFilt_r;
0762
0763 end
0764
0765
0766
0767 if mcMinPhase
0768
0769 disp('MC phase: minimum');
0770
0771 corrFilt_l_lim = AKsingle2bothSidedSpectrum(corrFilt_l_lim);
0772 corrFilt_r_lim = AKsingle2bothSidedSpectrum(corrFilt_r_lim);
0773
0774 corrFilt_l_lim = real(ifft(corrFilt_l_lim));
0775 corrFilt_r_lim = real(ifft(corrFilt_r_lim));
0776
0777 corrFilt_l_lim = AKphaseManipulation(corrFilt_l_lim,fs,'min',1,0);
0778 corrFilt_r_lim = AKphaseManipulation(corrFilt_r_lim,fs,'min',1,0);
0779
0780
0781 corrFilt_l_lim = AKboth2singleSidedSpectrum(fft(corrFilt_l_lim));
0782 corrFilt_r_lim = AKboth2singleSidedSpectrum(fft(corrFilt_r_lim));
0783
0784 else
0785
0786 disp('MC phase: zero');
0787
0788 end
0789
0790
0791 corrFilt_lim(:,:,1) = corrFilt_l_lim;
0792 corrFilt_lim(:,:,2) = corrFilt_r_lim;
0793
0794
0795 interpHRTFset.p.corrFilt_lim = corrFilt_lim;
0796
0797
0798 HRTF_L_ip = HRTF_L_ip.*corrFilt_lim(:,:,1).';
0799 HRTF_R_ip = HRTF_R_ip.*corrFilt_lim(:,:,2).';
0800
0801 end
0802
0803
0804
0805
0806 HRIR_L_ip = AKsingle2bothSidedSpectrum(HRTF_L_ip.');
0807 HRIR_R_ip = AKsingle2bothSidedSpectrum(HRTF_R_ip.');
0808 HRIR_L_ip = real(ifft(HRIR_L_ip));
0809 HRIR_R_ip = real(ifft(HRIR_R_ip));
0810
0811 HRIR_L_ip = HRIR_L_ip(1:hrirLength,:);
0812 HRIR_R_ip = HRIR_R_ip(1:hrirLength,:);
0813
0814 interpHRTFset.HRTF_L = HRTF_L_ip;
0815 interpHRTFset.HRTF_R = HRTF_R_ip;
0816 interpHRTFset.HRIR_L = HRIR_L_ip;
0817 interpHRTFset.HRIR_R = HRIR_R_ip;
0818 interpHRTFset.f = HRTFset.f;
0819 interpHRTFset.fs = fs;
0820 interpHRTFset.FFToversize = HRTFset.FFToversize;
0821 interpHRTFset.samplingGrid = ipSamplingGrid;
0822 interpHRTFset.headRadius = headRadius;
0823 interpHRTFset.ppMethod = ppMethod;
0824 interpHRTFset.ipMethod = ipMethod;
0825 interpHRTFset.headRadius = headRadius;
0826 if tikhEps ~= 0
0827 interpHRTFset.tikhEps = tikhEps;
0828 end
0829 if ~isnan(mc)
0830 interpHRTFset.mc = mc;
0831 interpHRTFset.mcKnee = mcKnee;
0832 interpHRTFset.mcMinPhase = mcMinPhase;
0833 if limitMC
0834 interpHRTFset.limitMC = 1;
0835 interpHRTFset.limitMC_fA = fA;
0836 interpHRTFset.limitMC_fAt = fAt;
0837 interpHRTFset.limitMC_fade = limFade;
0838 end
0839 end
0840 disp('Done...');
0841
0842 end
0843