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->firstInit = 1;
81 pData->hSTFT = NULL;
82 pData->SHFrameTD = (float**)malloc2d(MAX_NUM_SH_SIGNALS, AMBI_BIN_FRAME_SIZE, sizeof(float));
83 pData->binFrameTD = (float**)malloc2d(NUM_EARS, AMBI_BIN_FRAME_SIZE, sizeof(float));
84 pData->SHframeTF = (float_complex***)malloc3d(HYBRID_BANDS, MAX_NUM_SH_SIGNALS, TIME_SLOTS, sizeof(float_complex));
85 pData->binframeTF = (float_complex***)malloc3d(HYBRID_BANDS, NUM_EARS, TIME_SLOTS, sizeof(float_complex));
86 afSTFT_getCentreFreqs(pData->hSTFT, (float)pData->fs, HYBRID_BANDS, (float*)pData->freqVector);
87
88 /* codec data */
89 pData->progressBar0_1 = 0.0f;
91 strcpy(pData->progressBarText,"");
93 ambi_bin_codecPars* pars = pData->pars;
94 pars->sofa_filepath = NULL;
95 pars->hrirs = NULL;
96 pars->hrir_dirs_deg = NULL;
98 pars->itds_s = NULL;
99 pars->hrtf_fb = NULL;
100 pars->weights = NULL;
101
102 /* flags */
105 pData->recalc_M_rotFLAG = 1;
106 pData->reinit_hrtfsFLAG = 1;
107}
108
110(
111 void ** const phAmbi
112)
113{
114 ambi_bin_data *pData = (ambi_bin_data*)(*phAmbi);
115 ambi_bin_codecPars *pars;
116
117 if (pData != NULL) {
118 /* not safe to free memory during intialisation/processing loop */
119 while (pData->codecStatus == CODEC_STATUS_INITIALISING ||
121 SAF_SLEEP(10);
122 }
123
124 /* free afSTFT and buffers */
125 afSTFT_destroy(&(pData->hSTFT));
126 free(pData->SHFrameTD);
127 free(pData->binFrameTD);
128 free(pData->SHframeTF);
129 free(pData->binframeTF);
130
131 pars = pData->pars;
132 free(pars->sofa_filepath);
133 free(pars->weights);
134 free(pars->hrtf_fb);
135 free(pars->itds_s);
136 free(pars->hrirs);
137 free(pars->hrir_dirs_deg);
138 free(pars);
139 free(pData->progressBarText);
140
141 free(pData);
142 pData = NULL;
143 *phAmbi = NULL;
144 }
145}
146
148(
149 void * const hAmbi,
150 int sampleRate
151)
152{
153 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
154
155 /* define frequency vector */
156 if(pData->fs != sampleRate || pData->firstInit){
157 pData->fs = sampleRate;
158 pData->reinit_hrtfsFLAG = 1;
160 pData->firstInit = 0;
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 /* Resample HRIRs if needed */
250 pars->hrir_orig_fs = pars->hrir_fs;
251 if(pars->hrir_fs!=pData->fs){
252 strcpy(pData->progressBarText, "Resampling HRIRs");
253 pData->progressBar0_1 = 0.25f;
254 float* hrirs_resampled;
255 int hrir_length_resample;
256 resampleHRIRs(pars->hrirs, pars->N_hrir_dirs, pars->hrir_len, pars->hrir_fs, pData->fs, 1, &hrirs_resampled, &hrir_length_resample);
257
258 /* Replace with resampled HRIRs */
259 pars->hrir_fs = pData->fs;
260 pars->hrir_len = hrir_length_resample;
261 pars->hrirs = realloc1d(pars->hrirs, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
262 memcpy(pars->hrirs, hrirs_resampled, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
263
264 /* Clean-up */
265 free(hrirs_resampled);
266 }
267
268 /* convert hrirs to filterbank coefficients */
269 pData->progressBar0_1 = 0.4f;
270 pars->hrtf_fb = realloc1d(pars->hrtf_fb, HYBRID_BANDS * NUM_EARS * (pars->N_hrir_dirs)*sizeof(float_complex));
271 HRIRs2HRTFs_afSTFT(pars->hrirs, pars->N_hrir_dirs, pars->hrir_len, HOP_SIZE, 0, 1, pars->hrtf_fb);
272 /* HRIR pre-processing */
273 if(pData->preProc == HRIR_PREPROC_EQ || pData->preProc == HRIR_PREPROC_ALL){
274 /* get integration weights */
275 strcpy(pData->progressBarText,"Applying HRIR diffuse-field EQ");
276 pData->progressBar0_1 = 0.5f;
277 if(pars->N_hrir_dirs<=3600){
278 pars->weights = realloc1d(pars->weights, pars->N_hrir_dirs*sizeof(float));
279 //getVoronoiWeights(pars->hrir_dirs_deg, pars->N_hrir_dirs, 0, pars->weights);
280 float * hrir_dirs_rad = (float*) malloc1d(pars->N_hrir_dirs*2*sizeof(float));
281 memcpy(hrir_dirs_rad, pars->hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
282 cblas_sscal(pars->N_hrir_dirs*2, SAF_PI/180.f, hrir_dirs_rad, 1);
283 sphElev2incl(hrir_dirs_rad, pars->N_hrir_dirs, 0, hrir_dirs_rad);
284 int supOrder = calculateGridWeights(hrir_dirs_rad, pars->N_hrir_dirs, -1, pars->weights);
285 if(supOrder < 1){
286 saf_print_warning("Could not calculate grid weights");
287 free(pars->weights);
288 pars->weights = NULL;
289 }
290 }
291 else{
292 saf_print_warning("Too many grid points to calculate grid weights. Assuming that the HRTF measurement grid was uniform.");
293 free(pars->weights);
294 pars->weights = NULL;
295 }
296 }
297
298 /* estimate the ITDs for each HRIR */
299 pData->progressBar0_1 = 0.6f;
300 pars->itds_s = realloc1d(pars->itds_s, pars->N_hrir_dirs*sizeof(float));
301 estimateITDs(pars->hrirs, pars->N_hrir_dirs, pars->hrir_len, pars->hrir_fs, pars->itds_s);
302
303 /* apply HRIR pre-processing */
304 pData->progressBar0_1 = 0.75f;
306 pData->preProc == HRIR_PREPROC_EQ || pData->preProc == HRIR_PREPROC_ALL ? 1 : 0, /* Apply Diffuse-field EQ? */
307 pData->preProc == HRIR_PREPROC_PHASE || pData->preProc == HRIR_PREPROC_ALL ? 1 : 0, /* Apply phase simplification EQ? */
308 pars->hrtf_fb);
309 pData->reinit_hrtfsFLAG = 0;
310 }
311
312 /* get new decoder */
313 strcpy(pData->progressBarText,"Computing Decoder");
314 pData->progressBar0_1 = 0.95f;
315 float_complex* decMtx;
316 decMtx = calloc1d(HYBRID_BANDS*NUM_EARS*nSH, sizeof(float_complex));
317 AMBI_BIN_DECODING_METHODS method = pData->method;
318 switch(method){
319 default:
322 BINAURAL_DECODER_LS, order, pData->freqVector, pars->itds_s, pars->weights,
323 pData->enableDiffuseMatching, pData->enableMaxRE, decMtx);
324 break;
327 BINAURAL_DECODER_LSDIFFEQ, order, pData->freqVector, pars->itds_s, pars->weights,
328 pData->enableDiffuseMatching, pData->enableMaxRE, decMtx);
329 break;
332 BINAURAL_DECODER_SPR, order, pData->freqVector, pars->itds_s, pars->weights,
333 pData->enableDiffuseMatching, pData->enableMaxRE, decMtx);
334 break;
337 BINAURAL_DECODER_TA, order, pData->freqVector, pars->itds_s, pars->weights,
338 pData->enableDiffuseMatching, pData->enableMaxRE, decMtx);
339 break;
342 BINAURAL_DECODER_MAGLS, order, pData->freqVector, pars->itds_s, pars->weights,
343 pData->enableDiffuseMatching, pData->enableMaxRE, decMtx);
344 break;
345 }
346
347 /* Apply Truncation EQ */
348 if(pData->enableTruncationEQ &&
349 pData->method==DECODING_METHOD_LS &&
350 pData->preProc!=HRIR_PREPROC_PHASE &&
352 {
353 double *kr;
354 float *w_n, *eqGain;
355 const int order_truncated = order;
356 const int order_target = 42; /* Equalizing diffuse field to 42nd order equivalent. */
357 const float softThreshold = 9.0; /* results in +9 dB max */
358 const double r = 0.085; /* spherical scatterer radius (approx. size of human head) */
359 const int numBands = HYBRID_BANDS;
360 const double c = 343.;
361
362 /* Prep */
363 kr = malloc1d(numBands * sizeof(double));
364 w_n = calloc1d((order_truncated+1), sizeof(float));
365 eqGain = calloc1d(numBands, sizeof(float));
366 for (int k=0; k<numBands; k++)
367 kr[k] = 2.0*SAF_PId / c * (double)pData->freqVector[k] * r;
368
369 if (pData->enableMaxRE) {
370 /* maxRE as order weighting */
371 float *maxRECoeffs = malloc1d((order_truncated+1) * sizeof(float));
372 beamWeightsMaxEV(order_truncated, maxRECoeffs);
373 for (int idx_n=0; idx_n<order_truncated+1; idx_n++) {
374 w_n[idx_n] = maxRECoeffs[idx_n];
375 w_n[idx_n] /= sqrtf((float)(2*idx_n+1) / (4.0f*SAF_PI));
376 }
377 float w_0 = w_n[0];
378 for (int idx_n=0; idx_n<order_truncated+1; idx_n++)
379 w_n[idx_n] /= w_0;
380 free(maxRECoeffs);
381 }
382 else {
383 /* just truncation, no tapering */
384 for (int idx_n=0; idx_n<order_truncated+1; idx_n++)
385 w_n[idx_n] = 1.0f;
386 }
387 truncationEQ(w_n, order_truncated, order_target, kr, numBands, softThreshold, eqGain);
388
389 /* apply to decoding matrix */
390 for (int idxBand=0; idxBand<numBands; idxBand++){
391 for (int idxSH=0; idxSH<pData->nSH; idxSH++){
392 decMtx[idxBand*NUM_EARS*nSH+0*nSH+idxSH] = crmulf(decMtx[idxBand*NUM_EARS*nSH+0*nSH+idxSH], eqGain[idxBand]); /* left ear */
393 decMtx[idxBand*NUM_EARS*nSH+1*nSH+idxSH] = crmulf(decMtx[idxBand*NUM_EARS*nSH+1*nSH+idxSH], eqGain[idxBand]); /* right ear */
394 }
395 }
396
397 /* clean-up */
398 free(kr);
399 free(w_n);
400 free(eqGain);
401 }
402
403 /* replace current decoder */
404 memset(pars->M_dec, 0, HYBRID_BANDS*NUM_EARS*MAX_NUM_SH_SIGNALS*sizeof(float_complex));
405 for(band=0; band<HYBRID_BANDS; band++)
406 for(i=0; i<NUM_EARS; i++)
407 for(j=0; j<nSH; j++)
408 pars->M_dec[band][i][j] = decMtx[band*NUM_EARS*nSH + i*nSH + j];
409 free(decMtx);
410
411 /* rotation matrix will need to be updated too */
412 pData->recalc_M_rotFLAG = 1;
413
414 pData->order = order;
415
416 /* done! */
417 strcpy(pData->progressBarText,"Done!");
418 pData->progressBar0_1 = 1.0f;
420}
421
423(
424 void * const hAmbi,
425 const float *const * inputs,
426 float* const* const outputs,
427 int nInputs,
428 int nOutputs,
429 int nSamples
430)
431{
432 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
433 ambi_bin_codecPars* pars = pData->pars;
434 int ch, i, j, band;
435 const float_complex calpha = cmplxf(1.0f,0.0f), cbeta = cmplxf(0.0f, 0.0f);
436 float Rxyz[3][3];
437 float M_rot_tmp[MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS];
438
439 /* local copies of user parameters */
440 int order, nSH, enableRot;
441 NORM_TYPES norm;
442 CH_ORDER chOrdering;
443 norm = pData->norm;
444 chOrdering = pData->chOrdering;
445 order = pData->order;
446 nSH = (order+1)*(order+1);
447 enableRot = pData->enableRotation;
448
449 /* Process frame */
450 if (nSamples == AMBI_BIN_FRAME_SIZE && (pData->codecStatus == CODEC_STATUS_INITIALISED) ) {
452
453 /* Load time-domain data */
454 for(i=0; i < SAF_MIN(nSH, nInputs); i++)
455 utility_svvcopy(inputs[i], AMBI_BIN_FRAME_SIZE, pData->SHFrameTD[i]);
456 for(; i<nSH; i++)
457 memset(pData->SHFrameTD[i], 0, AMBI_BIN_FRAME_SIZE * sizeof(float)); /* fill remaining channels with zeros */
458
459 /* account for channel order convention */
460 switch(chOrdering){
461 case CH_ACN: /* already in ACN, do nothing */ break; /* Otherwise, convert to ACN... */
463 }
464
465 /* account for input normalisation scheme */
466 switch(norm){
467 case NORM_N3D: /* already in N3D, do nothing */ break; /* Otherwise, convert to N3D... */
470 }
471
472 /* Apply time-frequency transform (TFT) */
474
475 /* Main processing: */
476 if(order > 0 && enableRot) {
477 /* Apply rotation */
478 if(pData->recalc_M_rotFLAG){
479 /* Compute the new SH rotation matrix */
480 memset(pData->M_rot, 0, MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS*sizeof(float_complex));
481 yawPitchRoll2Rzyx(pData->yaw, pData->pitch, pData->roll, pData->useRollPitchYawFlag, Rxyz);
482 getSHrotMtxReal(Rxyz, (float*)M_rot_tmp, order);
483 for (i = 0; i < nSH; i++)
484 for (j = 0; j < nSH; j++)
485 pData->M_rot[i][j] = cmplxf(M_rot_tmp[i*nSH + j], 0.0f);
486
487 /* Bake the rotation into the decoding matrix */
488 for(band = 0; band < HYBRID_BANDS; band++) {
489 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, NUM_EARS, nSH, nSH, &calpha,
490 (float_complex*)pars->M_dec[band], MAX_NUM_SH_SIGNALS,
491 (float_complex*)pData->M_rot, MAX_NUM_SH_SIGNALS, &cbeta,
492 (float_complex*)pars->M_dec_rot[band], MAX_NUM_SH_SIGNALS);
493 }
494 pData->recalc_M_rotFLAG = 0;
495 }
496 }
497
498 /* Apply the decoder to go from SH input to binaural output */
499 for(band = 0; band < HYBRID_BANDS; band++) {
500 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, NUM_EARS, TIME_SLOTS, nSH, &calpha,
501 enableRot ? (float_complex*)pars->M_dec_rot[band] : (float_complex*)pars->M_dec[band], MAX_NUM_SH_SIGNALS,
502 FLATTEN2D(pData->SHframeTF[band]), TIME_SLOTS, &cbeta,
503 FLATTEN2D(pData->binframeTF[band]), TIME_SLOTS);
504 }
505
506 /* inverse-TFT */
508
509 /* Copy to output */
510 for (ch = 0; ch < SAF_MIN(NUM_EARS, nOutputs); ch++)
511 utility_svvcopy(pData->binFrameTD[ch], AMBI_BIN_FRAME_SIZE, outputs[ch]);
512 for (; ch < nOutputs; ch++)
513 memset(outputs[ch], 0, AMBI_BIN_FRAME_SIZE*sizeof(float));
514 }
515 else
516 for (ch=0; ch < nOutputs; ch++)
517 memset(outputs[ch],0, AMBI_BIN_FRAME_SIZE*sizeof(float));
518
520}
521
522
523/* Set Functions */
524
525void ambi_bin_refreshParams(void* const hAmbi)
526{
527 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
528 pData->reinit_hrtfsFLAG = 1;
530}
531
532void ambi_bin_setUseDefaultHRIRsflag(void* const hAmbi, int newState)
533{
534 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
535
536 if((!pData->useDefaultHRIRsFLAG) && (newState)){
537 pData->useDefaultHRIRsFLAG = newState;
538 ambi_bin_refreshParams(hAmbi); // re-init and re-calc
539 }
540}
541
542void ambi_bin_setSofaFilePath(void* const hAmbi, const char* path)
543{
544 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
545 ambi_bin_codecPars* pars = pData->pars;
546
547 pars->sofa_filepath = realloc1d(pars->sofa_filepath, strlen(path) + 1);
548 strcpy(pars->sofa_filepath, path);
549 pData->useDefaultHRIRsFLAG = 0;
550 ambi_bin_refreshParams(hAmbi); // re-init and re-calc
551
552}
553
554void ambi_bin_setInputOrderPreset(void* const hAmbi, SH_ORDERS newOrder)
555{
556 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
557 if(pData->order != (int)newOrder){
558 pData->new_order = (int)newOrder;
560 }
561 /* FUMA only supports 1st order */
562 if(pData->new_order!=SH_ORDER_FIRST && pData->chOrdering == CH_FUMA)
563 pData->chOrdering = CH_ACN;
564 if(pData->new_order!=SH_ORDER_FIRST && pData->norm == NORM_FUMA)
565 pData->norm = NORM_SN3D;
566}
567
569{
570 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
571 pData->method = newMethod;
573}
574
575void ambi_bin_setChOrder(void* const hAmbi, int newOrder)
576{
577 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
578 if((CH_ORDER)newOrder != CH_FUMA || pData->new_order==SH_ORDER_FIRST)/* FUMA only supports 1st order */
579 pData->chOrdering = (CH_ORDER)newOrder;
580}
581
582void ambi_bin_setNormType(void* const hAmbi, int newType)
583{
584 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
585 if((NORM_TYPES)newType != NORM_FUMA || pData->new_order==SH_ORDER_FIRST)/* FUMA only supports 1st order */
586 pData->norm = (NORM_TYPES)newType;
587}
588
589void ambi_bin_setEnableMaxRE(void* const hAmbi, int newState)
590{
591 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
592 if(pData->enableMaxRE != newState){
593 pData->enableMaxRE = newState;
595 }
596}
597
598void ambi_bin_setEnableDiffuseMatching(void* const hAmbi, int newState)
599{
600 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
601 if(pData->enableDiffuseMatching != newState){
602 pData->enableDiffuseMatching = newState;
604 }
605}
606
607void ambi_bin_setEnableTruncationEQ(void* const hAmbi, int newState)
608{
609 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
610 if(pData->enableTruncationEQ != newState){
611 pData->enableTruncationEQ = newState;
613 }
614}
615
616void ambi_bin_setHRIRsPreProc(void* const hAmbi, AMBI_BIN_PREPROC newType)
617{
618 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
619 if(pData->preProc != newType){
620 pData->preProc = newType;
622 }
623}
624
625void ambi_bin_setEnableRotation(void* const hAmbi, int newState)
626{
627 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
628 pData->enableRotation = newState;
629}
630
631void ambi_bin_setYaw(void * const hAmbi, float newYaw)
632{
633 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
634 pData->yaw = pData->bFlipYaw == 1 ? -DEG2RAD(newYaw) : DEG2RAD(newYaw);
635 pData->recalc_M_rotFLAG = 1;
636}
637
638void ambi_bin_setPitch(void* const hAmbi, float newPitch)
639{
640 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
641 pData->pitch = pData->bFlipPitch == 1 ? -DEG2RAD(newPitch) : DEG2RAD(newPitch);
642 pData->recalc_M_rotFLAG = 1;
643}
644
645void ambi_bin_setRoll(void* const hAmbi, float newRoll)
646{
647 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
648 pData->roll = pData->bFlipRoll == 1 ? -DEG2RAD(newRoll) : DEG2RAD(newRoll);
649 pData->recalc_M_rotFLAG = 1;
650}
651
652void ambi_bin_setFlipYaw(void* const hAmbi, int newState)
653{
654 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
655 if(newState !=pData->bFlipYaw ){
656 pData->bFlipYaw = newState;
657 ambi_bin_setYaw(hAmbi, -ambi_bin_getYaw(hAmbi));
658 }
659}
660
661void ambi_bin_setFlipPitch(void* const hAmbi, int newState)
662{
663 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
664 if(newState !=pData->bFlipPitch ){
665 pData->bFlipPitch = newState;
666 ambi_bin_setPitch(hAmbi, -ambi_bin_getPitch(hAmbi));
667 }
668}
669
670void ambi_bin_setFlipRoll(void* const hAmbi, int newState)
671{
672 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
673 if(newState !=pData->bFlipRoll ){
674 pData->bFlipRoll = newState;
675 ambi_bin_setRoll(hAmbi, -ambi_bin_getRoll(hAmbi));
676 }
677}
678
679void ambi_bin_setRPYflag(void* const hAmbi, int newState)
680{
681 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
682 pData->useRollPitchYawFlag = newState;
683}
684
685
686/* Get Functions */
687
689{
690 return AMBI_BIN_FRAME_SIZE;
691}
692
694{
695 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
696 return pData->codecStatus;
697}
698
699float ambi_bin_getProgressBar0_1(void* const hAmbi)
700{
701 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
702 return pData->progressBar0_1;
703}
704
705void ambi_bin_getProgressBarText(void* const hAmbi, char* text)
706{
707 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
708 memcpy(text, pData->progressBarText, PROGRESSBARTEXT_CHAR_LENGTH*sizeof(char));
709}
710
712{
713 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
714 return pData->useDefaultHRIRsFLAG;
715}
716
718{
719 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
720 return pData->preProc;
721}
722
723int ambi_bin_getInputOrderPreset(void* const hAmbi)
724{
725 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
726 return pData->new_order;
727}
728
730{
731 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
732 return pData->method;
733}
734
735char* ambi_bin_getSofaFilePath(void* const hAmbi)
736{
737 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
738 ambi_bin_codecPars* pars = pData->pars;
739 if(pars->sofa_filepath!=NULL)
740 return pars->sofa_filepath;
741 else
742 return "/Spatial_Audio_Framework/Default";
743}
744
745int ambi_bin_getChOrder(void* const hAmbi)
746{
747 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
748 return (int)pData->chOrdering;
749}
750
751int ambi_bin_getNormType(void* const hAmbi)
752{
753 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
754 return (int)pData->norm;
755}
756
757int ambi_bin_getEnableMaxRE(void* const hAmbi)
758{
759 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
760 return pData->enableMaxRE;
761}
762
764{
765 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
766 return pData->enableDiffuseMatching;
767}
768
769int ambi_bin_getEnableTruncationEQ(void* const hAmbi)
770{
771 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
772 return pData->enableTruncationEQ;
773}
774
776{
777 return NUM_EARS;
778}
779
780int ambi_bin_getNSHrequired(void* const hAmbi)
781{
782 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
783 return pData->nSH;
784}
785
786int ambi_bin_getEnableRotation(void* const hAmbi)
787{
788 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
789 return pData->enableRotation;
790}
791
792float ambi_bin_getYaw(void* const hAmbi)
793{
794 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
795 return pData->bFlipYaw == 1 ? -RAD2DEG(pData->yaw) : RAD2DEG(pData->yaw);
796}
797
798float ambi_bin_getPitch(void* const hAmbi)
799{
800 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
801 return pData->bFlipPitch == 1 ? -RAD2DEG(pData->pitch) : RAD2DEG(pData->pitch);
802}
803
804float ambi_bin_getRoll(void* const hAmbi)
805{
806 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
807 return pData->bFlipRoll == 1 ? -RAD2DEG(pData->roll) : RAD2DEG(pData->roll);
808}
809
810int ambi_bin_getFlipYaw(void* const hAmbi)
811{
812 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
813 return pData->bFlipYaw;
814}
815
816int ambi_bin_getFlipPitch(void* const hAmbi)
817{
818 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
819 return pData->bFlipPitch;
820}
821
822int ambi_bin_getFlipRoll(void* const hAmbi)
823{
824 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
825 return pData->bFlipRoll;
826}
827
828int ambi_bin_getRPYflag(void* const hAmbi)
829{
830 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
831 return pData->useRollPitchYawFlag;
832}
833
834int ambi_bin_getNDirs(void* const hAmbi)
835{
836 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
837 ambi_bin_codecPars* pars = pData->pars;
838 return pars->N_hrir_dirs;
839}
840
841int ambi_bin_getHRIRlength(void* const hAmbi)
842{
843 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
844 ambi_bin_codecPars* pars = pData->pars;
845 return pars->hrir_len;
846}
847
848int ambi_bin_getHRIRsamplerate(void* const hAmbi)
849{
850 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
851 ambi_bin_codecPars* pars = pData->pars;
852 return pars->hrir_orig_fs;
853}
854
855int ambi_bin_getDAWsamplerate(void* const hAmbi)
856{
857 ambi_bin_data *pData = (ambi_bin_data*)(hAmbi);
858 return pData->fs;
859}
860
862{
863 return 12*HOP_SIZE;
864}
#define PROGRESSBARTEXT_CHAR_LENGTH
Length of progress bar string.
Definition _common.h:255
@ PROC_STATUS_ONGOING
Codec is processing input audio, and should not be reinitialised at this time.
Definition _common.h:248
@ PROC_STATUS_NOT_ONGOING
Codec is not processing input audio, and may be reinitialised if needed.
Definition _common.h:250
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:267
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:229
@ CODEC_STATUS_NOT_INITIALISED
Codec has not yet been initialised, or the codec configuration has changed.
Definition _common.h:232
@ CODEC_STATUS_INITIALISED
Codec is initialised and ready to process input audio.
Definition _common.h:230
@ CODEC_STATUS_INITIALISING
Codec is currently being initialised, input audio should not be processed.
Definition _common.h:235
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:575
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:780
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:757
int ambi_bin_getHRIRsamplerate(void *const hAmbi)
Returns the HRIR sample rate.
Definition ambi_bin.c:848
int ambi_bin_getNormType(void *const hAmbi)
Returns the Ambisonic normalisation convention currently being usedto decode with,...
Definition ambi_bin.c:751
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:670
void ambi_bin_setPitch(void *const hAmbi, float newPitch)
Sets the 'pitch' rotation angle, in degrees.
Definition ambi_bin.c:638
int ambi_bin_getProcessingDelay(void)
Returns the processing delay in samples (may be used for delay compensation features)
Definition ambi_bin.c:861
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:769
void ambi_bin_setYaw(void *const hAmbi, float newYaw)
Sets the 'yaw' rotation angle, in degrees.
Definition ambi_bin.c:631
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:763
AMBI_BIN_PREPROC ambi_bin_getHRIRsPreProc(void *const hAmbi)
Returns HRIR pre-processing strategy.
Definition ambi_bin.c:717
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:729
int ambi_bin_getDAWsamplerate(void *const hAmbi)
Returns the DAW/Host sample rate.
Definition ambi_bin.c:855
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:616
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:652
void ambi_bin_setEnableMaxRE(void *const hAmbi, int newState)
Sets a flag to enable/disable the max_rE weighting.
Definition ambi_bin.c:589
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:542
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:786
int ambi_bin_getChOrder(void *const hAmbi)
Returns the Ambisonic channel ordering convention currently being used to decode with,...
Definition ambi_bin.c:745
int ambi_bin_getNumEars(void)
Returns the number of ears possessed by the average homo sapien (2)
Definition ambi_bin.c:775
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:423
float ambi_bin_getPitch(void *const hAmbi)
Returns the 'pitch' rotation angle, in degrees.
Definition ambi_bin.c:798
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:661
int ambi_bin_getHRIRlength(void *const hAmbi)
Returns the length of HRIRs in time-domain samples.
Definition ambi_bin.c:841
float ambi_bin_getRoll(void *const hAmbi)
Returns the 'roll' rotation angle, in degrees.
Definition ambi_bin.c:804
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:582
void ambi_bin_setInputOrderPreset(void *const hAmbi, SH_ORDERS newOrder)
Sets the decoding order (see SH_ORDERS enum)
Definition ambi_bin.c:554
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:625
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:679
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:816
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:822
int ambi_bin_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition ambi_bin.c:688
char * ambi_bin_getSofaFilePath(void *const hAmbi)
Returns the file path for a .sofa file.
Definition ambi_bin.c:735
float ambi_bin_getProgressBar0_1(void *const hAmbi)
(Optional) Returns current intialisation/processing progress, between 0..1
Definition ambi_bin.c:699
void ambi_bin_destroy(void **const phAmbi)
Destroys an instance of ambi_bin.
Definition ambi_bin.c:110
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:532
void ambi_bin_setEnableTruncationEQ(void *const hAmbi, int newState)
Sets a flag to enable/disable (1 or 0) truncation EQ.
Definition ambi_bin.c:607
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:828
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:810
int ambi_bin_getInputOrderPreset(void *const hAmbi)
Returns the decoding order.
Definition ambi_bin.c:723
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:568
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:598
void ambi_bin_init(void *const hAmbi, int sampleRate)
Initialises ambi_bin with default settings, and samplerate.
Definition ambi_bin.c:148
CODEC_STATUS ambi_bin_getCodecStatus(void *const hAmbi)
Returns current codec status, see CODEC_STATUS enum.
Definition ambi_bin.c:693
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:711
float ambi_bin_getYaw(void *const hAmbi)
Returns the 'yaw' rotation angle, in degree.
Definition ambi_bin.c:792
int ambi_bin_getNDirs(void *const hAmbi)
Returns the number of directions in the currently used HRIR set.
Definition ambi_bin.c:834
void ambi_bin_getProgressBarText(void *const hAmbi, char *text)
(Optional) Returns current intialisation/processing progress text
Definition ambi_bin.c:705
void ambi_bin_setRoll(void *const hAmbi, float newRoll)
Sets the 'roll' rotation angle, in degrees.
Definition ambi_bin.c:645
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:525
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 resampleHRIRs(float *hrirs_in, int hrirs_N_dirs, int hrirs_in_len, int hrirs_in_fs, int hrirs_out_fs, int padToNextPow2, float **hrirs_out, int *hrirs_out_len)
Resamples a set of HRIRs from its original samplerate to a new samplerate.
Definition saf_hrir.c:366
void estimateITDs(float *hrirs, int N_dirs, int hrir_len, int fs, float *itds_s)
Estimates the interaural time-differences (ITDs) for each HRIR based on the cross-correlation between...
Definition saf_hrir.c:41
void HRIRs2HRTFs_afSTFT(float *hrirs, int N_dirs, int hrir_len, int hopsize, int LDmode, int hybridmode, float_complex *hrtf_fb)
Passes zero padded HRIRs through the afSTFT filterbank.
Definition saf_hrir.c:111
int calculateGridWeights(float *dirs_rad, int nDirs, int order, float *w)
Computes approximation of quadrature/integration weights for a given grid.
Definition saf_sh.c:1066
void 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
_Atomic_INT32 hrir_orig_fs
Can be different from hrir_fs if HRIRs were resampled.
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.
int firstInit
flag, 1: _init() function has never been called, 0: _init() function has been called
_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.