SAF
Loading...
Searching...
No Matches
binauraliser_nf.c
Go to the documentation of this file.
1/*
2 * Copyright 2022 Michael McCrea, 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
38
40
41void binauraliserNF_create /* FREQUENCY DOMAIN version */
42(
43 void ** const phBin
44)
45{
47 *phBin = (void*)pData;
48 int nDim; // nDim not actually used
49
50 /* user parameters */
51 pData->useDefaultHRIRsFLAG = 1; /* pars->sofa_filepath must be valid to set this to 0 */
52 pData->enableHRIRsDiffuseEQ = 1;
53 pData->nSources = pData->new_nSources;
55 pData->yaw = 0.0f;
56 pData->pitch = 0.0f;
57 pData->roll = 0.0f;
58 pData->bFlipYaw = 0;
59 pData->bFlipPitch = 0;
60 pData->bFlipRoll = 0;
61 pData->useRollPitchYawFlag = 0;
62 pData->enableRotation = 0;
63
64 /* Near field DVF settings
65 * Head radius is set according to the linear combination of head width,
66 * height and depth from:
67 * Algazi VR, Avendano C, Duda RO. Estimation of a spherical-head model
68 * from anthropometry. J Audio Eng Soc 2001; 49(6):472-9.
69 * The far field threshold is set by rho (normalized distance) = 34, resulting
70 * in a ~3 m far field, where the max DVF filter response is about +/-0.5 dB.
71 * Near field limit set where filters are stable, in meters from head _center_.
72 */
73 pData->head_radius = 0.09096; /* Should match a_head in in saf_utility_dvf.c */
74 pData->head_radius_recip = 1.f / pData->head_radius;
75 pData->farfield_thresh_m = pData->head_radius * 34.f;
76 pData->farfield_headroom = 1.05f; /* 5% headroom above the far field threshold, for resetting to far field and UI range */
77 pData->nearfield_limit_m = 0.15f;
78
79 /* Set default source directions and distances */
80 binauraliser_loadPreset(SOURCE_CONFIG_PRESET_DEFAULT, pData->src_dirs_deg, &(pData->new_nSources), &nDim); /* check setStateInformation if you change default preset */
81 /* For now, any preset selected will reset sources to the far field */
82 binauraliserNF_resetSourceDistances(pData); /* Must be called after pData->farfield_thresh_m is set */
83
84 /* time-frequency transform + buffers */
85 pData->hSTFT = NULL;
86 /* hrir data */
87 pData->hrirs = NULL;
88 pData->hrir_dirs_deg = NULL;
89 pData->sofa_filepath = NULL;
90 pData->weights = NULL;
91 pData->N_hrir_dirs = pData->hrir_loaded_len = pData->hrir_runtime_len = 0;
92 pData->hrir_loaded_fs = pData->hrir_runtime_fs = -1; /* unknown */
93
94 /* time domain buffers */
95 pData->fs = 48000.0f;
96 pData->inputFrameTD = (float**)malloc2d(MAX_NUM_INPUTS, BINAURALISER_FRAME_SIZE, sizeof(float));
97 pData->outframeTD = (float**)malloc2d(NUM_EARS, BINAURALISER_FRAME_SIZE, sizeof(float));
98 pData->inputframeTF = (float_complex***)malloc3d(HYBRID_BANDS, MAX_NUM_INPUTS, TIME_SLOTS, sizeof(float_complex));
99 pData->outputframeTF = (float_complex***)malloc3d(HYBRID_BANDS, NUM_EARS, TIME_SLOTS, sizeof(float_complex));
100
101 /* vbap (amplitude normalised) */
102 pData->hrtf_vbap_gtableIdx = NULL;
103 pData->hrtf_vbap_gtableComp = NULL;
104 pData->nTriangles = pData->N_hrtf_vbap_gtable = 0;
105
106 /* HRTF filterbank coefficients */
107 pData->itds_s = NULL;
108 pData->hrtf_fb = NULL;
109 pData->hrtf_fb_mag = NULL;
110
111 /* Initialize DVF filter parameters */
112 memset(FLATTEN3D(pData->dvfmags), 1.f, MAX_NUM_INPUTS * NUM_EARS * HYBRID_BANDS * sizeof(float));
113 memset(FLATTEN3D(pData->dvfphases), 0.f, MAX_NUM_INPUTS * NUM_EARS * HYBRID_BANDS * sizeof(float));
114 memset(FLATTEN3D(pData->b_dvf), 0.f, MAX_NUM_INPUTS * NUM_EARS * 2 * sizeof(float));
115 memset(FLATTEN3D(pData->a_dvf), 0.f, MAX_NUM_INPUTS * NUM_EARS * 2 * sizeof(float));
116 for(int ch = 0; ch < MAX_NUM_INPUTS; ch++) {
117 for(int ear = 0; ear < NUM_EARS; ear++) {
118 pData->a_dvf[ch][ear][0] = 1.f; /* a_0 = 1.0, always */
119 }
120 }
121
122 /* flags/status */
123 pData->progressBar0_1 = 0.0f;
125 strcpy(pData->progressBarText, "");
128 pData->reInitHRTFsAndGainTables = 1;
129 for(int ch = 0; ch < MAX_NUM_INPUTS; ch++) {
130 pData->recalc_hrtf_interpFLAG[ch] = 1;
131 pData->recalc_dvfCoeffFLAG[ch] = 1;
132 pData->src_gains[ch] = 1.f;
133 }
134 pData->recalc_M_rotFLAG = 1;
135
136 for(int ch = 0; ch < MAX_NUM_INPUTS; ch++) {
137 pData->src_dirs_cur[ch][0] = pData->src_dirs_deg[ch][0];
138 pData->src_dirs_cur[ch][1] = pData->src_dirs_deg[ch][1];
139 }
140}
141
143(
144 void ** const phBin
145)
146{
147 binauraliserNF_data *pData = (binauraliserNF_data*)(*phBin);
148
149 if (pData != NULL) {
150 /* not safe to free memory during intialisation/processing loop */
151 while (pData->codecStatus == CODEC_STATUS_INITIALISING ||
153 SAF_SLEEP(10);
154 }
155
156 if(pData->hSTFT !=NULL)
157 afSTFT_destroy(&(pData->hSTFT));
158 free(pData->inputFrameTD);
159 free(pData->outframeTD);
160 free(pData->inputframeTF);
161 free(pData->outputframeTF);
162 free(pData->hrtf_vbap_gtableComp);
163 free(pData->hrtf_vbap_gtableIdx);
164 free(pData->hrtf_fb);
165 free(pData->hrtf_fb_mag);
166 free(pData->itds_s);
167 free(pData->hrirs);
168 free(pData->hrir_dirs_deg);
169 free(pData->weights);
170 free(pData->progressBarText);
171
172 free(pData);
173 pData = NULL;
174 *phBin = NULL;
175 }
176}
177
179(
180 void * const hBin, int sampleRate
181)
182{
183 binauraliser_init(hBin, sampleRate);
184}
185
186/* NOTE: This function is a copy of binauraliser_initCodec.
187 * The only difference is that it calls binauraliserNF_initTFT, which needs
188 * new_nSources * NUM_EARS output channels in the afSTFT. This function could
189 * be omitted if binauraliser_initTFT could be refactored to set its number
190 * of outputs differently for the regular and NF version of the binauraliser,
191 * e.g. a member var afSTFT_nOuts, which changes when binauraliser_setNumSources
192 * is called. */
194(
195 void* const hBin
196)
197{
198 binauraliser_data *pData = (binauraliser_data*)(hBin);
199
201 return; /* re-init not required, or already happening */
202 while (pData->procStatus == PROC_STATUS_ONGOING){
203 /* re-init required, but we need to wait for the current processing loop to end */
204 pData->codecStatus = CODEC_STATUS_INITIALISING; /* indicate that we want to init */
205 SAF_SLEEP(10);
206 }
207
208 /* for progress bar */
210 strcpy(pData->progressBarText,"Initialising");
211 pData->progressBar0_1 = 0.0f;
212
213 /* check if TFT needs to be reinitialised */
214 // use binauraliser_initTFT() Freq-domain DVF, binauraliserNF_initTFT() for Time-domain DVF
216
217 /* reinit HRTFs and interpolation tables */
218 if(pData->reInitHRTFsAndGainTables){
220 pData->reInitHRTFsAndGainTables = 0;
221 }
222
223 /* done! */
224 strcpy(pData->progressBarText,"Done!");
225 pData->progressBar0_1 = 1.0f;
227}
228
229void binauraliserNF_process /* FREQ DOMAIN version */
230(
231 void * const hBin,
232 const float *const * inputs,
233 float* const* const outputs,
234 int nInputs,
235 int nOutputs,
236 int nSamples
237)
238{
240 int ch, ear, i, band, nSources, enableRotation;
241 float hypotxy, headRadiusRecip, fs, ffThresh, rho, temp_gain;
242 float Rxyz[3][3];
243 float alphaLR[2] = { 0.0, 0.0 };
244
245 /* copy user parameters to local variables */
246 nSources = pData->nSources;
247 enableRotation = pData->enableRotation;
248 headRadiusRecip = pData->head_radius_recip;
249 ffThresh = pData->farfield_thresh_m;
250 fs = (float)pData->fs;
251
252 /* apply binaural panner */
253 if ((nSamples == BINAURALISER_FRAME_SIZE) && (pData->codecStatus==CODEC_STATUS_INITIALISED) && (pData->hrtf_fb!=NULL)) {
255
256 /* Load time-domain data */
257 for (i = 0; i < SAF_MIN(nSources, nInputs); i++)
259 for (; i < nSources; i++)
260 memset(pData->inputFrameTD[i], 0, BINAURALISER_FRAME_SIZE * sizeof(float));
261
262 /* Apply source gains */
263 for (ch = 0; ch < nSources; ch++) {
264 if(fabsf(pData->src_gains[ch] - 1.f) > 1e-6f){
265 temp_gain = pData->src_gains[ch];
266 utility_svsmul(pData->inputFrameTD[ch], &temp_gain, BINAURALISER_FRAME_SIZE, NULL);
267 }
268 }
269
270 /* Apply time-frequency transform (TFT) */
272
273 /* Rotate source directions */
274 if (enableRotation && pData->recalc_M_rotFLAG) {
275 yawPitchRoll2Rzyx (pData->yaw, pData->pitch, pData->roll, pData->useRollPitchYawFlag, Rxyz);
276 for(i = 0; i < nSources; i++){
277 pData->src_dirs_xyz[i][0] = cosf(DEG2RAD(pData->src_dirs_deg[i][1])) * cosf(DEG2RAD(pData->src_dirs_deg[i][0]));
278 pData->src_dirs_xyz[i][1] = cosf(DEG2RAD(pData->src_dirs_deg[i][1])) * sinf(DEG2RAD(pData->src_dirs_deg[i][0]));
279 pData->src_dirs_xyz[i][2] = sinf(DEG2RAD(pData->src_dirs_deg[i][1]));
280 pData->recalc_hrtf_interpFLAG[i] = 1;
281 }
282 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSources, 3, 3, 1.0f,
283 (float*)(pData->src_dirs_xyz), 3,
284 (float*)Rxyz, 3, 0.0f,
285 (float*)(pData->src_dirs_rot_xyz), 3);
286 for (i = 0; i < nSources; i++) {
287 hypotxy = sqrtf(powf(pData->src_dirs_rot_xyz[i][0], 2.0f) + powf(pData->src_dirs_rot_xyz[i][1], 2.0f));
288 pData->src_dirs_rot_deg[i][0] = RAD2DEG(atan2f(pData->src_dirs_rot_xyz[i][1], pData->src_dirs_rot_xyz[i][0]));
289 pData->src_dirs_rot_deg[i][1] = RAD2DEG(atan2f(pData->src_dirs_rot_xyz[i][2], hypotxy));
290 }
291 pData->recalc_M_rotFLAG = 0;
292 }
293
294 /* Interpolate and apply HRTFs, apply DVF magnitude filter */
295 /* Zero out TF summing bus */
296 memset(FLATTEN3D(pData->outputframeTF), 0, HYBRID_BANDS*NUM_EARS*TIME_SLOTS * sizeof(float_complex));
297
298 for (ch = 0; ch < nSources; ch++) {
299 /* Interpolate HRTFs */
300 if (pData->recalc_hrtf_interpFLAG[ch]) {
301 if (enableRotation) {
302 pData->src_dirs_cur[ch][0] = pData->src_dirs_rot_deg[ch][0];
303 pData->src_dirs_cur[ch][1] = pData->src_dirs_rot_deg[ch][1];
304 } else {
305 pData->src_dirs_cur[ch][0] = pData->src_dirs_deg[ch][0];
306 pData->src_dirs_cur[ch][1] = pData->src_dirs_deg[ch][1];
307 }
308 binauraliser_interpHRTFs(hBin, pData->interpMode, pData->src_dirs_cur[ch][0], pData->src_dirs_cur[ch][1], pData->hrtf_interp[ch]);
309 pData->recalc_hrtf_interpFLAG[ch] = 0;
310 pData->recalc_dvfCoeffFLAG[ch] = 1;
311 }
312 /* Update DVF filters with change in direction and/or distance */
313 if (pData->recalc_dvfCoeffFLAG[ch]) {
314 rho = pData->src_dists_m[ch] * headRadiusRecip;
315 doaToIpsiInteraural(pData->src_dirs_cur[ch][0], pData->src_dirs_cur[ch][1], &alphaLR[0], NULL);
316 calcDVFCoeffs(alphaLR[0], rho, fs, pData->b_dvf[ch][0], pData->a_dvf[ch][0]);
317 calcDVFCoeffs(alphaLR[1], rho, fs, pData->b_dvf[ch][1], pData->a_dvf[ch][1]);
318 pData->recalc_dvfCoeffFLAG[ch] = 0;
319
320 evalIIRTransferFunctionf(pData->b_dvf[ch][0], pData->a_dvf[ch][0], 2,
321 pData->freqVector, HYBRID_BANDS, fs, 0,
322 pData->dvfmags[ch][0],
323 pData->dvfphases[ch][0]); // NULL to return magnitude only
324
325 evalIIRTransferFunctionf(pData->b_dvf[ch][1], pData->a_dvf[ch][1], 2,
326 pData->freqVector, HYBRID_BANDS, fs, 0,
327 pData->dvfmags[ch][1],
328 pData->dvfphases[ch][1]); // NULL to return magnitude only
329 pData->recalc_dvfCoeffFLAG[ch] = 0;
330 }
331
332 /* Convolve this channel with the interpolated HRTF, and add it to the binaural buffer */
333 if (pData->src_dists_m[ch] < ffThresh) {
334 /* Near field: convolve this channel with the HRTF & DVF filter */
335 float_complex dvfScale;
336 for (band = 0; band < HYBRID_BANDS; band++) {
337 for (ear = 0; ear < NUM_EARS; ear++) {
338 /* combine mag and phase response of HRTF and DVF */
339 /* apply magnitude & phase */
340 dvfScale = ccmulf(cmplxf(pData->dvfmags[ch][ear][band], pData->dvfphases[ch][ear][band]), pData->hrtf_interp[ch][band][ear]);
341 /* apply magnitude only, no phase */
342 // dvfScale = crmulf(pData->hrtf_interp[ch][band][ear], pData->dvfmags[ch][ear][band]);
343 /* bypass dvf */
344 // dvfScale = pData->hrtf_interp[ch][band][ear];
345
346 cblas_caxpy(TIME_SLOTS, &dvfScale,
347 pData->inputframeTF[band][ch], 1,
348 pData->outputframeTF[band][ear], 1);
349 }
350 }
351 } else {
352 /* Far field: convolve this channel with the HRTF filter only */
353 for (band = 0; band < HYBRID_BANDS; band++)
354 for (ear = 0; ear < NUM_EARS; ear++)
355 cblas_caxpy(TIME_SLOTS, &pData->hrtf_interp[ch][band][ear],
356 pData->inputframeTF[band][ch], 1,
357 pData->outputframeTF[band][ear], 1);
358 }
359 }
360
361 /* scale by number of sources */
362 cblas_sscal(/*re+im*/2*HYBRID_BANDS*NUM_EARS*TIME_SLOTS, 1.0f/sqrtf((float)nSources), (float*)FLATTEN3D(pData->outputframeTF), 1);
363
364 /* inverse-TFT */
366
367 /* Copy to output buffer */
368 for (ch = 0; ch < SAF_MIN(NUM_EARS, nOutputs); ch++)
369 utility_svvcopy(pData->outframeTD[ch], BINAURALISER_FRAME_SIZE, outputs[ch]);
370 for (; ch < nOutputs; ch++)
371 memset(outputs[ch], 0, BINAURALISER_FRAME_SIZE*sizeof(float));
372 }
373 else{
374 for (ch=0; ch < nOutputs; ch++)
375 memset(outputs[ch],0, BINAURALISER_FRAME_SIZE*sizeof(float));
376 }
377
379}
380
381
382/* Set Functions */
383
384void binauraliserNF_setSourceDist_m(void* const hBin, int index, float newDist_m)
385{
387 newDist_m = SAF_MAX(newDist_m, pData->nearfield_limit_m);
388 if(pData->src_dists_m[index] != newDist_m){
389 pData->src_dists_m[index] = newDist_m;
390 pData->recalc_dvfCoeffFLAG[index] = 1;
391 }
392}
393
394void binauraliserNF_setInputConfigPreset(void* const hBin, int newPresetID)
395{
397 int ch, nDim;
398
399 binauraliser_loadPreset(newPresetID, pData->src_dirs_deg, &(pData->new_nSources), &nDim);
400 // For now, any preset selected will reset sources to the far field
402
403 if(pData->nSources != pData->new_nSources)
405 for(ch=0; ch<MAX_NUM_INPUTS; ch++) {
406 pData->recalc_hrtf_interpFLAG[ch] = 1;
407 pData->recalc_dvfCoeffFLAG[ch] = 1;
408 }
409}
410
411float binauraliserNF_getSourceDist_m(void* const hBin, int index)
412{
414
415 return pData->src_dists_m[index];
416}
417
419{
421
422 return pData->farfield_thresh_m;
423}
424
426{
428
429 return pData->farfield_headroom;
430}
431
433{
435
436 return pData->nearfield_limit_m;
437}
#define MAX_NUM_INPUTS
Maximum number of input channels supported.
Definition _common.h:237
#define PROGRESSBARTEXT_CHAR_LENGTH
Length of progress bar string.
Definition _common.h:231
@ PROC_STATUS_ONGOING
Codec is processing input audio, and should not be reinitialised at this time.
Definition _common.h:224
@ PROC_STATUS_NOT_ONGOING
Codec is not processing input audio, and may be reinitialised if needed.
Definition _common.h:226
@ CODEC_STATUS_NOT_INITIALISED
Codec has not yet been initialised, or the codec configuration has changed.
Definition _common.h:208
@ CODEC_STATUS_INITIALISED
Codec is initialised and ready to process input audio.
Definition _common.h:206
@ CODEC_STATUS_INITIALISING
Codec is currently being initialised, input audio should not be processed.
Definition _common.h:211
void afSTFT_backward_knownDimensions(void *const hSTFT, float_complex ***dataFD, int framesize, int dataFD_nCH, int dataFD_nHops, float **dataTD)
Performs backward afSTFT transform (dataFD dimensions are known)
Definition afSTFTlib.c:391
void afSTFT_forward_knownDimensions(void *const hSTFT, float **dataTD, int framesize, int dataFD_nCH, int dataFD_nHops, float_complex ***dataFD)
Performs forward afSTFT transform (dataFD dimensions are known)
Definition afSTFTlib.c:268
void afSTFT_destroy(void **const phSTFT)
Destroys an instance of afSTFT.
Definition afSTFTlib.c:199
#define TIME_SLOTS
Number of STFT timeslots.
#define HYBRID_BANDS
Number of frequency bands.
void binauraliser_init(void *const hBin, int samplerate)
Initialises an instance of binauraliser with default settings.
@ 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.
#define BINAURALISER_FRAME_SIZE
Framesize, in time-domain samples.
void binauraliserNF_init(void *const hBin, int sampleRate)
Initialises an instance of binauraliser with default settings.
float binauraliserNF_getNearfieldLimit_m(void *const hBin)
Returns the minimum distance possible for near field filter, in METERS.
float binauraliserNF_getSourceDist_m(void *const hBin, int index)
Returns the source elevation for a given index, in METERS.
void binauraliserNF_destroy(void **const phBin)
Destroys an instance of the binauraliser.
void binauraliserNF_setInputConfigPreset(void *const hBin, int newPresetID)
Loads an input preset (see SOURCE_CONFIG_PRESETS enum)
float binauraliserNF_getFarfieldThresh_m(void *const hBin)
Returns the distance considered to be the far field (beyond which no near field filtering is applied)...
void binauraliserNF_setSourceDist_m(void *const hBin, int index, float newDist_m)
Sets the panning distance for a specific channel index, in METERS.
float binauraliserNF_getFarfieldHeadroom(void *const hBin)
Returns the scaling factor to give the far field threshold headroom (useful for UI range limits)
void binauraliserNF_initCodec(void *const hBin)
Intialises the codec variables, based on current global/user parameters.
void binauraliserNF_create(void **const phBin)
Creates an instance of the binauraliser.
void binauraliserNF_process(void *const hBin, const float *const *inputs, float *const *outputs, int nInputs, int nOutputs, int nSamples)
Binauralises the input signals at the user specified directions.
void binauraliserNF_resetSourceDistances(void *const hBin)
Resets the source distances to the default far field distance.
Convolves input audio (up to 64 channels) with interpolated HRTFs in the time-frequency domain,...
void doaToIpsiInteraural(float azimuth, float elevation, float *alphaLR, float *betaLR)
Convert a frontal azimuth/elevation to a modified Interaural-Polar coordinate.
#define DEG2RAD(x)
Converts degrees to radians.
#define SAF_MAX(a, b)
Returns the maximum of the two values.
#define NUM_EARS
2 (true for most humans)
void utility_svvcopy(const float *a, const int len, float *c)
Single-precision, vector-vector copy, i.e.
void evalIIRTransferFunctionf(float *b_coeff, float *a_coeff, int nCoeffs, float *freqs, int nFreqs, float fs, int mag2dB, float *magnitude, float *phase_rad)
Computes magnitude and phase response of an IIR filter from its coefficients (floats) at user-specifi...
#define SAF_MIN(a, b)
Returns the minimum of the two values.
void yawPitchRoll2Rzyx(float yaw, float pitch, float roll, int rollPitchYawFLAG, float R[3][3])
Constructs a 3x3 rotation matrix from the Euler angles, using the yaw-pitch-roll (zyx) convention.
void calcDVFCoeffs(float alpha, float rho, float fs, float *b, float *a)
Calculate the Distance Variation Function (DVF) filter coefficients, as described in [1].
void utility_svsmul(float *a, const float *s, const int len, float *c)
Single-precision, multiplies each element in vector 'a' with a scalar 's', i.e.
#define RAD2DEG(x)
Converts radians to degrees.
void ** malloc2d(size_t dim1, size_t dim2, size_t data_size)
2-D malloc (contiguously allocated, so use free() as usual to deallocate)
Definition md_malloc.c:89
void * malloc1d(size_t dim1_data_size)
1-D malloc (same as malloc, but with error checking)
Definition md_malloc.c:59
void *** malloc3d(size_t dim1, size_t dim2, size_t dim3, size_t data_size)
3-D malloc (contiguously allocated, so use free() as usual to deallocate)
Definition md_malloc.c:151
#define FLATTEN3D(A)
Use this macro when passing a 3-D dynamic multi-dimensional array to memset, memcpy or any other func...
Definition md_malloc.h:72
Main structure for binauraliser.
_Atomic_INT32 reInitHRTFsAndGainTables
1: reinitialise the HRTFs and interpolation tables, 0: do not
char * progressBarText
Current (re)initialisation step, string.
_Atomic_PROC_STATUS procStatus
see PROC_STATUS
_Atomic_FLOAT32 progressBar0_1
Current (re)initialisation progress, between [0..1].
_Atomic_CODEC_STATUS codecStatus
see CODEC_STATUS
Main structure for binauraliserNF.
_Atomic_INT32 recalc_dvfCoeffFLAG[MAX_NUM_INPUTS]
1: re-calculate the DVF coefficients on change in distance, 0: do not.
_Atomic_INT32 useRollPitchYawFlag
rotation order flag, 1: r-p-y, 0: y-p-r
float * itds_s
interaural-time differences for each HRIR (in seconds); nBands x 1
char * sofa_filepath
absolute/relevative file path for a sofa file
float * hrir_dirs_deg
directions of the HRIRs in degrees [azi elev]; FLAT: N_hrir_dirs x 2
_Atomic_INT32 bFlipPitch
flag to flip the sign of the pitch rotation angle
float_complex *** outputframeTF
time-frequency domain input frame; HYBRID_BANDS x NUM_EARS x TIME_SLOTS
_Atomic_FLOAT32 src_dists_m[MAX_NUM_INPUTS]
Source distance, meters.
float_complex * hrtf_fb
hrtf filterbank coefficients; nBands x nCH x N_hrirs
_Atomic_INT32 enableRotation
1: enable rotation, 0: disable
_Atomic_PROC_STATUS procStatus
see PROC_STATUS
int N_hrtf_vbap_gtable
Number of interpolation weights/directions.
_Atomic_INT32 N_hrir_dirs
number of HRIR directions in the current sofa file
float src_dirs_rot_deg[MAX_NUM_INPUTS][2]
Intermediate rotated source directions, in degrees.
_Atomic_FLOAT32 pitch
pitch (Euler) rotation angle, in degrees
_Atomic_FLOAT32 progressBar0_1
Current (re)initialisation progress, between [0..1].
float * hrirs
time domain HRIRs; FLAT: N_hrir_dirs x NUM_EARS x hrir_len
_Atomic_INTERP_MODES interpMode
see INTERP_MODES
int nTriangles
Number of triangles in the convex hull of the spherical arrangement of HRIR directions/points.
_Atomic_FLOAT32 yaw
yaw (Euler) rotation angle, in degrees
float ** inputFrameTD
time-domain input frame; MAX_NUM_INPUTS x BINAURALISER_FRAME_SIZE
char * progressBarText
Current (re)initialisation step, string.
float head_radius_recip
Reciprocal of head radius.
float dvfphases[MAX_NUM_INPUTS][NUM_EARS][HYBRID_BANDS]
DVF filter frequency band phases.
float a_dvf[MAX_NUM_INPUTS][NUM_EARS][2]
shelf IIR denominator coefficients for each input, left and right.
_Atomic_INT32 useDefaultHRIRsFLAG
1: use default HRIRs in database, 0: use those from SOFA file
float * hrtf_fb_mag
magnitudes of the hrtf filterbank coefficients; nBands x nCH x N_hrirs
float * weights
Integration weights for the HRIR measurement grid; N_hrir_dirs x 1.
_Atomic_INT32 bFlipYaw
flag to flip the sign of the yaw rotation angle
float farfield_thresh_m
Distance considered to be far field (no near field filtering), meters.
float freqVector[HYBRID_BANDS]
Frequency vector (filterbank centre frequencies)
float_complex *** inputframeTF
time-frequency domain input frame; HYBRID_BANDS x MAX_NUM_INPUTS x TIME_SLOTS
_Atomic_INT32 hrir_loaded_fs
sampling rate of the loaded HRIRs
int fs
Host sampling rate, in Hz.
int * hrtf_vbap_gtableIdx
N_hrtf_vbap_gtable x 3.
_Atomic_FLOAT32 src_gains[MAX_NUM_INPUTS]
Gains applied per source.
float src_dirs_cur[MAX_NUM_INPUTS][2]
Pointer to assign to the current HRTF directions being operated on (non/rotated directions switch).
_Atomic_INT32 hrir_loaded_len
length of the loaded HRIRs, in samples
_Atomic_INT32 nSources
Current number of input/source signals.
_Atomic_INT32 hrir_runtime_len
length of the HRIRs being used for processing (after any resampling), in samples
float src_dirs_rot_xyz[MAX_NUM_INPUTS][3]
Intermediate rotated source directions, as unit-length Cartesian coordinates.
float dvfmags[MAX_NUM_INPUTS][NUM_EARS][HYBRID_BANDS]
DVF filter frequency band magnitudes.
float_complex hrtf_interp[MAX_NUM_INPUTS][HYBRID_BANDS][NUM_EARS]
Interpolated HRTFs.
float farfield_headroom
Scale factor applied to farfield_thresh_m when resetting to the far field, and for UI range,...
float head_radius
Head radius, used calculate normalized source distance meters, def.
_Atomic_INT32 reInitHRTFsAndGainTables
1: reinitialise the HRTFs and interpolation tables, 0: do not
_Atomic_INT32 hrir_runtime_fs
sampling rate of the HRIRs being used for processing (after any resampling)
_Atomic_INT32 recalc_hrtf_interpFLAG[MAX_NUM_INPUTS]
1: re-calculate/interpolate the HRTF, 0: do not
float b_dvf[MAX_NUM_INPUTS][NUM_EARS][2]
shelf IIR numerator coefficients for each input, left and right.
_Atomic_CODEC_STATUS codecStatus
see CODEC_STATUS
_Atomic_INT32 bFlipRoll
flag to flip the sign of the roll rotation angle
float ** outframeTD
time-domain output frame; NUM_EARS x BINAURALISER_FRAME_SIZE
float nearfield_limit_m
Minimum distance allowed for near-field filtering, from head center, meters, def.
float src_dirs_xyz[MAX_NUM_INPUTS][3]
Intermediate source directions, as unit-length Cartesian coordinates.
_Atomic_INT32 enableHRIRsDiffuseEQ
flag to diffuse-field equalisation to the currently loaded HRTFs
float * hrtf_vbap_gtableComp
N_hrtf_vbap_gtable x 3.
_Atomic_INT32 new_nSources
New number of input/source signals (current value will be replaced by this after next re-init)
_Atomic_INT32 recalc_M_rotFLAG
1: re-calculate the rotation matrix, 0: do not
_Atomic_FLOAT32 src_dirs_deg[MAX_NUM_INPUTS][2]
Current source/panning directions, in degrees.
_Atomic_FLOAT32 roll
roll (Euler) rotation angle, in degrees