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
48#include "ambi_bin_internal.h"
49
51(
52 void ** const phAmbi
53)
54{
56 *phAmbi = (void*)pData;
57 int band;
58
59 /* default user parameters */
60 for (band = 0; band<HYBRID_BANDS; band++)
61 pData->EQ[band] = 1.0f;
62 pData->useDefaultHRIRsFLAG = 1; /* pars->sofa_filepath must be valid to set this to 0 */
63 pData->preProc = HRIR_PREPROC_EQ;
64 pData->chOrdering = CH_ACN;
65 pData->norm = NORM_SN3D;
66 pData->enableMaxRE = 1;
67 pData->enableDiffuseMatching = 0;
68 pData->enableTruncationEQ = 1;
69 pData->enableRotation = 0;
70 pData->yaw = 0.0f;
71 pData->pitch = 0.0f;
72 pData->roll = 0.0f;
73 pData->bFlipYaw = 0;
74 pData->bFlipPitch = 0;
75 pData->bFlipRoll = 0;
76 pData->useRollPitchYawFlag = 0;
78 pData->order = pData->new_order = 1;
79 pData->nSH = (pData->order+1)*(pData->order+1);
80
81 /* afSTFT and audio buffers */
82 pData->fs = 48000;
83 pData->hSTFT = NULL;
84 pData->SHFrameTD = (float**)malloc2d(MAX_NUM_SH_SIGNALS, AMBI_BIN_FRAME_SIZE, sizeof(float));
85 pData->binFrameTD = (float**)malloc2d(NUM_EARS, AMBI_BIN_FRAME_SIZE, sizeof(float));
86 pData->SHframeTF = (float_complex***)malloc3d(HYBRID_BANDS, MAX_NUM_SH_SIGNALS, TIME_SLOTS, sizeof(float_complex));
87 pData->binframeTF = (float_complex***)malloc3d(HYBRID_BANDS, NUM_EARS, TIME_SLOTS, sizeof(float_complex));
88 afSTFT_getCentreFreqs(pData->hSTFT, (float)pData->fs, HYBRID_BANDS, (float*)pData->freqVector);
89
90 /* codec data */
91 pData->progressBar0_1 = 0.0f;
93 strcpy(pData->progressBarText,"");
95 ambi_bin_codecPars* pars = pData->pars;
96 pars->sofa_filepath = NULL;
97 pars->hrirs = NULL;
98 pars->hrir_dirs_deg = NULL;
99 pars->itds_s = NULL;
100 pars->hrtf_fb = NULL;
101 pars->weights = NULL;
102
103 /* flags */
106 pData->recalc_M_rotFLAG = 1;
107 pData->reinit_hrtfsFLAG = 1;
108}
109
111(
112 void ** const phAmbi
113)
114{
115 ambi_bin_data *pData = (ambi_bin_data*)(*phAmbi);
116 ambi_bin_codecPars *pars;
117
118 if (pData != NULL) {
119 /* not safe to free memory during intialisation/processing loop */
120 while (pData->codecStatus == CODEC_STATUS_INITIALISING ||
122 SAF_SLEEP(10);
123 }
124
125 /* free afSTFT and buffers */
126 afSTFT_destroy(&(pData->hSTFT));
127 free(pData->SHFrameTD);
128 free(pData->binFrameTD);
129 free(pData->SHframeTF);
130 free(pData->binframeTF);
131
132 pars = pData->pars;
133 free(pars->sofa_filepath);
134 free(pars->weights);
135 free(pars->hrtf_fb);
136 free(pars->itds_s);
137 free(pars->hrirs);
138 free(pars->hrir_dirs_deg);
139 free(pars);
140 free(pData->progressBarText);
141
142 free(pData);
143 pData = NULL;
144 *phAmbi = NULL;
145 }
146}
147
149(
150 void * const hAmbi,
151 int sampleRate
152)
153{
154 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
155
156 /* define frequency vector */
157 if(pData->fs != sampleRate){
158 pData->fs = sampleRate;
159 pData->reinit_hrtfsFLAG = 1;
161 }
162 afSTFT_getCentreFreqs(pData->hSTFT, (float)pData->fs, HYBRID_BANDS, (float*)pData->freqVector);
163
164 /* default starting values */
165 pData->recalc_M_rotFLAG = 1;
166}
167
169(
170 void* const hAmbi
171)
172{
173 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
174 ambi_bin_codecPars* pars = pData->pars;
175 int i, j, nSH, order, band;
176#ifdef SAF_ENABLE_SOFA_READER_MODULE
179#endif
180
182 return; /* re-init not required, or already happening */
183 while (pData->procStatus == PROC_STATUS_ONGOING){
184 /* re-init required, but we need to wait for the current processing loop to end */
185 pData->codecStatus = CODEC_STATUS_INITIALISING; /* indicate that we want to init */
186 SAF_SLEEP(10);
187 }
188
189 /* for progress bar */
191 strcpy(pData->progressBarText,"Preparing HRIRs");
192 pData->progressBar0_1 = 0.0f;
193
194 /* (Re)Initialise afSTFT */
195 order = pData->new_order;
196 nSH = (order+1)*(order+1);
197 if(pData->hSTFT==NULL)
199 else if(pData->nSH != nSH) {/* Or change the number of channels */
200 afSTFT_channelChange(pData->hSTFT, nSH, NUM_EARS);
202 }
203 pData->nSH = nSH;
204
205 if(pData->reinit_hrtfsFLAG){
206 /* load sofa file or default hrir data */
207 strcpy(pData->progressBarText,"Preparing HRIRs");
208 pData->progressBar0_1 = 0.15f;
209 /* load sofa file or load default hrir data */
210#ifdef SAF_ENABLE_SOFA_READER_MODULE
211 if(!pData->useDefaultHRIRsFLAG && pars->sofa_filepath!=NULL){
212 /* Load SOFA file */
214
215 /* Load defaults instead */
216 if(error!=SAF_SOFA_OK || sofa.nReceivers!=NUM_EARS){
217 pData->useDefaultHRIRsFLAG = 1;
218 saf_print_warning("Unable to load the specified SOFA file, or it contained something other than 2 channels. Using default HRIR data instead.");
219 }
220 else{
221 /* Copy SOFA data */
222 pars->hrir_fs = (int)sofa.DataSamplingRate;
223 pars->hrir_len = sofa.DataLengthIR;
224 pars->N_hrir_dirs = sofa.nSources;
225 pars->hrirs = realloc1d(pars->hrirs, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
226 memcpy(pars->hrirs, sofa.DataIR, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
227 pars->hrir_dirs_deg = realloc1d(pars->hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
228 cblas_scopy(pars->N_hrir_dirs, sofa.SourcePosition, 3, pars->hrir_dirs_deg, 2); /* azi */
229 cblas_scopy(pars->N_hrir_dirs, &sofa.SourcePosition[1], 3, &pars->hrir_dirs_deg[1], 2); /* elev */
230 }
231
232 /* Clean-up */
233 saf_sofa_close(&sofa);
234 }
235#else
236 pData->useDefaultHRIRsFLAG = 1; /* Can only load the default HRIR data */
237#endif
238 if(pData->useDefaultHRIRsFLAG){
239 /* Copy default HRIR data */
243 pars->hrirs = realloc1d(pars->hrirs, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
244 memcpy(pars->hrirs, (float*)__default_hrirs, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
245 pars->hrir_dirs_deg = realloc1d(pars->hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
246 memcpy(pars->hrir_dirs_deg, (float*)__default_hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
247 }
248
249 /* convert hrirs to filterbank coefficients */
250 pData->progressBar0_1 = 0.4f;
251 pars->hrtf_fb = realloc1d(pars->hrtf_fb, HYBRID_BANDS * NUM_EARS * (pars->N_hrir_dirs)*sizeof(float_complex));
252 HRIRs2HRTFs_afSTFT(pars->hrirs, pars->N_hrir_dirs, pars->hrir_len, HOP_SIZE, 0, 1, pars->hrtf_fb);
253 /* HRIR pre-processing */
254 if(pData->preProc == HRIR_PREPROC_EQ || pData->preProc == HRIR_PREPROC_ALL){
255 /* get integration weights */
256 strcpy(pData->progressBarText,"Applying HRIR diffuse-field EQ");
257 pData->progressBar0_1 = 0.5f;
258 if(pars->N_hrir_dirs<=3600){
259 pars->weights = realloc1d(pars->weights, pars->N_hrir_dirs*sizeof(float));
260 //getVoronoiWeights(pars->hrir_dirs_deg, pars->N_hrir_dirs, 0, pars->weights);
261 float * hrir_dirs_rad = (float*) malloc1d(pars->N_hrir_dirs*2*sizeof(float));
262 memcpy(hrir_dirs_rad, pars->hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
263 cblas_sscal(pars->N_hrir_dirs*2, SAF_PI/180.f, hrir_dirs_rad, 1);
264 sphElev2incl(hrir_dirs_rad, pars->N_hrir_dirs, 0, hrir_dirs_rad);
265 int supOrder = calculateGridWeights(hrir_dirs_rad, pars->N_hrir_dirs, -1, pars->weights);
266 if(supOrder < 1){
267 saf_print_warning("Could not calculate grid weights");
268 free(pars->weights);
269 pars->weights = NULL;
270 }
271 }
272 else{
273 saf_print_warning("Too many grid points");
274 free(pars->weights);
275 pars->weights = NULL;
276 }
277 }
278
279 /* estimate the ITDs for each HRIR */
280 pData->progressBar0_1 = 0.6f;
281 pars->itds_s = realloc1d(pars->itds_s, pars->N_hrir_dirs*sizeof(float));
282 estimateITDs(pars->hrirs, pars->N_hrir_dirs, pars->hrir_len, pars->hrir_fs, pars->itds_s);
283
284 /* apply HRIR pre-processing */
285 pData->progressBar0_1 = 0.75f;
287 pData->preProc == HRIR_PREPROC_EQ || pData->preProc == HRIR_PREPROC_ALL ? 1 : 0, /* Apply Diffuse-field EQ? */
288 pData->preProc == HRIR_PREPROC_PHASE || pData->preProc == HRIR_PREPROC_ALL ? 1 : 0, /* Apply phase simplification EQ? */
289 pars->hrtf_fb);
290 pData->reinit_hrtfsFLAG = 0;
291 }
292
293 /* get new decoder */
294 strcpy(pData->progressBarText,"Computing Decoder");
295 pData->progressBar0_1 = 0.95f;
296 float_complex* decMtx;
297 decMtx = calloc1d(HYBRID_BANDS*NUM_EARS*nSH, sizeof(float_complex));
298 switch(pData->method){
299 default:
302 BINAURAL_DECODER_LS, order, pData->freqVector, pars->itds_s, pars->weights,
303 pData->enableDiffuseMatching, pData->enableMaxRE, decMtx);
304 break;
307 BINAURAL_DECODER_LSDIFFEQ, order, pData->freqVector, pars->itds_s, pars->weights,
308 pData->enableDiffuseMatching, pData->enableMaxRE, decMtx);
309 break;
312 BINAURAL_DECODER_SPR, order, pData->freqVector, pars->itds_s, pars->weights,
313 pData->enableDiffuseMatching, pData->enableMaxRE, decMtx);
314 break;
317 BINAURAL_DECODER_TA, order, pData->freqVector, pars->itds_s, pars->weights,
318 pData->enableDiffuseMatching, pData->enableMaxRE, decMtx);
319 break;
322 BINAURAL_DECODER_MAGLS, order, pData->freqVector, pars->itds_s, pars->weights,
323 pData->enableDiffuseMatching, pData->enableMaxRE, decMtx);
324 break;
325 }
326
327 /* Apply Truncation EQ */
328 if(pData->enableTruncationEQ &&
329 pData->method==DECODING_METHOD_LS &&
330 pData->preProc!=HRIR_PREPROC_PHASE &&
332 {
333 double *kr;
334 float *w_n, *eqGain;
335 const int order_truncated = order;
336 const int order_target = 42; /* Equalizing diffuse field to 42nd order equivalent. */
337 const float softThreshold = 9.0; /* results in +9 dB max */
338 const double r = 0.085; /* spherical scatterer radius (approx. size of human head) */
339 const int numBands = HYBRID_BANDS;
340 const double c = 343.;
341
342 /* Prep */
343 kr = malloc1d(numBands * sizeof(double));
344 w_n = calloc1d((order_truncated+1), sizeof(float));
345 eqGain = calloc1d(numBands, sizeof(float));
346 for (int k=0; k<numBands; k++)
347 kr[k] = 2.0*SAF_PId / c * (double)pData->freqVector[k] * r;
348
349 if (pData->enableMaxRE) {
350 /* maxRE as order weighting */
351 float *maxRECoeffs = malloc1d((order_truncated+1) * sizeof(float));
352 beamWeightsMaxEV(order_truncated, maxRECoeffs);
353 for (int idx_n=0; idx_n<order_truncated+1; idx_n++) {
354 w_n[idx_n] = maxRECoeffs[idx_n];
355 w_n[idx_n] /= sqrtf((float)(2*idx_n+1) / (4.0f*SAF_PI));
356 }
357 float w_0 = w_n[0];
358 for (int idx_n=0; idx_n<order_truncated+1; idx_n++)
359 w_n[idx_n] /= w_0;
360 free(maxRECoeffs);
361 }
362 else {
363 /* just truncation, no tapering */
364 for (int idx_n=0; idx_n<order_truncated+1; idx_n++)
365 w_n[idx_n] = 1.0f;
366 }
367 truncationEQ(w_n, order_truncated, order_target, kr, numBands, softThreshold, eqGain);
368
369 /* apply to decoding matrix */
370 for (int idxBand=0; idxBand<numBands; idxBand++){
371 for (int idxSH=0; idxSH<pData->nSH; idxSH++){
372 decMtx[idxBand*NUM_EARS*nSH+0*nSH+idxSH] = crmulf(decMtx[idxBand*NUM_EARS*nSH+0*nSH+idxSH], eqGain[idxBand]); /* left ear */
373 decMtx[idxBand*NUM_EARS*nSH+1*nSH+idxSH] = crmulf(decMtx[idxBand*NUM_EARS*nSH+1*nSH+idxSH], eqGain[idxBand]); /* right ear */
374 }
375 }
376
377 /* clean-up */
378 free(kr);
379 free(w_n);
380 free(eqGain);
381 }
382
383 /* replace current decoder */
384 memset(pars->M_dec, 0, HYBRID_BANDS*NUM_EARS*MAX_NUM_SH_SIGNALS*sizeof(float_complex));
385 for(band=0; band<HYBRID_BANDS; band++)
386 for(i=0; i<NUM_EARS; i++)
387 for(j=0; j<nSH; j++)
388 pars->M_dec[band][i][j] = decMtx[band*NUM_EARS*nSH + i*nSH + j];
389 free(decMtx);
390
391 /* rotation matrix will need to be updated too */
392 pData->recalc_M_rotFLAG = 1;
393
394 pData->order = order;
395
396 /* done! */
397 strcpy(pData->progressBarText,"Done!");
398 pData->progressBar0_1 = 1.0f;
400}
401
403(
404 void * const hAmbi,
405 const float *const * inputs,
406 float* const* const outputs,
407 int nInputs,
408 int nOutputs,
409 int nSamples
410)
411{
412 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
413 ambi_bin_codecPars* pars = pData->pars;
414 int ch, i, j, band;
415 const float_complex calpha = cmplxf(1.0f,0.0f), cbeta = cmplxf(0.0f, 0.0f);
416 float Rxyz[3][3];
417 float M_rot_tmp[MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS];
418
419 /* local copies of user parameters */
420 int order, nSH, enableRot;
421 NORM_TYPES norm;
422 CH_ORDER chOrdering;
423 norm = pData->norm;
424 chOrdering = pData->chOrdering;
425 order = pData->order;
426 nSH = (order+1)*(order+1);
427 enableRot = pData->enableRotation;
428
429 /* Process frame */
430 if (nSamples == AMBI_BIN_FRAME_SIZE && (pData->codecStatus == CODEC_STATUS_INITIALISED) ) {
432
433 /* Load time-domain data */
434 for(i=0; i < SAF_MIN(nSH, nInputs); i++)
435 utility_svvcopy(inputs[i], AMBI_BIN_FRAME_SIZE, pData->SHFrameTD[i]);
436 for(; i<nSH; i++)
437 memset(pData->SHFrameTD[i], 0, AMBI_BIN_FRAME_SIZE * sizeof(float)); /* fill remaining channels with zeros */
438
439 /* account for channel order convention */
440 switch(chOrdering){
441 case CH_ACN: /* already in ACN, do nothing */ break; /* Otherwise, convert to ACN... */
443 }
444
445 /* account for input normalisation scheme */
446 switch(norm){
447 case NORM_N3D: /* already in N3D, do nothing */ break; /* Otherwise, convert to N3D... */
450 }
451
452 /* Apply time-frequency transform (TFT) */
454
455 /* Main processing: */
456 if(order > 0 && enableRot) {
457 /* Apply rotation */
458 if(pData->recalc_M_rotFLAG){
459 /* Compute the new SH rotation matrix */
460 memset(pData->M_rot, 0, MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS*sizeof(float_complex));
461 yawPitchRoll2Rzyx(pData->yaw, pData->pitch, pData->roll, pData->useRollPitchYawFlag, Rxyz);
462 getSHrotMtxReal(Rxyz, (float*)M_rot_tmp, order);
463 for (i = 0; i < nSH; i++)
464 for (j = 0; j < nSH; j++)
465 pData->M_rot[i][j] = cmplxf(M_rot_tmp[i*nSH + j], 0.0f);
466
467 /* Bake the rotation into the decoding matrix */
468 for(band = 0; band < HYBRID_BANDS; band++) {
469 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, NUM_EARS, nSH, nSH, &calpha,
470 pars->M_dec[band], MAX_NUM_SH_SIGNALS,
471 pData->M_rot, MAX_NUM_SH_SIGNALS, &cbeta,
472 pars->M_dec_rot[band], MAX_NUM_SH_SIGNALS);
473 }
474 pData->recalc_M_rotFLAG = 0;
475 }
476 }
477
478 /* Apply the decoder to go from SH input to binaural output */
479 for(band = 0; band < HYBRID_BANDS; band++) {
480 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, NUM_EARS, TIME_SLOTS, nSH, &calpha,
481 enableRot ? pars->M_dec_rot[band] : pars->M_dec[band], MAX_NUM_SH_SIGNALS,
482 FLATTEN2D(pData->SHframeTF[band]), TIME_SLOTS, &cbeta,
483 FLATTEN2D(pData->binframeTF[band]), TIME_SLOTS);
484 }
485
486 /* inverse-TFT */
488
489 /* Copy to output */
490 for (ch = 0; ch < SAF_MIN(NUM_EARS, nOutputs); ch++)
491 utility_svvcopy(pData->binFrameTD[ch], AMBI_BIN_FRAME_SIZE, outputs[ch]);
492 for (; ch < nOutputs; ch++)
493 memset(outputs[ch], 0, AMBI_BIN_FRAME_SIZE*sizeof(float));
494 }
495 else
496 for (ch=0; ch < nOutputs; ch++)
497 memset(outputs[ch],0, AMBI_BIN_FRAME_SIZE*sizeof(float));
498
500}
501
502
503/* Set Functions */
504
505void ambi_bin_refreshParams(void* const hAmbi)
506{
507 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
508 pData->reinit_hrtfsFLAG = 1;
510}
511
512void ambi_bin_setUseDefaultHRIRsflag(void* const hAmbi, int newState)
513{
514 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
515
516 if((!pData->useDefaultHRIRsFLAG) && (newState)){
517 pData->useDefaultHRIRsFLAG = newState;
518 ambi_bin_refreshParams(hAmbi); // re-init and re-calc
519 }
520}
521
522void ambi_bin_setSofaFilePath(void* const hAmbi, const char* path)
523{
524 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
525 ambi_bin_codecPars* pars = pData->pars;
526
527 pars->sofa_filepath = realloc1d(pars->sofa_filepath, strlen(path) + 1);
528 strcpy(pars->sofa_filepath, path);
529 pData->useDefaultHRIRsFLAG = 0;
530 ambi_bin_refreshParams(hAmbi); // re-init and re-calc
531
532}
533
534void ambi_bin_setInputOrderPreset(void* const hAmbi, SH_ORDERS newOrder)
535{
536 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
537 if(pData->order != (int)newOrder){
538 pData->new_order = (int)newOrder;
540 }
541 /* FUMA only supports 1st order */
542 if(pData->new_order!=SH_ORDER_FIRST && pData->chOrdering == CH_FUMA)
543 pData->chOrdering = CH_ACN;
544 if(pData->new_order!=SH_ORDER_FIRST && pData->norm == NORM_FUMA)
545 pData->norm = NORM_SN3D;
546}
547
549{
550 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
551 pData->method = newMethod;
553}
554
555void ambi_bin_setChOrder(void* const hAmbi, int newOrder)
556{
557 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
558 if((CH_ORDER)newOrder != CH_FUMA || pData->new_order==SH_ORDER_FIRST)/* FUMA only supports 1st order */
559 pData->chOrdering = (CH_ORDER)newOrder;
560}
561
562void ambi_bin_setNormType(void* const hAmbi, int newType)
563{
564 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
565 if((NORM_TYPES)newType != NORM_FUMA || pData->new_order==SH_ORDER_FIRST)/* FUMA only supports 1st order */
566 pData->norm = (NORM_TYPES)newType;
567}
568
569void ambi_bin_setEnableMaxRE(void* const hAmbi, int newState)
570{
571 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
572 if(pData->enableMaxRE != newState){
573 pData->enableMaxRE = newState;
575 }
576}
577
578void ambi_bin_setEnableDiffuseMatching(void* const hAmbi, int newState)
579{
580 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
581 if(pData->enableDiffuseMatching != newState){
582 pData->enableDiffuseMatching = newState;
584 }
585}
586
587void ambi_bin_setEnableTruncationEQ(void* const hAmbi, int newState)
588{
589 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
590 if(pData->enableTruncationEQ != newState){
591 pData->enableTruncationEQ = newState;
593 }
594}
595
596void ambi_bin_setHRIRsPreProc(void* const hAmbi, AMBI_BIN_PREPROC newType)
597{
598 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
599 if(pData->preProc != newType){
600 pData->preProc = newType;
602 }
603}
604
605void ambi_bin_setEnableRotation(void* const hAmbi, int newState)
606{
607 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
608 pData->enableRotation = newState;
609}
610
611void ambi_bin_setYaw(void * const hAmbi, float newYaw)
612{
613 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
614 pData->yaw = pData->bFlipYaw == 1 ? -DEG2RAD(newYaw) : DEG2RAD(newYaw);
615 pData->recalc_M_rotFLAG = 1;
616}
617
618void ambi_bin_setPitch(void* const hAmbi, float newPitch)
619{
620 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
621 pData->pitch = pData->bFlipPitch == 1 ? -DEG2RAD(newPitch) : DEG2RAD(newPitch);
622 pData->recalc_M_rotFLAG = 1;
623}
624
625void ambi_bin_setRoll(void* const hAmbi, float newRoll)
626{
627 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
628 pData->roll = pData->bFlipRoll == 1 ? -DEG2RAD(newRoll) : DEG2RAD(newRoll);
629 pData->recalc_M_rotFLAG = 1;
630}
631
632void ambi_bin_setFlipYaw(void* const hAmbi, int newState)
633{
634 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
635 if(newState !=pData->bFlipYaw ){
636 pData->bFlipYaw = newState;
637 ambi_bin_setYaw(hAmbi, -ambi_bin_getYaw(hAmbi));
638 }
639}
640
641void ambi_bin_setFlipPitch(void* const hAmbi, int newState)
642{
643 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
644 if(newState !=pData->bFlipPitch ){
645 pData->bFlipPitch = newState;
646 ambi_bin_setPitch(hAmbi, -ambi_bin_getPitch(hAmbi));
647 }
648}
649
650void ambi_bin_setFlipRoll(void* const hAmbi, int newState)
651{
652 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
653 if(newState !=pData->bFlipRoll ){
654 pData->bFlipRoll = newState;
655 ambi_bin_setRoll(hAmbi, -ambi_bin_getRoll(hAmbi));
656 }
657}
658
659void ambi_bin_setRPYflag(void* const hAmbi, int newState)
660{
661 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
662 pData->useRollPitchYawFlag = newState;
663}
664
665
666/* Get Functions */
667
669{
670 return AMBI_BIN_FRAME_SIZE;
671}
672
674{
675 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
676 return pData->codecStatus;
677}
678
679float ambi_bin_getProgressBar0_1(void* const hAmbi)
680{
681 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
682 return pData->progressBar0_1;
683}
684
685void ambi_bin_getProgressBarText(void* const hAmbi, char* text)
686{
687 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
688 memcpy(text, pData->progressBarText, PROGRESSBARTEXT_CHAR_LENGTH*sizeof(char));
689}
690
692{
693 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
694 return pData->useDefaultHRIRsFLAG;
695}
696
698{
699 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
700 return pData->preProc;
701}
702
703int ambi_bin_getInputOrderPreset(void* const hAmbi)
704{
705 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
706 return pData->new_order;
707}
708
710{
711 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
712 return pData->method;
713}
714
715char* ambi_bin_getSofaFilePath(void* const hAmbi)
716{
717 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
718 ambi_bin_codecPars* pars = pData->pars;
719 if(pars->sofa_filepath!=NULL)
720 return pars->sofa_filepath;
721 else
722 return "no_file";
723}
724
725int ambi_bin_getChOrder(void* const hAmbi)
726{
727 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
728 return (int)pData->chOrdering;
729}
730
731int ambi_bin_getNormType(void* const hAmbi)
732{
733 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
734 return (int)pData->norm;
735}
736
737int ambi_bin_getEnableMaxRE(void* const hAmbi)
738{
739 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
740 return pData->enableMaxRE;
741}
742
744{
745 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
746 return pData->enableDiffuseMatching;
747}
748
749int ambi_bin_getEnableTruncationEQ(void* const hAmbi)
750{
751 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
752 return pData->enableTruncationEQ;
753}
754
756{
757 return NUM_EARS;
758}
759
760int ambi_bin_getNSHrequired(void* const hAmbi)
761{
762 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
763 return pData->nSH;
764}
765
766int ambi_bin_getEnableRotation(void* const hAmbi)
767{
768 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
769 return pData->enableRotation;
770}
771
772float ambi_bin_getYaw(void* const hAmbi)
773{
774 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
775 return pData->bFlipYaw == 1 ? -RAD2DEG(pData->yaw) : RAD2DEG(pData->yaw);
776}
777
778float ambi_bin_getPitch(void* const hAmbi)
779{
780 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
781 return pData->bFlipPitch == 1 ? -RAD2DEG(pData->pitch) : RAD2DEG(pData->pitch);
782}
783
784float ambi_bin_getRoll(void* const hAmbi)
785{
786 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
787 return pData->bFlipRoll == 1 ? -RAD2DEG(pData->roll) : RAD2DEG(pData->roll);
788}
789
790int ambi_bin_getFlipYaw(void* const hAmbi)
791{
792 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
793 return pData->bFlipYaw;
794}
795
796int ambi_bin_getFlipPitch(void* const hAmbi)
797{
798 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
799 return pData->bFlipPitch;
800}
801
802int ambi_bin_getFlipRoll(void* const hAmbi)
803{
804 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
805 return pData->bFlipRoll;
806}
807
808int ambi_bin_getRPYflag(void* const hAmbi)
809{
810 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
811 return pData->useRollPitchYawFlag;
812}
813
814int ambi_bin_getNDirs(void* const hAmbi)
815{
816 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
817 ambi_bin_codecPars* pars = pData->pars;
818 return pars->N_hrir_dirs;
819}
820
821int ambi_bin_getHRIRlength(void* const hAmbi)
822{
823 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
824 ambi_bin_codecPars* pars = pData->pars;
825 return pars->hrir_len;
826}
827
828int ambi_bin_getHRIRsamplerate(void* const hAmbi)
829{
830 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
831 ambi_bin_codecPars* pars = pData->pars;
832 return pars->hrir_fs;
833}
834
835int ambi_bin_getDAWsamplerate(void* const hAmbi)
836{
837 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
838 return pData->fs;
839}
840
842{
843 return 12*HOP_SIZE;
844}
#define PROGRESSBARTEXT_CHAR_LENGTH
Length of progress bar string.
Definition _common.h:227
@ PROC_STATUS_ONGOING
Codec is processing input audio, and should not be reinitialised at this time.
Definition _common.h:220
@ PROC_STATUS_NOT_ONGOING
Codec is not processing input audio, and may be reinitialised if needed.
Definition _common.h:222
NORM_TYPES
Available Ambisonic normalisation conventions.
Definition _common.h:74
@ NORM_SN3D
Schmidt semi-normalisation (SN3D)
Definition _common.h:76
@ NORM_FUMA
(Legacy) Furse-Malham scaling
Definition _common.h:77
@ NORM_N3D
orthonormalised (N3D)
Definition _common.h:75
CH_ORDER
Available Ambisonic channel ordering conventions.
Definition _common.h:59
@ CH_ACN
Ambisonic Channel Numbering (ACN)
Definition _common.h:60
@ CH_FUMA
(Legacy) Furse-Malham/B-format (WXYZ)
Definition _common.h:61
#define MAX_NUM_SH_SIGNALS
Maximum number of spherical harmonic components/signals supported.
Definition _common.h:239
SH_ORDERS
Available spherical harmonic (SH) input/output order options.
Definition _common.h:38
@ SH_ORDER_FIRST
First-order (4 channels)
Definition _common.h:39
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_INITIALISED
Codec is initialised and ready to process input audio.
Definition _common.h:202
@ 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_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:555
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:760
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:737
int ambi_bin_getHRIRsamplerate(void *const hAmbi)
Returns the HRIR sample rate.
Definition ambi_bin.c:828
int ambi_bin_getNormType(void *const hAmbi)
Returns the Ambisonic normalisation convention currently being usedto decode with,...
Definition ambi_bin.c:731
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:650
void ambi_bin_setPitch(void *const hAmbi, float newPitch)
Sets the 'pitch' rotation angle, in degrees.
Definition ambi_bin.c:618
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:749
void ambi_bin_setYaw(void *const hAmbi, float newYaw)
Sets the 'yaw' rotation angle, in degrees.
Definition ambi_bin.c:611
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:743
AMBI_BIN_PREPROC ambi_bin_getHRIRsPreProc(void *const hAmbi)
Returns HRIR pre-processing strategy.
Definition ambi_bin.c:697
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:709
int ambi_bin_getDAWsamplerate(void *const hAmbi)
Returns the DAW/Host sample rate.
Definition ambi_bin.c:835
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:596
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:632
void ambi_bin_setEnableMaxRE(void *const hAmbi, int newState)
Sets a flag to enable/disable the max_rE weighting.
Definition ambi_bin.c:569
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:522
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:766
int ambi_bin_getChOrder(void *const hAmbi)
Returns the Ambisonic channel ordering convention currently being used to decode with,...
Definition ambi_bin.c:725
void ambi_bin_initCodec(void *const hAmbi)
Intialises the codec variables, based on current global/user parameters.
Definition ambi_bin.c:169
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:403
float ambi_bin_getPitch(void *const hAmbi)
Returns the 'pitch' rotation angle, in degrees.
Definition ambi_bin.c:778
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:641
int ambi_bin_getHRIRlength(void *const hAmbi)
Returns the length of HRIRs in time-domain samples.
Definition ambi_bin.c:821
float ambi_bin_getRoll(void *const hAmbi)
Returns the 'roll' rotation angle, in degrees.
Definition ambi_bin.c:784
int ambi_bin_getNumEars()
Returns the number of ears possessed by the average homo sapien (2)
Definition ambi_bin.c:755
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:562
void ambi_bin_setInputOrderPreset(void *const hAmbi, SH_ORDERS newOrder)
Sets the decoding order (see SH_ORDERS enum)
Definition ambi_bin.c:534
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:605
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:659
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:796
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:802
int ambi_bin_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition ambi_bin.c:668
char * ambi_bin_getSofaFilePath(void *const hAmbi)
Returns the file path for a .sofa file.
Definition ambi_bin.c:715
float ambi_bin_getProgressBar0_1(void *const hAmbi)
(Optional) Returns current intialisation/processing progress, between 0..1
Definition ambi_bin.c:679
void ambi_bin_destroy(void **const phAmbi)
Destroys an instance of ambi_bin.
Definition ambi_bin.c:111
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:512
void ambi_bin_setEnableTruncationEQ(void *const hAmbi, int newState)
Sets a flag to enable/disable (1 or 0) truncation EQ.
Definition ambi_bin.c:587
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:808
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:790
int ambi_bin_getInputOrderPreset(void *const hAmbi)
Returns the decoding order.
Definition ambi_bin.c:703
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:548
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:578
void ambi_bin_init(void *const hAmbi, int sampleRate)
Initialises ambi_bin with default settings, and samplerate.
Definition ambi_bin.c:149
CODEC_STATUS ambi_bin_getCodecStatus(void *const hAmbi)
Returns current codec status, see CODEC_STATUS enum.
Definition ambi_bin.c:673
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:691
float ambi_bin_getYaw(void *const hAmbi)
Returns the 'yaw' rotation angle, in degree.
Definition ambi_bin.c:772
int ambi_bin_getNDirs(void *const hAmbi)
Returns the number of directions in the currently used HRIR set.
Definition ambi_bin.c:814
void ambi_bin_getProgressBarText(void *const hAmbi, char *text)
(Optional) Returns current intialisation/processing progress text
Definition ambi_bin.c:685
int ambi_bin_getProcessingDelay()
Returns the processing delay in samples (may be used for delay compensation features)
Definition ambi_bin.c:841
void ambi_bin_setRoll(void *const hAmbi, float newRoll)
Sets the 'roll' rotation angle, in degrees.
Definition ambi_bin.c:625
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:505
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.
int N_hrir_dirs
number of HRIR directions in the current sofa file
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
int hrir_len
length of the HRIRs, this can be truncated, see "saf_sofa_reader.h"
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
int hrir_fs
sampling rate of the HRIRs, should ideally match the host sampling rate, although not required
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
Main structure for ambi_bin.
CODEC_STATUS codecStatus
see CODEC_STATUS
float EQ[HYBRID_BANDS]
EQ curve.
float_complex *** binframeTF
Output binaural signals in the time-frequency domain; HYBRID_BANDS x NUM_EARS x TIME_SLOTS.
float pitch
pitch (Euler) rotation angle, in degrees
CH_ORDER chOrdering
Ambisonic channel order convention (see CH_ORDER)
int bFlipRoll
flag to flip the sign of the roll rotation angle
int enableDiffuseMatching
0: disabled, 1: enabled
int bFlipPitch
flag to flip the sign of the pitch rotation angle
int enableTruncationEQ
0: disabled, 1: enabled
float_complex M_rot[MAX_NUM_SH_SIGNALS][MAX_NUM_SH_SIGNALS]
Current SH rotation matrix.
AMBI_BIN_DECODING_METHODS method
current decoding method (see AMBI_BIN_DECODING_METHODS)
int useRollPitchYawFlag
rotation order flag, 1: r-p-y, 0: y-p-r
int enableMaxRE
0: disabled, 1: enabled
PROC_STATUS procStatus
see PROC_STATUS
char * progressBarText
Current (re)initialisation step, string.
int useDefaultHRIRsFLAG
1: use default HRIRs in database, 0: use those from SOFA file
int bFlipYaw
flag to flip the sign of the yaw rotation angle
int new_order
new decoding order (current value will be replaced by this after next re-init)
void * hSTFT
afSTFT handle
NORM_TYPES norm
Ambisonic normalisation convention (see NORM_TYPES)
AMBI_BIN_PREPROC preProc
HRIR pre-processing strategy.
float_complex *** SHframeTF
Input spherical harmonic (SH) signals in the time-frequency domain; HYBRID_BANDS x MAX_NUM_SH_SIGNALS...
float progressBar0_1
Current (re)initialisation progress, between [0..1].
float freqVector[HYBRID_BANDS]
frequency vector for time-frequency transform, in Hz
float roll
roll (Euler) rotation angle, in degrees
int recalc_M_rotFLAG
0: no init required, 1: init required
int nSH
number of spherical harmonic signals
ambi_bin_codecPars * pars
Decoding specific data.
float yaw
yaw (Euler) rotation angle, in degrees
int order
current decoding order
int reinit_hrtfsFLAG
0: no init required, 1: init required
float ** SHFrameTD
Input spherical harmonic (SH) signals in the time-domain; MAX_NUM_SH_SIGNALS x AMBI_BIN_FRAME_SIZE.
int fs
host sampling rate
float ** binFrameTD
Output binaural signals in the time-domain; NUM_EARS x AMBI_BIN_FRAME_SIZE.
int enableRotation
Whether rotation should be enabled (1) or disabled (0)
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.