SAF
Loading...
Searching...
No Matches
ambi_bin.c
Go to the documentation of this file.
1/*
2 * Copyright 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
47
48#include "ambi_bin_internal.h"
49
51(
52 void ** const phAmbi
53)
54{
56 *phAmbi = (void*)pData;
57
58 /* default user parameters */
59 pData->useDefaultHRIRsFLAG = 1; /* pars->sofa_filepath must be valid to set this to 0 */
60 pData->preProc = HRIR_PREPROC_EQ;
61 pData->chOrdering = CH_ACN;
62 pData->norm = NORM_SN3D;
63 pData->enableMaxRE = 1;
64 pData->enableDiffuseMatching = 0;
65 pData->enableTruncationEQ = 1;
66 pData->enableRotation = 0;
67 pData->yaw = 0.0f;
68 pData->pitch = 0.0f;
69 pData->roll = 0.0f;
70 pData->bFlipYaw = 0;
71 pData->bFlipPitch = 0;
72 pData->bFlipRoll = 0;
73 pData->useRollPitchYawFlag = 0;
75 pData->order = pData->new_order = 1;
76 pData->nSH = (pData->order+1)*(pData->order+1);
77
78 /* afSTFT and audio buffers */
79 pData->fs = 48000;
80 pData->hSTFT = NULL;
81 pData->SHFrameTD = (float**)malloc2d(MAX_NUM_SH_SIGNALS, AMBI_BIN_FRAME_SIZE, sizeof(float));
82 pData->binFrameTD = (float**)malloc2d(NUM_EARS, AMBI_BIN_FRAME_SIZE, sizeof(float));
83 pData->SHframeTF = (float_complex***)malloc3d(HYBRID_BANDS, MAX_NUM_SH_SIGNALS, TIME_SLOTS, sizeof(float_complex));
84 pData->binframeTF = (float_complex***)malloc3d(HYBRID_BANDS, NUM_EARS, TIME_SLOTS, sizeof(float_complex));
85 afSTFT_getCentreFreqs(pData->hSTFT, (float)pData->fs, HYBRID_BANDS, (float*)pData->freqVector);
86
87 /* codec data */
88 pData->progressBar0_1 = 0.0f;
90 strcpy(pData->progressBarText,"");
92 ambi_bin_codecPars* pars = pData->pars;
93 pars->sofa_filepath = NULL;
94 pars->hrirs = NULL;
95 pars->hrir_dirs_deg = NULL;
96 pars->itds_s = NULL;
97 pars->hrtf_fb = NULL;
98 pars->weights = NULL;
99
100 /* flags */
103 pData->recalc_M_rotFLAG = 1;
104 pData->reinit_hrtfsFLAG = 1;
105}
106
108(
109 void ** const phAmbi
110)
111{
112 ambi_bin_data *pData = (ambi_bin_data*)(*phAmbi);
113 ambi_bin_codecPars *pars;
114
115 if (pData != NULL) {
116 /* not safe to free memory during intialisation/processing loop */
117 while (pData->codecStatus == CODEC_STATUS_INITIALISING ||
119 SAF_SLEEP(10);
120 }
121
122 /* free afSTFT and buffers */
123 afSTFT_destroy(&(pData->hSTFT));
124 free(pData->SHFrameTD);
125 free(pData->binFrameTD);
126 free(pData->SHframeTF);
127 free(pData->binframeTF);
128
129 pars = pData->pars;
130 free(pars->sofa_filepath);
131 free(pars->weights);
132 free(pars->hrtf_fb);
133 free(pars->itds_s);
134 free(pars->hrirs);
135 free(pars->hrir_dirs_deg);
136 free(pars);
137 free(pData->progressBarText);
138
139 free(pData);
140 pData = NULL;
141 *phAmbi = NULL;
142 }
143}
144
146(
147 void * const hAmbi,
148 int sampleRate
149)
150{
151 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
152
153 /* define frequency vector */
154 if(pData->fs != sampleRate){
155 pData->fs = sampleRate;
156 pData->reinit_hrtfsFLAG = 1;
158 }
159 afSTFT_getCentreFreqs(pData->hSTFT, (float)pData->fs, HYBRID_BANDS, (float*)pData->freqVector);
160
161 /* default starting values */
162 pData->recalc_M_rotFLAG = 1;
163}
164
166(
167 void* const hAmbi
168)
169{
170 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
171 ambi_bin_codecPars* pars = pData->pars;
172 int i, j, nSH, order, band;
173#ifdef SAF_ENABLE_SOFA_READER_MODULE
176#endif
177
179 return; /* re-init not required, or already happening */
180 while (pData->procStatus == PROC_STATUS_ONGOING){
181 /* re-init required, but we need to wait for the current processing loop to end */
182 pData->codecStatus = CODEC_STATUS_INITIALISING; /* indicate that we want to init */
183 SAF_SLEEP(10);
184 }
185
186 /* for progress bar */
188 strcpy(pData->progressBarText,"Preparing HRIRs");
189 pData->progressBar0_1 = 0.0f;
190
191 /* (Re)Initialise afSTFT */
192 order = pData->new_order;
193 nSH = (order+1)*(order+1);
194 if(pData->hSTFT==NULL)
196 else if(pData->nSH != nSH) {/* Or change the number of channels */
197 afSTFT_channelChange(pData->hSTFT, nSH, NUM_EARS);
199 }
200 pData->nSH = nSH;
201
202 if(pData->reinit_hrtfsFLAG){
203 /* load sofa file or default hrir data */
204 strcpy(pData->progressBarText,"Preparing HRIRs");
205 pData->progressBar0_1 = 0.15f;
206 /* load sofa file or load default hrir data */
207#ifdef SAF_ENABLE_SOFA_READER_MODULE
208 if(!pData->useDefaultHRIRsFLAG && pars->sofa_filepath!=NULL){
209 /* Load SOFA file */
211
212 /* Load defaults instead */
213 if(error!=SAF_SOFA_OK || sofa.nReceivers!=NUM_EARS){
214 pData->useDefaultHRIRsFLAG = 1;
215 saf_print_warning("Unable to load the specified SOFA file, or it contained something other than 2 channels. Using default HRIR data instead.");
216 }
217 else{
218 /* Copy SOFA data */
219 pars->hrir_fs = (int)sofa.DataSamplingRate;
220 pars->hrir_len = sofa.DataLengthIR;
221 pars->N_hrir_dirs = sofa.nSources;
222 pars->hrirs = realloc1d(pars->hrirs, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
223 memcpy(pars->hrirs, sofa.DataIR, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
224 pars->hrir_dirs_deg = realloc1d(pars->hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
225 cblas_scopy(pars->N_hrir_dirs, sofa.SourcePosition, 3, pars->hrir_dirs_deg, 2); /* azi */
226 cblas_scopy(pars->N_hrir_dirs, &sofa.SourcePosition[1], 3, &pars->hrir_dirs_deg[1], 2); /* elev */
227 }
228
229 /* Clean-up */
230 saf_sofa_close(&sofa);
231 }
232#else
233 pData->useDefaultHRIRsFLAG = 1; /* Can only load the default HRIR data */
234#endif
235 if(pData->useDefaultHRIRsFLAG){
236 /* Copy default HRIR data */
240 pars->hrirs = realloc1d(pars->hrirs, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
241 memcpy(pars->hrirs, (float*)__default_hrirs, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
242 pars->hrir_dirs_deg = realloc1d(pars->hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
243 memcpy(pars->hrir_dirs_deg, (float*)__default_hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
244 }
245
246 /* convert hrirs to filterbank coefficients */
247 pData->progressBar0_1 = 0.4f;
248 pars->hrtf_fb = realloc1d(pars->hrtf_fb, HYBRID_BANDS * NUM_EARS * (pars->N_hrir_dirs)*sizeof(float_complex));
249 HRIRs2HRTFs_afSTFT(pars->hrirs, pars->N_hrir_dirs, pars->hrir_len, HOP_SIZE, 0, 1, pars->hrtf_fb);
250 /* HRIR pre-processing */
251 if(pData->preProc == HRIR_PREPROC_EQ || pData->preProc == HRIR_PREPROC_ALL){
252 /* get integration weights */
253 strcpy(pData->progressBarText,"Applying HRIR diffuse-field EQ");
254 pData->progressBar0_1 = 0.5f;
255 if(pars->N_hrir_dirs<=3600){
256 pars->weights = realloc1d(pars->weights, pars->N_hrir_dirs*sizeof(float));
257 //getVoronoiWeights(pars->hrir_dirs_deg, pars->N_hrir_dirs, 0, pars->weights);
258 float * hrir_dirs_rad = (float*) malloc1d(pars->N_hrir_dirs*2*sizeof(float));
259 memcpy(hrir_dirs_rad, pars->hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
260 cblas_sscal(pars->N_hrir_dirs*2, SAF_PI/180.f, hrir_dirs_rad, 1);
261 sphElev2incl(hrir_dirs_rad, pars->N_hrir_dirs, 0, hrir_dirs_rad);
262 int supOrder = calculateGridWeights(hrir_dirs_rad, pars->N_hrir_dirs, -1, pars->weights);
263 if(supOrder < 1){
264 saf_print_warning("Could not calculate grid weights");
265 free(pars->weights);
266 pars->weights = NULL;
267 }
268 }
269 else{
270 saf_print_warning("Too many grid points to calculate grid weights. Assuming that the HRTF measurement grid was uniform.");
271 free(pars->weights);
272 pars->weights = NULL;
273 }
274 }
275
276 /* estimate the ITDs for each HRIR */
277 pData->progressBar0_1 = 0.6f;
278 pars->itds_s = realloc1d(pars->itds_s, pars->N_hrir_dirs*sizeof(float));
279 estimateITDs(pars->hrirs, pars->N_hrir_dirs, pars->hrir_len, pars->hrir_fs, pars->itds_s);
280
281 /* apply HRIR pre-processing */
282 pData->progressBar0_1 = 0.75f;
284 pData->preProc == HRIR_PREPROC_EQ || pData->preProc == HRIR_PREPROC_ALL ? 1 : 0, /* Apply Diffuse-field EQ? */
285 pData->preProc == HRIR_PREPROC_PHASE || pData->preProc == HRIR_PREPROC_ALL ? 1 : 0, /* Apply phase simplification EQ? */
286 pars->hrtf_fb);
287 pData->reinit_hrtfsFLAG = 0;
288 }
289
290 /* get new decoder */
291 strcpy(pData->progressBarText,"Computing Decoder");
292 pData->progressBar0_1 = 0.95f;
293 float_complex* decMtx;
294 decMtx = calloc1d(HYBRID_BANDS*NUM_EARS*nSH, sizeof(float_complex));
295 switch(pData->method){
296 default:
299 BINAURAL_DECODER_LS, order, pData->freqVector, pars->itds_s, pars->weights,
300 pData->enableDiffuseMatching, pData->enableMaxRE, decMtx);
301 break;
304 BINAURAL_DECODER_LSDIFFEQ, order, pData->freqVector, pars->itds_s, pars->weights,
305 pData->enableDiffuseMatching, pData->enableMaxRE, decMtx);
306 break;
309 BINAURAL_DECODER_SPR, order, pData->freqVector, pars->itds_s, pars->weights,
310 pData->enableDiffuseMatching, pData->enableMaxRE, decMtx);
311 break;
314 BINAURAL_DECODER_TA, order, pData->freqVector, pars->itds_s, pars->weights,
315 pData->enableDiffuseMatching, pData->enableMaxRE, decMtx);
316 break;
319 BINAURAL_DECODER_MAGLS, order, pData->freqVector, pars->itds_s, pars->weights,
320 pData->enableDiffuseMatching, pData->enableMaxRE, decMtx);
321 break;
322 }
323
324 /* Apply Truncation EQ */
325 if(pData->enableTruncationEQ &&
326 pData->method==DECODING_METHOD_LS &&
327 pData->preProc!=HRIR_PREPROC_PHASE &&
329 {
330 double *kr;
331 float *w_n, *eqGain;
332 const int order_truncated = order;
333 const int order_target = 42; /* Equalizing diffuse field to 42nd order equivalent. */
334 const float softThreshold = 9.0; /* results in +9 dB max */
335 const double r = 0.085; /* spherical scatterer radius (approx. size of human head) */
336 const int numBands = HYBRID_BANDS;
337 const double c = 343.;
338
339 /* Prep */
340 kr = malloc1d(numBands * sizeof(double));
341 w_n = calloc1d((order_truncated+1), sizeof(float));
342 eqGain = calloc1d(numBands, sizeof(float));
343 for (int k=0; k<numBands; k++)
344 kr[k] = 2.0*SAF_PId / c * (double)pData->freqVector[k] * r;
345
346 if (pData->enableMaxRE) {
347 /* maxRE as order weighting */
348 float *maxRECoeffs = malloc1d((order_truncated+1) * sizeof(float));
349 beamWeightsMaxEV(order_truncated, maxRECoeffs);
350 for (int idx_n=0; idx_n<order_truncated+1; idx_n++) {
351 w_n[idx_n] = maxRECoeffs[idx_n];
352 w_n[idx_n] /= sqrtf((float)(2*idx_n+1) / (4.0f*SAF_PI));
353 }
354 float w_0 = w_n[0];
355 for (int idx_n=0; idx_n<order_truncated+1; idx_n++)
356 w_n[idx_n] /= w_0;
357 free(maxRECoeffs);
358 }
359 else {
360 /* just truncation, no tapering */
361 for (int idx_n=0; idx_n<order_truncated+1; idx_n++)
362 w_n[idx_n] = 1.0f;
363 }
364 truncationEQ(w_n, order_truncated, order_target, kr, numBands, softThreshold, eqGain);
365
366 /* apply to decoding matrix */
367 for (int idxBand=0; idxBand<numBands; idxBand++){
368 for (int idxSH=0; idxSH<pData->nSH; idxSH++){
369 decMtx[idxBand*NUM_EARS*nSH+0*nSH+idxSH] = crmulf(decMtx[idxBand*NUM_EARS*nSH+0*nSH+idxSH], eqGain[idxBand]); /* left ear */
370 decMtx[idxBand*NUM_EARS*nSH+1*nSH+idxSH] = crmulf(decMtx[idxBand*NUM_EARS*nSH+1*nSH+idxSH], eqGain[idxBand]); /* right ear */
371 }
372 }
373
374 /* clean-up */
375 free(kr);
376 free(w_n);
377 free(eqGain);
378 }
379
380 /* replace current decoder */
381 memset(pars->M_dec, 0, HYBRID_BANDS*NUM_EARS*MAX_NUM_SH_SIGNALS*sizeof(float_complex));
382 for(band=0; band<HYBRID_BANDS; band++)
383 for(i=0; i<NUM_EARS; i++)
384 for(j=0; j<nSH; j++)
385 pars->M_dec[band][i][j] = decMtx[band*NUM_EARS*nSH + i*nSH + j];
386 free(decMtx);
387
388 /* rotation matrix will need to be updated too */
389 pData->recalc_M_rotFLAG = 1;
390
391 pData->order = order;
392
393 /* done! */
394 strcpy(pData->progressBarText,"Done!");
395 pData->progressBar0_1 = 1.0f;
397}
398
400(
401 void * const hAmbi,
402 const float *const * inputs,
403 float* const* const outputs,
404 int nInputs,
405 int nOutputs,
406 int nSamples
407)
408{
409 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
410 ambi_bin_codecPars* pars = pData->pars;
411 int ch, i, j, band;
412 const float_complex calpha = cmplxf(1.0f,0.0f), cbeta = cmplxf(0.0f, 0.0f);
413 float Rxyz[3][3];
414 float M_rot_tmp[MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS];
415
416 /* local copies of user parameters */
417 int order, nSH, enableRot;
418 NORM_TYPES norm;
419 CH_ORDER chOrdering;
420 norm = pData->norm;
421 chOrdering = pData->chOrdering;
422 order = pData->order;
423 nSH = (order+1)*(order+1);
424 enableRot = pData->enableRotation;
425
426 /* Process frame */
427 if (nSamples == AMBI_BIN_FRAME_SIZE && (pData->codecStatus == CODEC_STATUS_INITIALISED) ) {
429
430 /* Load time-domain data */
431 for(i=0; i < SAF_MIN(nSH, nInputs); i++)
432 utility_svvcopy(inputs[i], AMBI_BIN_FRAME_SIZE, pData->SHFrameTD[i]);
433 for(; i<nSH; i++)
434 memset(pData->SHFrameTD[i], 0, AMBI_BIN_FRAME_SIZE * sizeof(float)); /* fill remaining channels with zeros */
435
436 /* account for channel order convention */
437 switch(chOrdering){
438 case CH_ACN: /* already in ACN, do nothing */ break; /* Otherwise, convert to ACN... */
440 }
441
442 /* account for input normalisation scheme */
443 switch(norm){
444 case NORM_N3D: /* already in N3D, do nothing */ break; /* Otherwise, convert to N3D... */
447 }
448
449 /* Apply time-frequency transform (TFT) */
451
452 /* Main processing: */
453 if(order > 0 && enableRot) {
454 /* Apply rotation */
455 if(pData->recalc_M_rotFLAG){
456 /* Compute the new SH rotation matrix */
457 memset(pData->M_rot, 0, MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS*sizeof(float_complex));
458 yawPitchRoll2Rzyx(pData->yaw, pData->pitch, pData->roll, pData->useRollPitchYawFlag, Rxyz);
459 getSHrotMtxReal(Rxyz, (float*)M_rot_tmp, order);
460 for (i = 0; i < nSH; i++)
461 for (j = 0; j < nSH; j++)
462 pData->M_rot[i][j] = cmplxf(M_rot_tmp[i*nSH + j], 0.0f);
463
464 /* Bake the rotation into the decoding matrix */
465 for(band = 0; band < HYBRID_BANDS; band++) {
466 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, NUM_EARS, nSH, nSH, &calpha,
467 pars->M_dec[band], MAX_NUM_SH_SIGNALS,
468 pData->M_rot, MAX_NUM_SH_SIGNALS, &cbeta,
469 pars->M_dec_rot[band], MAX_NUM_SH_SIGNALS);
470 }
471 pData->recalc_M_rotFLAG = 0;
472 }
473 }
474
475 /* Apply the decoder to go from SH input to binaural output */
476 for(band = 0; band < HYBRID_BANDS; band++) {
477 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, NUM_EARS, TIME_SLOTS, nSH, &calpha,
478 enableRot ? pars->M_dec_rot[band] : pars->M_dec[band], MAX_NUM_SH_SIGNALS,
479 FLATTEN2D(pData->SHframeTF[band]), TIME_SLOTS, &cbeta,
480 FLATTEN2D(pData->binframeTF[band]), TIME_SLOTS);
481 }
482
483 /* inverse-TFT */
485
486 /* Copy to output */
487 for (ch = 0; ch < SAF_MIN(NUM_EARS, nOutputs); ch++)
488 utility_svvcopy(pData->binFrameTD[ch], AMBI_BIN_FRAME_SIZE, outputs[ch]);
489 for (; ch < nOutputs; ch++)
490 memset(outputs[ch], 0, AMBI_BIN_FRAME_SIZE*sizeof(float));
491 }
492 else
493 for (ch=0; ch < nOutputs; ch++)
494 memset(outputs[ch],0, AMBI_BIN_FRAME_SIZE*sizeof(float));
495
497}
498
499
500/* Set Functions */
501
502void ambi_bin_refreshParams(void* const hAmbi)
503{
504 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
505 pData->reinit_hrtfsFLAG = 1;
507}
508
509void ambi_bin_setUseDefaultHRIRsflag(void* const hAmbi, int newState)
510{
511 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
512
513 if((!pData->useDefaultHRIRsFLAG) && (newState)){
514 pData->useDefaultHRIRsFLAG = newState;
515 ambi_bin_refreshParams(hAmbi); // re-init and re-calc
516 }
517}
518
519void ambi_bin_setSofaFilePath(void* const hAmbi, const char* path)
520{
521 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
522 ambi_bin_codecPars* pars = pData->pars;
523
524 pars->sofa_filepath = realloc1d(pars->sofa_filepath, strlen(path) + 1);
525 strcpy(pars->sofa_filepath, path);
526 pData->useDefaultHRIRsFLAG = 0;
527 ambi_bin_refreshParams(hAmbi); // re-init and re-calc
528
529}
530
531void ambi_bin_setInputOrderPreset(void* const hAmbi, SH_ORDERS newOrder)
532{
533 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
534 if(pData->order != (int)newOrder){
535 pData->new_order = (int)newOrder;
537 }
538 /* FUMA only supports 1st order */
539 if(pData->new_order!=SH_ORDER_FIRST && pData->chOrdering == CH_FUMA)
540 pData->chOrdering = CH_ACN;
541 if(pData->new_order!=SH_ORDER_FIRST && pData->norm == NORM_FUMA)
542 pData->norm = NORM_SN3D;
543}
544
546{
547 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
548 pData->method = newMethod;
550}
551
552void ambi_bin_setChOrder(void* const hAmbi, int newOrder)
553{
554 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
555 if((CH_ORDER)newOrder != CH_FUMA || pData->new_order==SH_ORDER_FIRST)/* FUMA only supports 1st order */
556 pData->chOrdering = (CH_ORDER)newOrder;
557}
558
559void ambi_bin_setNormType(void* const hAmbi, int newType)
560{
561 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
562 if((NORM_TYPES)newType != NORM_FUMA || pData->new_order==SH_ORDER_FIRST)/* FUMA only supports 1st order */
563 pData->norm = (NORM_TYPES)newType;
564}
565
566void ambi_bin_setEnableMaxRE(void* const hAmbi, int newState)
567{
568 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
569 if(pData->enableMaxRE != newState){
570 pData->enableMaxRE = newState;
572 }
573}
574
575void ambi_bin_setEnableDiffuseMatching(void* const hAmbi, int newState)
576{
577 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
578 if(pData->enableDiffuseMatching != newState){
579 pData->enableDiffuseMatching = newState;
581 }
582}
583
584void ambi_bin_setEnableTruncationEQ(void* const hAmbi, int newState)
585{
586 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
587 if(pData->enableTruncationEQ != newState){
588 pData->enableTruncationEQ = newState;
590 }
591}
592
593void ambi_bin_setHRIRsPreProc(void* const hAmbi, AMBI_BIN_PREPROC newType)
594{
595 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
596 if(pData->preProc != newType){
597 pData->preProc = newType;
599 }
600}
601
602void ambi_bin_setEnableRotation(void* const hAmbi, int newState)
603{
604 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
605 pData->enableRotation = newState;
606}
607
608void ambi_bin_setYaw(void * const hAmbi, float newYaw)
609{
610 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
611 pData->yaw = pData->bFlipYaw == 1 ? -DEG2RAD(newYaw) : DEG2RAD(newYaw);
612 pData->recalc_M_rotFLAG = 1;
613}
614
615void ambi_bin_setPitch(void* const hAmbi, float newPitch)
616{
617 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
618 pData->pitch = pData->bFlipPitch == 1 ? -DEG2RAD(newPitch) : DEG2RAD(newPitch);
619 pData->recalc_M_rotFLAG = 1;
620}
621
622void ambi_bin_setRoll(void* const hAmbi, float newRoll)
623{
624 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
625 pData->roll = pData->bFlipRoll == 1 ? -DEG2RAD(newRoll) : DEG2RAD(newRoll);
626 pData->recalc_M_rotFLAG = 1;
627}
628
629void ambi_bin_setFlipYaw(void* const hAmbi, int newState)
630{
631 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
632 if(newState !=pData->bFlipYaw ){
633 pData->bFlipYaw = newState;
634 ambi_bin_setYaw(hAmbi, -ambi_bin_getYaw(hAmbi));
635 }
636}
637
638void ambi_bin_setFlipPitch(void* const hAmbi, int newState)
639{
640 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
641 if(newState !=pData->bFlipPitch ){
642 pData->bFlipPitch = newState;
643 ambi_bin_setPitch(hAmbi, -ambi_bin_getPitch(hAmbi));
644 }
645}
646
647void ambi_bin_setFlipRoll(void* const hAmbi, int newState)
648{
649 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
650 if(newState !=pData->bFlipRoll ){
651 pData->bFlipRoll = newState;
652 ambi_bin_setRoll(hAmbi, -ambi_bin_getRoll(hAmbi));
653 }
654}
655
656void ambi_bin_setRPYflag(void* const hAmbi, int newState)
657{
658 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
659 pData->useRollPitchYawFlag = newState;
660}
661
662
663/* Get Functions */
664
666{
667 return AMBI_BIN_FRAME_SIZE;
668}
669
671{
672 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
673 return pData->codecStatus;
674}
675
676float ambi_bin_getProgressBar0_1(void* const hAmbi)
677{
678 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
679 return pData->progressBar0_1;
680}
681
682void ambi_bin_getProgressBarText(void* const hAmbi, char* text)
683{
684 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
685 memcpy(text, pData->progressBarText, PROGRESSBARTEXT_CHAR_LENGTH*sizeof(char));
686}
687
689{
690 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
691 return pData->useDefaultHRIRsFLAG;
692}
693
695{
696 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
697 return pData->preProc;
698}
699
700int ambi_bin_getInputOrderPreset(void* const hAmbi)
701{
702 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
703 return pData->new_order;
704}
705
707{
708 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
709 return pData->method;
710}
711
712char* ambi_bin_getSofaFilePath(void* const hAmbi)
713{
714 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
715 ambi_bin_codecPars* pars = pData->pars;
716 if(pars->sofa_filepath!=NULL)
717 return pars->sofa_filepath;
718 else
719 return "/Spatial_Audio_Framework/Default";
720}
721
722int ambi_bin_getChOrder(void* const hAmbi)
723{
724 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
725 return (int)pData->chOrdering;
726}
727
728int ambi_bin_getNormType(void* const hAmbi)
729{
730 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
731 return (int)pData->norm;
732}
733
734int ambi_bin_getEnableMaxRE(void* const hAmbi)
735{
736 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
737 return pData->enableMaxRE;
738}
739
741{
742 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
743 return pData->enableDiffuseMatching;
744}
745
746int ambi_bin_getEnableTruncationEQ(void* const hAmbi)
747{
748 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
749 return pData->enableTruncationEQ;
750}
751
753{
754 return NUM_EARS;
755}
756
757int ambi_bin_getNSHrequired(void* const hAmbi)
758{
759 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
760 return pData->nSH;
761}
762
763int ambi_bin_getEnableRotation(void* const hAmbi)
764{
765 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
766 return pData->enableRotation;
767}
768
769float ambi_bin_getYaw(void* const hAmbi)
770{
771 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
772 return pData->bFlipYaw == 1 ? -RAD2DEG(pData->yaw) : RAD2DEG(pData->yaw);
773}
774
775float ambi_bin_getPitch(void* const hAmbi)
776{
777 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
778 return pData->bFlipPitch == 1 ? -RAD2DEG(pData->pitch) : RAD2DEG(pData->pitch);
779}
780
781float ambi_bin_getRoll(void* const hAmbi)
782{
783 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
784 return pData->bFlipRoll == 1 ? -RAD2DEG(pData->roll) : RAD2DEG(pData->roll);
785}
786
787int ambi_bin_getFlipYaw(void* const hAmbi)
788{
789 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
790 return pData->bFlipYaw;
791}
792
793int ambi_bin_getFlipPitch(void* const hAmbi)
794{
795 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
796 return pData->bFlipPitch;
797}
798
799int ambi_bin_getFlipRoll(void* const hAmbi)
800{
801 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
802 return pData->bFlipRoll;
803}
804
805int ambi_bin_getRPYflag(void* const hAmbi)
806{
807 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
808 return pData->useRollPitchYawFlag;
809}
810
811int ambi_bin_getNDirs(void* const hAmbi)
812{
813 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
814 ambi_bin_codecPars* pars = pData->pars;
815 return pars->N_hrir_dirs;
816}
817
818int ambi_bin_getHRIRlength(void* const hAmbi)
819{
820 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
821 ambi_bin_codecPars* pars = pData->pars;
822 return pars->hrir_len;
823}
824
825int ambi_bin_getHRIRsamplerate(void* const hAmbi)
826{
827 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
828 ambi_bin_codecPars* pars = pData->pars;
829 return pars->hrir_fs;
830}
831
832int ambi_bin_getDAWsamplerate(void* const hAmbi)
833{
834 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
835 return pData->fs;
836}
837
839{
840 return 12*HOP_SIZE;
841}
#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
NORM_TYPES
Available Ambisonic normalisation conventions.
Definition _common.h:78
@ NORM_SN3D
Schmidt semi-normalisation (SN3D)
Definition _common.h:80
@ NORM_FUMA
(Legacy) Furse-Malham scaling
Definition _common.h:81
@ NORM_N3D
orthonormalised (N3D)
Definition _common.h:79
CH_ORDER
Available Ambisonic channel ordering conventions.
Definition _common.h:63
@ CH_ACN
Ambisonic Channel Numbering (ACN)
Definition _common.h:64
@ CH_FUMA
(Legacy) Furse-Malham/B-format (WXYZ)
Definition _common.h:65
#define MAX_NUM_SH_SIGNALS
Maximum number of spherical harmonic components/signals supported.
Definition _common.h:243
SH_ORDERS
Available spherical harmonic (SH) input/output order options.
Definition _common.h:42
@ SH_ORDER_FIRST
First-order (4 channels)
Definition _common.h:43
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_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_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_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_getCentreFreqs(void *const hSTFT, float fs, int nBands, float *freqVector)
Returns current frequency vector.
Definition afSTFTlib.c:546
void afSTFT_destroy(void **const phSTFT)
Destroys an instance of afSTFT.
Definition afSTFTlib.c:199
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
void ambi_bin_setChOrder(void *const hAmbi, int newOrder)
Sets the Ambisonic channel ordering convention to decode with, in order to match the convention emplo...
Definition ambi_bin.c:552
int ambi_bin_getNSHrequired(void *const hAmbi)
Returns the number of spherical harmonic signals required by the current decoding order: (current_ord...
Definition ambi_bin.c:757
int ambi_bin_getEnableMaxRE(void *const hAmbi)
Returns the flag value which dictates whether to enable/disable maxrE weighting ('0' disabled,...
Definition ambi_bin.c:734
int ambi_bin_getHRIRsamplerate(void *const hAmbi)
Returns the HRIR sample rate.
Definition ambi_bin.c:825
int ambi_bin_getNormType(void *const hAmbi)
Returns the Ambisonic normalisation convention currently being usedto decode with,...
Definition ambi_bin.c:728
void ambi_bin_setFlipRoll(void *const hAmbi, int newState)
Sets a flag as to whether to "flip" the sign of the current 'roll' angle.
Definition ambi_bin.c:647
void ambi_bin_setPitch(void *const hAmbi, float newPitch)
Sets the 'pitch' rotation angle, in degrees.
Definition ambi_bin.c:615
int ambi_bin_getProcessingDelay(void)
Returns the processing delay in samples (may be used for delay compensation features)
Definition ambi_bin.c:838
int ambi_bin_getEnableTruncationEQ(void *const hAmbi)
Returns the flag value which dictates whether the truncation EQ is currently enabled ('0' disabled,...
Definition ambi_bin.c:746
void ambi_bin_setYaw(void *const hAmbi, float newYaw)
Sets the 'yaw' rotation angle, in degrees.
Definition ambi_bin.c:608
int ambi_bin_getEnableDiffuseMatching(void *const hAmbi)
Returns the flag value which dictates whether the diffuse covariance contraint is currently enabled (...
Definition ambi_bin.c:740
AMBI_BIN_PREPROC ambi_bin_getHRIRsPreProc(void *const hAmbi)
Returns HRIR pre-processing strategy.
Definition ambi_bin.c:694
AMBI_BIN_DECODING_METHODS ambi_bin_getDecodingMethod(void *const hAmbi)
Returns the currently selected decoding method (see AMBI_BIN_DECODING_METHODS enum)
Definition ambi_bin.c:706
int ambi_bin_getDAWsamplerate(void *const hAmbi)
Returns the DAW/Host sample rate.
Definition ambi_bin.c:832
void ambi_bin_create(void **const phAmbi)
Creates an instance of ambi_bin.
Definition ambi_bin.c:51
void ambi_bin_setHRIRsPreProc(void *const hAmbi, AMBI_BIN_PREPROC newType)
Sets HRIR pre-processing strategy (see AMBI_BIN_PREPROC enum)
Definition ambi_bin.c:593
void ambi_bin_setFlipYaw(void *const hAmbi, int newState)
Sets a flag as to whether to "flip" the sign of the current 'yaw' angle.
Definition ambi_bin.c:629
void ambi_bin_setEnableMaxRE(void *const hAmbi, int newState)
Sets a flag to enable/disable the max_rE weighting.
Definition ambi_bin.c:566
void ambi_bin_setSofaFilePath(void *const hAmbi, const char *path)
Sets the file path for a .sofa file, in order to employ a custom HRIR set for the decoding.
Definition ambi_bin.c:519
int ambi_bin_getEnableRotation(void *const hAmbi)
Returns the flag value which dictates whether to enable/disable sound-field rotation ('0' disabled,...
Definition ambi_bin.c:763
int ambi_bin_getChOrder(void *const hAmbi)
Returns the Ambisonic channel ordering convention currently being used to decode with,...
Definition ambi_bin.c:722
int ambi_bin_getNumEars(void)
Returns the number of ears possessed by the average homo sapien (2)
Definition ambi_bin.c:752
void ambi_bin_initCodec(void *const hAmbi)
Intialises the codec variables, based on current global/user parameters.
Definition ambi_bin.c:166
void ambi_bin_process(void *const hAmbi, const float *const *inputs, float *const *const outputs, int nInputs, int nOutputs, int nSamples)
Decodes input spherical harmonic signals to the binaural channels.
Definition ambi_bin.c:400
float ambi_bin_getPitch(void *const hAmbi)
Returns the 'pitch' rotation angle, in degrees.
Definition ambi_bin.c:775
void ambi_bin_setFlipPitch(void *const hAmbi, int newState)
Sets a flag as to whether to "flip" the sign of the current 'pitch' angle.
Definition ambi_bin.c:638
int ambi_bin_getHRIRlength(void *const hAmbi)
Returns the length of HRIRs in time-domain samples.
Definition ambi_bin.c:818
float ambi_bin_getRoll(void *const hAmbi)
Returns the 'roll' rotation angle, in degrees.
Definition ambi_bin.c:781
void ambi_bin_setNormType(void *const hAmbi, int newType)
Sets the Ambisonic normalisation convention to decode with, in order to match with the convention emp...
Definition ambi_bin.c:559
void ambi_bin_setInputOrderPreset(void *const hAmbi, SH_ORDERS newOrder)
Sets the decoding order (see SH_ORDERS enum)
Definition ambi_bin.c:531
void ambi_bin_setEnableRotation(void *const hAmbi, int newState)
Sets the flag to enable/disable (1 or 0) sound-field rotation.
Definition ambi_bin.c:602
void ambi_bin_setRPYflag(void *const hAmbi, int newState)
Sets a flag as to whether to use "yaw-pitch-roll" (0) or "roll-pitch-yaw" (1) rotation order.
Definition ambi_bin.c:656
int ambi_bin_getFlipPitch(void *const hAmbi)
Returns a flag as to whether to "flip" the sign of the current 'pitch' angle ('0' do not flip sign,...
Definition ambi_bin.c:793
int ambi_bin_getFlipRoll(void *const hAmbi)
Returns a flag as to whether to "flip" the sign of the current 'roll' angle ('0' do not flip sign,...
Definition ambi_bin.c:799
int ambi_bin_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition ambi_bin.c:665
char * ambi_bin_getSofaFilePath(void *const hAmbi)
Returns the file path for a .sofa file.
Definition ambi_bin.c:712
float ambi_bin_getProgressBar0_1(void *const hAmbi)
(Optional) Returns current intialisation/processing progress, between 0..1
Definition ambi_bin.c:676
void ambi_bin_destroy(void **const phAmbi)
Destroys an instance of ambi_bin.
Definition ambi_bin.c:108
void ambi_bin_setUseDefaultHRIRsflag(void *const hAmbi, int newState)
Sets flag to dictate whether the default HRIRs in the Spatial_Audio_Framework should be used,...
Definition ambi_bin.c:509
void ambi_bin_setEnableTruncationEQ(void *const hAmbi, int newState)
Sets a flag to enable/disable (1 or 0) truncation EQ.
Definition ambi_bin.c:584
int ambi_bin_getRPYflag(void *const hAmbi)
Returns a flag as to whether to use "yaw-pitch-roll" (0) or "roll-pitch-yaw" (1) rotation order.
Definition ambi_bin.c:805
int ambi_bin_getFlipYaw(void *const hAmbi)
Returns a flag as to whether to "flip" the sign of the current 'yaw' angle ('0' do not flip sign,...
Definition ambi_bin.c:787
int ambi_bin_getInputOrderPreset(void *const hAmbi)
Returns the decoding order.
Definition ambi_bin.c:700
void ambi_bin_setDecodingMethod(void *const hAmbi, AMBI_BIN_DECODING_METHODS newMethod)
Sets the decoding method (see AMBI_BIN_DECODING_METHODS enum)
Definition ambi_bin.c:545
void ambi_bin_setEnableDiffuseMatching(void *const hAmbi, int newState)
Sets a flag to enable/disable (1 or 0) the diffuse-covariance constraint.
Definition ambi_bin.c:575
void ambi_bin_init(void *const hAmbi, int sampleRate)
Initialises ambi_bin with default settings, and samplerate.
Definition ambi_bin.c:146
CODEC_STATUS ambi_bin_getCodecStatus(void *const hAmbi)
Returns current codec status, see CODEC_STATUS enum.
Definition ambi_bin.c:670
int ambi_bin_getUseDefaultHRIRsflag(void *const hAmbi)
Returns the value of a flag used to dictate whether the default HRIRs in the Spatial_Audio_Framework ...
Definition ambi_bin.c:688
float ambi_bin_getYaw(void *const hAmbi)
Returns the 'yaw' rotation angle, in degree.
Definition ambi_bin.c:769
int ambi_bin_getNDirs(void *const hAmbi)
Returns the number of directions in the currently used HRIR set.
Definition ambi_bin.c:811
void ambi_bin_getProgressBarText(void *const hAmbi, char *text)
(Optional) Returns current intialisation/processing progress text
Definition ambi_bin.c:682
void ambi_bin_setRoll(void *const hAmbi, float newRoll)
Sets the 'roll' rotation angle, in degrees.
Definition ambi_bin.c:622
void ambi_bin_refreshParams(void *const hAmbi)
Sets intialisation flags to 1, so as to re-initialise all settings/variables (as ambi_bin is currentl...
Definition ambi_bin.c:502
AMBI_BIN_DECODING_METHODS
Available decoding methods for the ambi_bin example.
Definition ambi_bin.h:126
@ DECODING_METHOD_LSDIFFEQ
Least-squares (LS) decoder with diffuse-field spectral equalisation.
Definition ambi_bin.h:128
@ DECODING_METHOD_LS
Least-squares (LS) decoder.
Definition ambi_bin.h:127
@ DECODING_METHOD_SPR
Spatial resampling decoder (on the same lines as the virtual loudspeaker approach)
Definition ambi_bin.h:130
@ DECODING_METHOD_TA
Time-alignment (TA)
Definition ambi_bin.h:132
@ DECODING_METHOD_MAGLS
Magnitude least-squares decoder (MagLS)
Definition ambi_bin.h:133
AMBI_BIN_PREPROC
Available HRIR pre-preprocessing options.
Definition ambi_bin.h:141
@ HRIR_PREPROC_PHASE
Phase simplification based on ITD.
Definition ambi_bin.h:144
@ HRIR_PREPROC_EQ
Diffuse-field EQ (compensates CTF)
Definition ambi_bin.h:143
@ HRIR_PREPROC_ALL
Diffuse-field EQ AND phase-simplification.
Definition ambi_bin.h:145
void ambi_bin_setCodecStatus(void *const hAmbi, CODEC_STATUS newStatus)
Sets codec status.
A binaural Ambisonic decoder for reproducing Ambisonic sound scenes over headphones.
#define AMBI_BIN_FRAME_SIZE
Framesize, in time-domain samples.
#define TIME_SLOTS
Number of STFT timeslots.
#define HOP_SIZE
STFT hop size.
#define HYBRID_BANDS
Number of frequency bands.
void getBinauralAmbiDecoderMtx(float_complex *hrtfs, float *hrtf_dirs_deg, int N_dirs, int N_bands, BINAURAL_AMBI_DECODER_METHODS method, int order, float *freqVector, float *itd_s, float *weights, int enableDiffCovMatching, int enableMaxReWeighting, float_complex *decMtx)
Computes binaural ambisonic decoding matrices (one per frequency) at a specific order,...
Definition saf_hoa.c:395
void convertHOAChannelConvention(float *insig, int order, int signalLength, HOA_CH_ORDER inConvention, HOA_CH_ORDER outConvention)
Converts an Ambisonic signal from one channel ordering convention to another.
Definition saf_hoa.c:41
void convertHOANormConvention(float *insig, int order, int signalLength, HOA_NORM inConvention, HOA_NORM outConvention)
Converts an Ambisonic signal from one normalisation convention to another.
Definition saf_hoa.c:73
void truncationEQ(float *w_n, int order_truncated, int order_target, double *kr, int nBands, float softThreshold, float *gain)
Filter that equalises the high frequency roll-off due to SH truncation and tapering; as described in ...
Definition saf_hoa.c:270
@ HOA_CH_ORDER_FUMA
Furse-Malham (FuMa) convention, often used by older recordings.
Definition saf_hoa.h:187
@ HOA_CH_ORDER_ACN
Ambisonic Channel numbering (ACN) convention, which is employed by all spherical harmonic related fun...
Definition saf_hoa.h:184
@ HOA_NORM_FUMA
Furse-Malham (FuMa) convention.
Definition saf_hoa.h:208
@ HOA_NORM_SN3D
Schmidt semi-normalisation (SN3D) convention, as used by the AmbiX standard.
Definition saf_hoa.h:206
@ HOA_NORM_N3D
Orthonormalised (N3D) convention, which is the default convention used by SAF.
Definition saf_hoa.h:204
@ BINAURAL_DECODER_MAGLS
Magnitude least-squares decoder [3].
Definition saf_hoa.h:170
@ BINAURAL_DECODER_LS
Least-squares (LS) decoder.
Definition saf_hoa.h:144
@ BINAURAL_DECODER_SPR
Spatial resampling decoder (on the same lines as the virtual loudspeaker approach) [4].
Definition saf_hoa.h:157
@ BINAURAL_DECODER_TA
Time-alignment decoder [2].
Definition saf_hoa.h:165
@ BINAURAL_DECODER_LSDIFFEQ
Least-squares (LS) decoder with diffuse-field spectral equalisation [1].
Definition saf_hoa.h:152
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 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 beamWeightsMaxEV(int N, float *b_n)
Generates beamweights in the SHD for maximum energy-vector beampatterns.
Definition saf_sh.c:858
void getSHrotMtxReal(float Rxyz[3][3], float *RotMtx, int L)
Generates a real-valued spherical harmonic rotation matrix [1] based on a 3x3 rotation matrix (see qu...
Definition saf_sh.c:586
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.
#define SAF_PI
pi constant (single precision)
#define DEG2RAD(x)
Converts degrees to radians.
#define NUM_EARS
2 (true for most humans)
#define SAF_PId
pi constant (double precision)
void utility_svvcopy(const float *a, const int len, float *c)
Single-precision, vector-vector copy, i.e.
#define SAF_MIN(a, b)
Returns the minimum of the two values.
void sphElev2incl(float *dirsElev, int nDirs, int degreesFlag, float *dirsIncl)
Converts spherical coordinates of unit length from elevation to inclination.
#define saf_print_warning(message)
Macro to print a warning message along with the filename and line number.
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.
#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 * calloc1d(size_t dim1, size_t data_size)
1-D calloc (same as calloc, but with error checking)
Definition md_malloc.c:69
void * realloc1d(void *ptr, size_t dim1_data_size)
1-D realloc (same as realloc, but with error checking)
Definition md_malloc.c:79
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 FLATTEN2D(A)
Use this macro when passing a 2-D dynamic multi-dimensional array to memset, memcpy or any other func...
Definition md_malloc.h:65
Contains variables for sofa file loading, HRIRs, and the binaural decoder.
float * hrir_dirs_deg
directions of the HRIRs in degrees [azi elev]; FLAT: N_hrir_dirs x 2
float * weights
grid integration weights of hrirs; N_hrirs x 1
_Atomic_INT32 N_hrir_dirs
number of HRIR directions in the current sofa file
float_complex * hrtf_fb
HRTF filterbank coeffs; FLAT: nBands x nCH x N_hrirs.
char * sofa_filepath
absolute/relevative file path for a sofa file
_Atomic_INT32 hrir_len
length of the HRIRs, this can be truncated, see "saf_sofa_reader.h"
float_complex M_dec_rot[HYBRID_BANDS][NUM_EARS][MAX_NUM_SH_SIGNALS]
Decording matrix per band, with sound-field rotation baked-in.
float * hrirs
time domain HRIRs; FLAT: N_hrir_dirs x 2 x hrir_len
float_complex M_dec[HYBRID_BANDS][NUM_EARS][MAX_NUM_SH_SIGNALS]
Decoding matrix per band.
float * itds_s
interaural-time differences for each HRIR (in seconds); N_hrirs x 1
_Atomic_INT32 hrir_fs
sampling rate of the HRIRs, should ideally match the host sampling rate, although not required
Main structure for ambi_bin.
_Atomic_INT32 fs
host sampling rate
float_complex *** binframeTF
Output binaural signals in the time-frequency domain; HYBRID_BANDS x NUM_EARS x TIME_SLOTS.
_Atomic_INT32 enableRotation
Whether rotation should be enabled (1) or disabled (0)
_Atomic_CODEC_STATUS codecStatus
see CODEC_STATUS
_Atomic_AMBI_BIN_PREPROC preProc
HRIR pre-processing strategy.
_Atomic_INT32 enableTruncationEQ
0: disabled, 1: enabled
_Atomic_INT32 reinit_hrtfsFLAG
0: no init required, 1: init required
float_complex M_rot[MAX_NUM_SH_SIGNALS][MAX_NUM_SH_SIGNALS]
Current SH rotation matrix.
_Atomic_FLOAT32 pitch
pitch (Euler) rotation angle, in degrees
_Atomic_NORM_TYPES norm
Ambisonic normalisation convention (see NORM_TYPES)
char * progressBarText
Current (re)initialisation step, string.
_Atomic_INT32 useDefaultHRIRsFLAG
1: use default HRIRs in database, 0: use those from SOFA file
_Atomic_FLOAT32 yaw
yaw (Euler) rotation angle, in degrees
_Atomic_INT32 enableDiffuseMatching
0: disabled, 1: enabled
_Atomic_FLOAT32 roll
roll (Euler) rotation angle, in degrees
_Atomic_INT32 new_order
new decoding order (current value will be replaced by this after next re-init)
_Atomic_INT32 enableMaxRE
0: disabled, 1: enabled
void * hSTFT
afSTFT handle
_Atomic_INT32 nSH
number of spherical harmonic signals
_Atomic_AMBI_BIN_DECODING_METHODS method
current decoding method (see AMBI_BIN_DECODING_METHODS)
_Atomic_INT32 useRollPitchYawFlag
rotation order flag, 1: r-p-y, 0: y-p-r
float_complex *** SHframeTF
Input spherical harmonic (SH) signals in the time-frequency domain; HYBRID_BANDS x MAX_NUM_SH_SIGNALS...
float freqVector[HYBRID_BANDS]
frequency vector for time-frequency transform, in Hz
_Atomic_PROC_STATUS procStatus
see PROC_STATUS
_Atomic_INT32 bFlipYaw
flag to flip the sign of the yaw rotation angle
_Atomic_FLOAT32 progressBar0_1
Current (re)initialisation progress, between [0..1].
_Atomic_INT32 recalc_M_rotFLAG
0: no init required, 1: init required
_Atomic_INT32 bFlipRoll
flag to flip the sign of the roll rotation angle
ambi_bin_codecPars * pars
Decoding specific data.
_Atomic_CH_ORDER chOrdering
Ambisonic channel order convention (see CH_ORDER)
_Atomic_INT32 order
current decoding order
float ** SHFrameTD
Input spherical harmonic (SH) signals in the time-domain; MAX_NUM_SH_SIGNALS x AMBI_BIN_FRAME_SIZE.
_Atomic_INT32 bFlipPitch
flag to flip the sign of the pitch rotation angle
float ** binFrameTD
Output binaural signals in the time-domain; NUM_EARS x AMBI_BIN_FRAME_SIZE.
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.