SAF
Loading...
Searching...
No Matches
binauraliser_internal.c
Go to the documentation of this file.
1/*
2 * Copyright 2017-2018 Leo McCormack
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
32
34
35void binauraliser_setCodecStatus(void* const hBin, CODEC_STATUS newStatus)
36{
37 binauraliser_data *pData = (binauraliser_data*)(hBin);
38 if(newStatus==CODEC_STATUS_NOT_INITIALISED){
39 /* Pause until current initialisation is complete */
41 SAF_SLEEP(10);
42 }
43 pData->codecStatus = newStatus;
44}
45
47(
48 void* const hBin,
49 INTERP_MODES mode,
50 float azimuth_deg,
51 float elevation_deg,
52 float_complex h_intrp[HYBRID_BANDS][NUM_EARS]
53)
54{
55 binauraliser_data *pData = (binauraliser_data*)(hBin);
56 int i, band;
57 int aziIndex, elevIndex, N_azi, idx3d;
58 float_complex ipd;
59 float_complex weights_cmplx[3], hrtf_fb3[NUM_EARS][3];
60 float aziRes, elevRes, weights[3], itds3[3], itdInterp;
61 float magnitudes3[HYBRID_BANDS][3][NUM_EARS], magInterp[HYBRID_BANDS][NUM_EARS];
62 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
63
64 /* find closest pre-computed VBAP direction */
65 aziRes = (float)pData->hrtf_vbapTableRes[0];
66 elevRes = (float)pData->hrtf_vbapTableRes[1];
67 N_azi = (int)(360.0f / aziRes + 0.5f) + 1;
68 aziIndex = (int)(matlab_fmodf(azimuth_deg + 180.0f, 360.0f) / aziRes + 0.5f);
69 elevIndex = (int)((elevation_deg + 90.0f) / elevRes + 0.5f);
70 idx3d = elevIndex * N_azi + aziIndex;
71 for (i = 0; i < 3; i++)
72 weights[i] = pData->hrtf_vbap_gtableComp[idx3d*3 + i];
73
74 switch(mode){
75 case INTERP_TRI:
76 for (i = 0; i < 3; i++)
77 weights_cmplx[i] = cmplxf(weights[i], 0.0f);
78 for (band = 0; band < HYBRID_BANDS; band++) {
79 for (i = 0; i < 3; i++){
80 hrtf_fb3[0][i] = pData->hrtf_fb[band*NUM_EARS*(pData->N_hrir_dirs) + 0*(pData->N_hrir_dirs) + pData->hrtf_vbap_gtableIdx[idx3d*3+i]];
81 hrtf_fb3[1][i] = pData->hrtf_fb[band*NUM_EARS*(pData->N_hrir_dirs) + 1*(pData->N_hrir_dirs) + pData->hrtf_vbap_gtableIdx[idx3d*3+i]];
82 }
83 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, NUM_EARS, 1, 3, &calpha,
84 (float_complex*)hrtf_fb3, 3,
85 (float_complex*)weights_cmplx, 1, &cbeta,
86 (float_complex*)h_intrp[band], 1);
87 }
88 break;
89
90 case INTERP_TRI_PS:
91 /* retrieve the 3 itds and hrtf magnitudes */
92 for (i = 0; i < 3; i++) {
93 itds3[i] = pData->itds_s[pData->hrtf_vbap_gtableIdx[idx3d*3+i]];
94 for (band = 0; band < HYBRID_BANDS; band++) {
95 magnitudes3[band][i][0] = pData->hrtf_fb_mag[band*NUM_EARS*(pData->N_hrir_dirs) + 0*(pData->N_hrir_dirs) + pData->hrtf_vbap_gtableIdx[idx3d*3+i]];
96 magnitudes3[band][i][1] = pData->hrtf_fb_mag[band*NUM_EARS*(pData->N_hrir_dirs) + 1*(pData->N_hrir_dirs) + pData->hrtf_vbap_gtableIdx[idx3d*3+i]];
97 }
98 }
99
100 /* interpolate hrtf magnitudes and itd */
101 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 1, 1, 3, 1.0f,
102 (float*)weights, 3,
103 (float*)itds3, 1, 0.0f,
104 &itdInterp, 1);
105 for (band = 0; band < HYBRID_BANDS; band++) {
106 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 1, 2, 3, 1.0f,
107 (float*)weights, 3,
108 (float*)magnitudes3[band], 2, 0.0f,
109 (float*)magInterp[band], 2);
110 }
111
112 /* introduce interaural phase difference */
113 for (band = 0; band < HYBRID_BANDS; band++) {
114 if(pData->freqVector[band]<1.5e3f)
115 ipd = cmplxf(0.0f, (matlab_fmodf(2.0f*SAF_PI*(pData->freqVector[band]) * itdInterp + SAF_PI, 2.0f*SAF_PI) - SAF_PI)/2.0f);
116 else
117 ipd = cmplxf(0.0f, 0.0f);
118 h_intrp[band][0] = crmulf(cexpf(ipd), magInterp[band][0]);
119 h_intrp[band][1] = crmulf(conjf(cexpf(ipd)), magInterp[band][1]);
120 }
121 break;
122 }
123}
124
126{
127 binauraliser_data *pData = (binauraliser_data*)(hBin);
128 int i, new_len;
129 float* hrtf_vbap_gtable, *hrirs_resampled;//, *hrir_dirs_rad;
130#ifdef SAF_ENABLE_SOFA_READER_MODULE
133#endif
134
135 strcpy(pData->progressBarText,"Loading HRIRs");
136 pData->progressBar0_1 = 0.2f;
137
138 /* load sofa file or load default hrir data */
139#ifdef SAF_ENABLE_SOFA_READER_MODULE
140 if(!pData->useDefaultHRIRsFLAG && pData->sofa_filepath!=NULL){
141 /* Load SOFA file */
143
144 /* Load defaults instead */
145 if(error!=SAF_SOFA_OK || sofa.nReceivers!=NUM_EARS){
146 pData->useDefaultHRIRsFLAG = 1;
147 saf_print_warning("Unable to load the specified SOFA file, or it contained something other than 2 channels. Using default HRIR data instead.");
148 }
149 else{
150 /* Copy SOFA data */
151 pData->hrir_loaded_fs = (int)sofa.DataSamplingRate;
152 pData->hrir_loaded_len = sofa.DataLengthIR;
153 pData->N_hrir_dirs = sofa.nSources;
154 pData->hrirs = realloc1d(pData->hrirs, pData->N_hrir_dirs*NUM_EARS*(pData->hrir_loaded_len)*sizeof(float));
155 memcpy(pData->hrirs, sofa.DataIR, pData->N_hrir_dirs*NUM_EARS*(pData->hrir_loaded_len)*sizeof(float));
156 pData->hrir_dirs_deg = realloc1d(pData->hrir_dirs_deg, pData->N_hrir_dirs*2*sizeof(float));
157 cblas_scopy(pData->N_hrir_dirs, sofa.SourcePosition, 3, pData->hrir_dirs_deg, 2); /* azi */
158 cblas_scopy(pData->N_hrir_dirs, &sofa.SourcePosition[1], 3, &pData->hrir_dirs_deg[1], 2); /* elev */
159 }
160
161 /* Clean-up */
162 saf_sofa_close(&sofa);
163 }
164#else
165 pData->useDefaultHRIRsFLAG = 1; /* Can only load the default HRIR data */
166#endif
167 if(pData->useDefaultHRIRsFLAG){
168 /* Copy default HRIR data */
172 pData->hrirs = realloc1d(pData->hrirs, pData->N_hrir_dirs*NUM_EARS*(pData->hrir_loaded_len)*sizeof(float));
173 memcpy(pData->hrirs, (float*)__default_hrirs, pData->N_hrir_dirs*NUM_EARS*(pData->hrir_loaded_len)*sizeof(float));
174 pData->hrir_dirs_deg = realloc1d(pData->hrir_dirs_deg, pData->N_hrir_dirs*2*sizeof(float));
175 memcpy(pData->hrir_dirs_deg, (float*)__default_hrir_dirs_deg, pData->N_hrir_dirs*2*sizeof(float));
176 }
177
178 /* Convert from the 0..360 convention, to -180..180 */
180
181 /* estimate the ITDs for each HRIR */
182 strcpy(pData->progressBarText,"Estimating ITDs");
183 pData->progressBar0_1 = 0.4f;
184 pData->itds_s = realloc1d(pData->itds_s, pData->N_hrir_dirs*sizeof(float));
185 estimateITDs(pData->hrirs, pData->N_hrir_dirs, pData->hrir_loaded_len, pData->hrir_loaded_fs, pData->itds_s);
186
187 /* Resample the HRIRs if needed */
188 if(pData->hrir_loaded_fs!=pData->fs){
189 strcpy(pData->progressBarText,"Resampling the HRIRs");
190 pData->progressBar0_1 = 0.5f;
191 hrirs_resampled = NULL;
192 resampleHRIRs(pData->hrirs, pData->N_hrir_dirs, pData->hrir_loaded_len, pData->hrir_loaded_fs, pData->fs, 1, &hrirs_resampled, &new_len);
193 pData->hrirs = realloc1d(pData->hrirs, pData->N_hrir_dirs*NUM_EARS*new_len*sizeof(float));
194 cblas_scopy(pData->N_hrir_dirs*NUM_EARS*new_len, hrirs_resampled, 1, pData->hrirs, 1);
195 free(hrirs_resampled);
196 pData->hrir_runtime_fs = pData->fs;
197 pData->hrir_runtime_len = new_len;
198 }
199 else{
200 pData->hrir_runtime_fs = pData->hrir_loaded_fs;
201 pData->hrir_runtime_len = pData->hrir_loaded_len;
202 }
203
204 /* generate VBAP gain table */
205 strcpy(pData->progressBarText,"Generating interpolation table");
206 pData->progressBar0_1 = 0.6f;
207 hrtf_vbap_gtable = NULL;
208 pData->hrtf_vbapTableRes[0] = 2;
209 pData->hrtf_vbapTableRes[1] = 5;
210 generateVBAPgainTable3D(pData->hrir_dirs_deg, pData->N_hrir_dirs, pData->hrtf_vbapTableRes[0], pData->hrtf_vbapTableRes[1], 1, 0, 0.0f,
211 &hrtf_vbap_gtable, &(pData->N_hrtf_vbap_gtable), &(pData->nTriangles));
212 if(hrtf_vbap_gtable==NULL){
213 /* if generating vbap gain tabled failed, re-calculate with default HRIR set */
214 pData->useDefaultHRIRsFLAG = 1;
216 }
217
218 /* compress VBAP table (i.e. remove the zero elements) */
219 pData->hrtf_vbap_gtableComp = realloc1d(pData->hrtf_vbap_gtableComp, pData->N_hrtf_vbap_gtable * 3 * sizeof(float));
220 pData->hrtf_vbap_gtableIdx = realloc1d(pData->hrtf_vbap_gtableIdx, pData->N_hrtf_vbap_gtable * 3 * sizeof(int));
222
223 /* convert hrirs to filterbank coefficients */
224 pData->progressBar0_1 = 0.6f;
225 pData->hrtf_fb = realloc1d(pData->hrtf_fb, HYBRID_BANDS * NUM_EARS * (pData->N_hrir_dirs)*sizeof(float_complex));
226 HRIRs2HRTFs_afSTFT(pData->hrirs, pData->N_hrir_dirs, pData->hrir_runtime_len, HOP_SIZE, 0, 1, pData->hrtf_fb);
227
228 /* HRIR pre-processing */
229 if(pData->enableHRIRsDiffuseEQ){
230 /* get integration weights */
231 strcpy(pData->progressBarText,"Applying HRIR diffuse-field EQ");
232 pData->progressBar0_1 = 0.9f;
233 if(pData->N_hrir_dirs<=3600){
234 pData->weights = realloc1d(pData->weights, pData->N_hrir_dirs*sizeof(float));
235 float * hrir_dirs_rad = (float*) malloc1d(pData->N_hrir_dirs*2*sizeof(float));
236 memcpy(hrir_dirs_rad, pData->hrir_dirs_deg, pData->N_hrir_dirs*2*sizeof(float));
237 cblas_sscal(pData->N_hrir_dirs*2, SAF_PI/180.f, hrir_dirs_rad, 1);
238 sphElev2incl(hrir_dirs_rad, pData->N_hrir_dirs, 0, hrir_dirs_rad);
239 int supOrder = calculateGridWeights(hrir_dirs_rad, pData->N_hrir_dirs, -1, pData->weights);
240 if(supOrder < 1){
241 saf_print_warning("Could not calculate grid weights");
242 free(pData->weights);
243 pData->weights = NULL;
244 }
245 }
246 else{
247 saf_print_warning("Too many grid points to calculate grid weights. Assuming that the HRTF measurement grid was uniform.");
248 free(pData->weights);
249 pData->weights = NULL;
250 }
251 diffuseFieldEqualiseHRTFs(pData->N_hrir_dirs, pData->itds_s, pData->freqVector, HYBRID_BANDS, pData->weights, 1, 0, pData->hrtf_fb);
252 }
253
254 /* calculate magnitude responses */
255 pData->hrtf_fb_mag = realloc1d(pData->hrtf_fb_mag, HYBRID_BANDS*NUM_EARS*(pData->N_hrir_dirs)*sizeof(float));
256 for(i=0; i<HYBRID_BANDS*NUM_EARS* (pData->N_hrir_dirs); i++)
257 pData->hrtf_fb_mag[i] = cabsf(pData->hrtf_fb[i]);
258
259 /* The HRTFs should be re-interpolated */
260 for(i=0; i<MAX_NUM_INPUTS; i++)
261 pData->recalc_hrtf_interpFLAG[i] = 1;
262
263 /* clean-up */
264 free(hrtf_vbap_gtable);
265}
266
268(
269 void* const hBin
270)
271{
272 binauraliser_data *pData = (binauraliser_data*)(hBin);
273
274 if(pData->hSTFT==NULL)
276 else if(pData->new_nSources!=pData->nSources){
279 }
280 pData->nSources = pData->new_nSources;
281}
282
284(
286 _Atomic_FLOAT32 dirs_deg[MAX_NUM_INPUTS][2],
287 _Atomic_INT32* newNCH,
288 int* nDims
289)
290{
291 float sum_elev;
292 int ch, i, nCH;
293
294 switch(preset){
295 default:
296 case SOURCE_CONFIG_PRESET_DEFAULT:
297 nCH = 1;
298 for(ch=0; ch<nCH; ch++)
299 for(i=0; i<2; i++)
300 dirs_deg[ch][i] = 0.0f;
301 break;
302 case SOURCE_CONFIG_PRESET_MONO:
303 nCH = 1;
304 for(ch=0; ch<nCH; ch++)
305 for(i=0; i<2; i++)
306 dirs_deg[ch][i] = __mono_dirs_deg[ch][i];
307 break;
308 case SOURCE_CONFIG_PRESET_STEREO:
309 nCH = 2;
310 for(ch=0; ch<nCH; ch++)
311 for(i=0; i<2; i++)
312 dirs_deg[ch][i] = __stereo_dirs_deg[ch][i];
313 break;
314 case SOURCE_CONFIG_PRESET_5PX:
315 nCH = 5;
316 for(ch=0; ch<nCH; ch++)
317 for(i=0; i<2; i++)
318 dirs_deg[ch][i] = __5pX_dirs_deg[ch][i];
319 break;
320 case SOURCE_CONFIG_PRESET_7PX:
321 nCH = 7;
322 for(ch=0; ch<nCH; ch++)
323 for(i=0; i<2; i++)
324 dirs_deg[ch][i] = __7pX_dirs_deg[ch][i];
325 break;
326 case SOURCE_CONFIG_PRESET_8PX:
327 nCH = 8;
328 for(ch=0; ch<nCH; ch++)
329 for(i=0; i<2; i++)
330 dirs_deg[ch][i] = __8pX_dirs_deg[ch][i];
331 break;
332 case SOURCE_CONFIG_PRESET_9PX:
333 nCH = 9;
334 for(ch=0; ch<nCH; ch++)
335 for(i=0; i<2; i++)
336 dirs_deg[ch][i] = __9pX_dirs_deg[ch][i];
337 break;
338 case SOURCE_CONFIG_PRESET_10PX:
339 nCH = 10;
340 for(ch=0; ch<nCH; ch++)
341 for(i=0; i<2; i++)
342 dirs_deg[ch][i] = __10pX_dirs_deg[ch][i];
343 break;
344 case SOURCE_CONFIG_PRESET_11PX:
345 nCH = 11;
346 for(ch=0; ch<nCH; ch++)
347 for(i=0; i<2; i++)
348 dirs_deg[ch][i] = __11pX_dirs_deg[ch][i];
349 break;
350 case SOURCE_CONFIG_PRESET_11PX_7_4:
351 nCH = 11;
352 for(ch=0; ch<nCH; ch++)
353 for(i=0; i<2; i++)
354 dirs_deg[ch][i] = __11pX_7_4_dirs_deg[ch][i];
355 break;
356 case SOURCE_CONFIG_PRESET_13PX:
357 nCH = 13;
358 for(ch=0; ch<nCH; ch++)
359 for(i=0; i<2; i++)
360 dirs_deg[ch][i] = __13pX_dirs_deg[ch][i];
361 break;
362 case SOURCE_CONFIG_PRESET_22PX:
363 nCH = 22;
364 for(ch=0; ch<nCH; ch++)
365 for(i=0; i<2; i++)
366 dirs_deg[ch][i] = __22pX_dirs_deg[ch][i];
367 break;
368 case SOURCE_CONFIG_PRESET_22P2_9_10_3:
369 nCH = 24;
370 for(ch=0; ch<nCH; ch++)
371 for(i=0; i<2; i++)
372 dirs_deg[ch][i] = __9_10_3p2_dirs_deg[ch][i];
373 break;
374 case SOURCE_CONFIG_PRESET_AALTO_MCC:
375 nCH = 45;
376 for(ch=0; ch<nCH; ch++)
377 for(i=0; i<2; i++)
378 dirs_deg[ch][i] = __Aalto_MCC_dirs_deg[ch][i];
379 break;
380 case SOURCE_CONFIG_PRESET_AALTO_MCC_SUBSET:
381 nCH = 37;
382 for(ch=0; ch<nCH; ch++)
383 for(i=0; i<2; i++)
384 dirs_deg[ch][i] = __Aalto_MCCsubset_dirs_deg[ch][i];
385 break;
386 case SOURCE_CONFIG_PRESET_AALTO_APAJA:
387 nCH = 29;
388 for(ch=0; ch<nCH; ch++)
389 for(i=0; i<2; i++)
390 dirs_deg[ch][i] = __Aalto_Apaja_dirs_deg[ch][i];
391 break;
392 case SOURCE_CONFIG_PRESET_AALTO_LR:
393 nCH = 13;
394 for(ch=0; ch<nCH; ch++)
395 for(i=0; i<2; i++)
396 dirs_deg[ch][i] = __Aalto_LR_dirs_deg[ch][i];
397 break;
398 case SOURCE_CONFIG_PRESET_DTU_AVIL:
399 nCH = 64;
400 for(ch=0; ch<nCH; ch++)
401 for(i=0; i<2; i++)
402 dirs_deg[ch][i] = __DTU_AVIL_dirs_deg[ch][i];
403 break;
404 case SOURCE_CONFIG_PRESET_ZYLIA_LAB:
405 nCH = 22;
406 for(ch=0; ch<nCH; ch++)
407 for(i=0; i<2; i++)
408 dirs_deg[ch][i] = __Zylia_Lab_dirs_deg[ch][i];
409 break;
410 case SOURCE_CONFIG_PRESET_T_DESIGN_4:
411 nCH = 4;
412 for(ch=0; ch<nCH; ch++)
413 for(i=0; i<2; i++)
414 dirs_deg[ch][i] = __Tdesign_degree_2_dirs_deg[ch][i];
415 break;
416 case SOURCE_CONFIG_PRESET_T_DESIGN_12:
417 nCH = 12;
418 for(ch=0; ch<nCH; ch++)
419 for(i=0; i<2; i++)
420 dirs_deg[ch][i] = __Tdesign_degree_4_dirs_deg[ch][i];
421 break;
422 case SOURCE_CONFIG_PRESET_T_DESIGN_24:
423 nCH = 24;
424 for(ch=0; ch<nCH; ch++)
425 for(i=0; i<2; i++)
426 dirs_deg[ch][i] = __Tdesign_degree_6_dirs_deg[ch][i];
427 break;
428 case SOURCE_CONFIG_PRESET_T_DESIGN_36:
429 nCH = 36;
430 for(ch=0; ch<nCH; ch++)
431 for(i=0; i<2; i++)
432 dirs_deg[ch][i] = __Tdesign_degree_8_dirs_deg[ch][i];
433 break;
434 case SOURCE_CONFIG_PRESET_T_DESIGN_48:
435 nCH = 48;
436 for(ch=0; ch<nCH; ch++)
437 for(i=0; i<2; i++)
438 dirs_deg[ch][i] = __Tdesign_degree_9_dirs_deg[ch][i];
439 break;
440 case SOURCE_CONFIG_PRESET_T_DESIGN_60:
441 nCH = 60;
442 for(ch=0; ch<nCH; ch++)
443 for(i=0; i<2; i++)
444 dirs_deg[ch][i] = __Tdesign_degree_10_dirs_deg[ch][i];
445 break;
446 case SOURCE_CONFIG_PRESET_SPH_COV_9:
447 nCH = 9;
448 for(ch=0; ch<nCH; ch++)
449 for(i=0; i<2; i++)
450 dirs_deg[ch][i] = __SphCovering_9_dirs_deg[ch][i];
451 break;
452 case SOURCE_CONFIG_PRESET_SPH_COV_16:
453 nCH = 16;
454 for(ch=0; ch<nCH; ch++)
455 for(i=0; i<2; i++)
456 dirs_deg[ch][i] = __SphCovering_16_dirs_deg[ch][i];
457 break;
458 case SOURCE_CONFIG_PRESET_SPH_COV_25:
459 nCH = 25;
460 for(ch=0; ch<nCH; ch++)
461 for(i=0; i<2; i++)
462 dirs_deg[ch][i] = __SphCovering_25_dirs_deg[ch][i];
463 break;
464 case SOURCE_CONFIG_PRESET_SPH_COV_49:
465 nCH = 49;
466 for(ch=0; ch<nCH; ch++)
467 for(i=0; i<2; i++)
468 dirs_deg[ch][i] = __SphCovering_49_dirs_deg[ch][i];
469 break;
470 case SOURCE_CONFIG_PRESET_SPH_COV_64:
471 nCH = 64;
472 for(ch=0; ch<nCH; ch++)
473 for(i=0; i<2; i++)
474 dirs_deg[ch][i] = __SphCovering_64_dirs_deg[ch][i];
475 break;
476 }
477
478 /* Fill remaining slots with default coords */
479 for(; ch<MAX_NUM_INPUTS; ch++){
480 for(i=0; i<2; i++){
481 dirs_deg[ch][i] = __default_LScoords128_deg[ch][i];
482 }
483 }
484
485 /* For dynamically changing the number of TFT channels */
486 (*newNCH) = nCH;
487
488 /* estimate number of dimensions. (Obviously fails if using 2D setups thare are on an angle.
489 However, in these cases, triangulation should fail and revert to 2D anyway) */
490 sum_elev = 0.0f;
491 for(i=0; i<nCH; i++){
492 sum_elev += dirs_deg[i][1];
493 }
494 if(sum_elev < 0.01f)
495 (*nDims) = 2;
496 else
497 (*nDims) = 3;
498}
499
500
501
502
503
504
505
506
507
508
509
510
#define MAX_NUM_INPUTS
Maximum number of input channels supported.
Definition _common.h:237
SOURCE_CONFIG_PRESETS
Available source configurations presets to use for encoding/panning.
Definition _common.h:137
CODEC_STATUS
Current status of the codec.
Definition _common.h:205
@ CODEC_STATUS_NOT_INITIALISED
Codec has not yet been initialised, or the codec configuration has changed.
Definition _common.h:208
@ CODEC_STATUS_INITIALISING
Codec is currently being initialised, input audio should not be processed.
Definition _common.h:211
void afSTFT_clearBuffers(void *const hSTFT)
Flushes time-domain buffers with zeros.
Definition afSTFTlib.c:519
void afSTFT_create(void **const phSTFT, int nCHin, int nCHout, int hopsize, int lowDelayMode, int hybridmode, AFSTFT_FDDATA_FORMAT format)
Creates an instance of afSTFT.
Definition afSTFTlib.c:143
void afSTFT_channelChange(void *const hSTFT, int new_nCHin, int new_nCHout)
Re-allocates memory to support a change in the number of input/output channels.
Definition afSTFTlib.c:477
@ AFSTFT_BANDS_CH_TIME
nBands x nChannels x nTimeHops
Definition afSTFTlib.h:80
#define HOP_SIZE
STFT hop size.
#define HYBRID_BANDS
Number of frequency bands.
INTERP_MODES
Available interpolation modes.
@ INTERP_TRI
Triangular interpolation.
@ INTERP_TRI_PS
Triangular interpolation (with phase-simplification)
void binauraliser_initHRTFsAndGainTables(void *const hBin)
Initialise the HRTFs: either loading the default set or loading from a SOFA file; and then generate a...
void binauraliser_loadPreset(SOURCE_CONFIG_PRESETS preset, _Atomic_FLOAT32 dirs_deg[MAX_NUM_INPUTS][2], _Atomic_INT32 *newNCH, int *nDims)
Returns the source directions for a specified source config preset.
void binauraliser_setCodecStatus(void *const hBin, CODEC_STATUS newStatus)
Sets codec status (see CODEC_STATUS enum)
void binauraliser_initTFT(void *const hBin)
Initialise the filterbank used by binauraliser.
void binauraliser_interpHRTFs(void *const hBin, INTERP_MODES mode, float azimuth_deg, float elevation_deg, float_complex h_intrp[HYBRID_BANDS][NUM_EARS])
Interpolates between (up to) 3 HRTFs via amplitude-normalised VBAP gains.
Convolves input audio (up to 64 channels) with interpolated HRTFs in the time-frequency domain.
const int __default_N_hrir_dirs
The number of directions/measurements in the default HRIR dataset.
const float __default_hrirs[836][2][256]
The default HRIR data for SAF.
const float __default_hrir_dirs_deg[836][2]
The measurement directions used for the default HRIR dataset.
const int __default_hrir_len
The length of the filters, in samples, for the default HRIR dataset.
const int __default_hrir_fs
The samplerate used to measure the default HRIR filters.
void diffuseFieldEqualiseHRTFs(int N_dirs, float *itds_s, float *centreFreq, int N_bands, float *weights, int applyEQ, int applyPhase, float_complex *hrtfs)
Applies pre-processing to a set of HRTFs, which can either be diffuse-field EQ of an (optionally weig...
Definition saf_hrir.c:174
void resampleHRIRs(float *hrirs_in, int hrirs_N_dirs, int hrirs_in_len, int hrirs_in_fs, int hrirs_out_fs, int padToNextPow2, float **hrirs_out, int *hrirs_out_len)
Resamples a set of HRIRs from its original samplerate to a new samplerate.
Definition saf_hrir.c:366
void estimateITDs(float *hrirs, int N_dirs, int hrir_len, int fs, float *itds_s)
Estimates the interaural time-differences (ITDs) for each HRIR based on the cross-correlation between...
Definition saf_hrir.c:41
void HRIRs2HRTFs_afSTFT(float *hrirs, int N_dirs, int hrir_len, int hopsize, int LDmode, int hybridmode, float_complex *hrtf_fb)
Passes zero padded HRIRs through the afSTFT filterbank.
Definition saf_hrir.c:111
int calculateGridWeights(float *dirs_rad, int nDirs, int order, float *w)
Computes approximation of quadrature/integration weights for a given grid.
Definition saf_sh.c:1066
void saf_sofa_close(saf_sofa_container *c)
Frees all SOFA data in a sofa_container.
SAF_SOFA_ERROR_CODES saf_sofa_open(saf_sofa_container *h, char *sofa_filepath, SAF_SOFA_READER_OPTIONS option)
Fills a 'sofa_container' with data found in a SOFA file (GeneralFIR or SimpleFreeFieldHRIR),...
SAF_SOFA_ERROR_CODES
SOFA loader error codes.
@ SAF_SOFA_READER_OPTION_DEFAULT
The default option is SAF_SOFA_READER_OPTION_LIBMYSOFA.
@ SAF_SOFA_OK
None of the error checks failed.
const float __Zylia_Lab_dirs_deg[22][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for the 22.x setup, at Zylia Labs.
#define SAF_PI
pi constant (single precision)
const float __9pX_dirs_deg[9][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 9.x setup.
const float __SphCovering_16_dirs_deg[16][2]
Directions [azimuth, Elevation] in degrees, for sphere covering: 16 dirs.
const float __Aalto_MCC_dirs_deg[45][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for the multi-channel anechoic chamber (MCC),...
const float __SphCovering_49_dirs_deg[49][2]
Directions [azimuth, Elevation] in degrees, for sphere covering: 49 dirs.
void convert_0_360To_m180_180(float *dirs_deg, int nDirs)
Wraps around any angles exeeding 180 degrees (e.g., 200-> -160)
#define NUM_EARS
2 (true for most humans)
float matlab_fmodf(float x, float y)
C fmodf function, except it behaves like 'mod' in Matlab (i.e.
const float __mono_dirs_deg[1][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a mono setup.
const float __5pX_dirs_deg[5][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 5.x setup.
const float __11pX_dirs_deg[11][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 11.x setup.
const float __Tdesign_degree_9_dirs_deg[48][2]
Directions [azimuth, Elevation] in degrees, for minimum Tdesign degree: 9.
const float __Tdesign_degree_2_dirs_deg[4][2]
Directions [azimuth, Elevation] in degrees, for minimum Tdesign degree: 2.
const float __11pX_7_4_dirs_deg[11][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 7.4.x setup.
const float __Tdesign_degree_8_dirs_deg[36][2]
Directions [azimuth, Elevation] in degrees, for minimum Tdesign degree: 8.
const float __9_10_3p2_dirs_deg[24][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 9+10+3.2 setup BS 2051 recommedation: h...
const float __default_LScoords128_deg[128][2]
Default Loudspeaker directions [azimuth, Elevation] - to replace above!
const float __Aalto_MCCsubset_dirs_deg[37][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for the multi-channel anechoic chamber (MCC) ...
const float __Aalto_Apaja_dirs_deg[29][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for the audio-visual listening room (Apaja),...
const float __SphCovering_9_dirs_deg[9][2]
Directions [azimuth, Elevation] in degrees, for sphere covering: 9 dirs.
const float __stereo_dirs_deg[2][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a stereo setup.
const float __SphCovering_64_dirs_deg[64][2]
Directions [azimuth, Elevation] in degrees, for sphere covering: 64 dirs.
const float __Tdesign_degree_4_dirs_deg[12][2]
Directions [azimuth, Elevation] in degrees, for minimum Tdesign degree: 4.
void sphElev2incl(float *dirsElev, int nDirs, int degreesFlag, float *dirsIncl)
Converts spherical coordinates of unit length from elevation to inclination.
const float __Aalto_LR_dirs_deg[13][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for the ITU standard listening room (LR),...
const float __DTU_AVIL_dirs_deg[64][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for the Audio Visual Immersion Lab (AVIL),...
const float __8pX_dirs_deg[8][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 8.x setup.
const float __Tdesign_degree_6_dirs_deg[24][2]
Directions [azimuth, Elevation] in degrees, for minimum Tdesign degree: 6.
const float __13pX_dirs_deg[13][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 13.x setup.
const float __7pX_dirs_deg[7][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 7.x setup.
#define saf_print_warning(message)
Macro to print a warning message along with the filename and line number.
const float __22pX_dirs_deg[22][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 22.x setup.
const float __SphCovering_25_dirs_deg[25][2]
Directions [azimuth, Elevation] in degrees, for sphere covering: 25 dirs.
const float __Tdesign_degree_10_dirs_deg[60][2]
Directions [azimuth, Elevation] in degrees, for minimum Tdesign degree: 10.
const float __10pX_dirs_deg[10][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 10.x setup.
void generateVBAPgainTable3D(float *ls_dirs_deg, int L, int az_res_deg, int el_res_deg, int omitLargeTriangles, int enableDummies, float spread, float **gtable, int *N_gtable, int *nTriangles)
Generates a 3-D VBAP gain table based on specified loudspeaker directions, with optional spreading [2...
Definition saf_vbap.c:172
void compressVBAPgainTable3D(float *vbap_gtable, int nTable, int nDirs, float *vbap_gtableComp, int *vbap_gtableIdx)
Compresses a VBAP gain table to use less memory and CPU (by removing the elements which are just zero...
Definition saf_vbap.c:313
void * malloc1d(size_t dim1_data_size)
1-D malloc (same as malloc, but with error checking)
Definition md_malloc.c:59
void * realloc1d(void *ptr, size_t dim1_data_size)
1-D realloc (same as realloc, but with error checking)
Definition md_malloc.c:79
Main structure for binauraliser.
_Atomic_INT32 hrir_loaded_fs
sampling rate of the loaded HRIRs
float * hrtf_vbap_gtableComp
N_hrtf_vbap_gtable x 3.
_Atomic_INT32 enableHRIRsDiffuseEQ
flag to diffuse-field equalisation to the currently loaded HRTFs
_Atomic_INT32 hrir_runtime_fs
sampling rate of the HRIRs being used for processing (after any resampling)
float * hrirs
time domain HRIRs; FLAT: N_hrir_dirs x NUM_EARS x hrir_len
float_complex * hrtf_fb
hrtf filterbank coefficients; nBands x nCH x N_hrirs
int N_hrtf_vbap_gtable
Number of interpolation weights/directions.
float * hrir_dirs_deg
directions of the HRIRs in degrees [azi elev]; FLAT: N_hrir_dirs x 2
_Atomic_FLOAT32 fs
Host sampling rate, in Hz.
float * weights
Integration weights for the HRIR measurement grid; N_hrir_dirs x 1.
float * itds_s
interaural-time differences for each HRIR (in seconds); nBands x 1
_Atomic_INT32 hrir_loaded_len
length of the loaded HRIRs, in samples
int * hrtf_vbap_gtableIdx
N_hrtf_vbap_gtable x 3.
int hrtf_vbapTableRes[2]
[0] azimuth, and [1] elevation grid resolution, in degrees
char * progressBarText
Current (re)initialisation step, string.
void * hSTFT
afSTFT handle
_Atomic_INT32 recalc_hrtf_interpFLAG[MAX_NUM_INPUTS]
1: re-calculate/interpolate the HRTF, 0: do not
float * hrtf_fb_mag
magnitudes of the hrtf filterbank coefficients; nBands x nCH x N_hrirs
_Atomic_FLOAT32 progressBar0_1
Current (re)initialisation progress, between [0..1].
_Atomic_INT32 N_hrir_dirs
number of HRIR directions in the current sofa file
_Atomic_INT32 hrir_runtime_len
length of the HRIRs being used for processing (after any resampling), in samples
_Atomic_INT32 useDefaultHRIRsFLAG
1: use default HRIRs in database, 0: use those from SOFA file
char * sofa_filepath
absolute/relevative file path for a sofa file
_Atomic_CODEC_STATUS codecStatus
see CODEC_STATUS
int nTriangles
Number of triangles in the convex hull of the spherical arrangement of HRIR directions/points.
float freqVector[HYBRID_BANDS]
Frequency vector (filterbank centre frequencies)
_Atomic_INT32 new_nSources
New number of input/source signals (current value will be replaced by this after next re-init)
_Atomic_INT32 nSources
Current number of input/source signals.
SOFA container struct comprising all possible data that can be extracted from SOFA 1....
int DataLengthIR
Length of the IRs, in samples.
int nSources
Number of source/measurement positions.
float * SourcePosition
Source positions (refer to SourcePositionType & SourcePositionUnits for the convention and units); FL...
float DataSamplingRate
Sampling rate used to measure the IRs.
int nReceivers
Number of ears/number of mics etc.
float * DataIR
The impulse response (IR) Data; FLAT:nSources x nReceivers x DataLengthIR.