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
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. i.e., we're not 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 float dirs_deg[MAX_NUM_INPUTS][2],
287 int* 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:233
SOURCE_CONFIG_PRESETS
Available source configurations presets to use for encoding/panning.
Definition _common.h:133
CODEC_STATUS
Current status of the codec.
Definition _common.h:201
@ CODEC_STATUS_NOT_INITIALISED
Codec has not yet been initialised, or the codec configuration has changed.
Definition _common.h:204
@ CODEC_STATUS_INITIALISING
Codec is currently being initialised, input audio should not be processed.
Definition _common.h:207
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_setCodecStatus(void *const hBin, CODEC_STATUS newStatus)
Sets codec status (see CODEC_STATUS enum)
void binauraliser_loadPreset(SOURCE_CONFIG_PRESETS preset, float dirs_deg[MAX_NUM_INPUTS][2], int *newNCH, int *nDims)
Returns the source directions for a specified source config preset.
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.
int hrir_runtime_len
length of the HRIRs being used for processing (after any resampling), in samples
int fs
Host sampling rate, in Hz.
int nSources
Current number of input/source signals.
float * hrtf_vbap_gtableComp
N_hrtf_vbap_gtable x 3.
int N_hrir_dirs
number of HRIR directions in the current sofa file
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 progressBar0_1
Current (re)initialisation progress, between [0..1].
int hrir_runtime_fs
sampling rate of the HRIRs being used for processing (after any resampling)
float * hrir_dirs_deg
directions of the HRIRs in degrees [azi elev]; FLAT: N_hrir_dirs x 2
float * weights
Integration weights for the HRIR measurement grid.
float * itds_s
interaural-time differences for each HRIR (in seconds); nBands x 1
int * hrtf_vbap_gtableIdx
N_hrtf_vbap_gtable x 3.
int hrir_loaded_len
length of the loaded HRIRs, in samples
int hrtf_vbapTableRes[2]
[0] azimuth, and [1] elevation grid resolution, in degrees
CODEC_STATUS codecStatus
see CODEC_STATUS
char * progressBarText
Current (re)initialisation step, string.
void * hSTFT
afSTFT handle
float * hrtf_fb_mag
magnitudes of the hrtf filterbank coefficients; nBands x nCH x N_hrirs
int new_nSources
New number of input/source signals (current value will be replaced by this after next re-init)
int enableHRIRsDiffuseEQ
flag to diffuse-field equalisation to the currently loaded HRTFs
int recalc_hrtf_interpFLAG[MAX_NUM_INPUTS]
1: re-calculate/interpolate the HRTF, 0: do not
int hrir_loaded_fs
sampling rate of the loaded HRIRs
int useDefaultHRIRsFLAG
1: use default HRIRs in database, 0: use those from SOFA file
char * sofa_filepath
absolute/relevative file path for a sofa file
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)
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.