SAF
Loading...
Searching...
No Matches
ambi_dec.c
Go to the documentation of this file.
1/*
2 * Copyright 2017-2018 Leo McCormack
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
46#include "ambi_dec_internal.h"
47
49(
50 void ** const phAmbi
51)
52{
54 *phAmbi = (void*)pData;
55 int i, j, ch, band;
56
57 /* default user parameters */
58 loadLoudspeakerArrayPreset(LOUDSPEAKER_ARRAY_PRESET_T_DESIGN_24, pData->loudpkrs_dirs_deg, &(pData->new_nLoudpkrs), &(pData->loudpkrs_nDims));
59 pData->masterOrder = pData->new_masterOrder = 1;
60 for (band = 0; band<HYBRID_BANDS; band++)
61 pData->orderPerBand[band] = 1;
62 pData->useDefaultHRIRsFLAG = 1; /* pars->sofa_filepath must be valid to set this to 0 */
63 pData->enableHRIRsPreProc = 1;
64 pData->nLoudpkrs = pData->new_nLoudpkrs;
65 pData->chOrdering = CH_ACN;
66 pData->norm = NORM_SN3D;
69 pData->rE_WEIGHT[0] = 1;
70 pData->rE_WEIGHT[1] = 1;
71 pData->diffEQmode[0] = ENERGY_PRESERVING;
72 pData->diffEQmode[1] = ENERGY_PRESERVING;
73 pData->transitionFreq = 800.0f;
74
75 /* afSTFT stuff and audio buffers */
76 pData->fs = 48000.0f;
77 pData->hSTFT = NULL;
78 pData->SHFrameTD = (float**)malloc2d(MAX_NUM_SH_SIGNALS, AMBI_DEC_FRAME_SIZE, sizeof(float));
80 pData->SHframeTF = (float_complex***)malloc3d(HYBRID_BANDS, MAX_NUM_SH_SIGNALS, TIME_SLOTS, sizeof(float_complex));
81 pData->outputframeTF = (float_complex***)malloc3d(HYBRID_BANDS, MAX_NUM_LOUDSPEAKERS, TIME_SLOTS, sizeof(float_complex));
82 pData->binframeTF = (float_complex***)malloc3d(HYBRID_BANDS, NUM_EARS, TIME_SLOTS, sizeof(float_complex));
83
84 /* codec data */
85 pData->progressBar0_1 = 0.0f;
87 strcpy(pData->progressBarText,"");
90 ambi_dec_codecPars* pars = pData->pars;
91 for (i=0; i<NUM_DECODERS; i++){
92 for(j=0; j<MAX_SH_ORDER; j++){
93 pars->M_dec[i][j] = NULL;
94 pars->M_dec_cmplx[i][j] = NULL;
95 pars->M_dec_maxrE[i][j] = NULL;
96 pars->M_dec_cmplx_maxrE[i][j] = NULL;
97 }
98 }
99 pars->sofa_filepath = NULL;
100 pars->hrirs = NULL;
101 pars->hrir_dirs_deg = NULL;
102 pars->hrtf_vbap_gtableIdx = NULL;
103 pars->hrtf_vbap_gtableComp = NULL;
104 pars->itds_s = NULL;
105 pars->hrtf_fb = NULL;
106 pars->hrtf_fb_mag = NULL;
107 pars->weights = NULL;
108
109 /* internal parameters */
110 pData->binauraliseLS = pData->new_binauraliseLS = 0;
111
112 /* flags */
114 pData->reinit_hrtfsFLAG = 1;
115 for(ch=0; ch<MAX_NUM_LOUDSPEAKERS; ch++)
116 pData->recalc_hrtf_interpFLAG[ch] = 1;
117}
118
120(
121 void ** const phAmbi
122)
123{
124 ambi_dec_data *pData = (ambi_dec_data*)(*phAmbi);
125 ambi_dec_codecPars *pars;
126 int i, j;
127
128 if (pData != NULL) {
129 /* not safe to free memory during intialisation/processing loop */
130 while (pData->codecStatus == CODEC_STATUS_INITIALISING ||
132 SAF_SLEEP(10);
133 }
134
135 /* free afSTFT and buffers */
136 if(pData->hSTFT!=NULL)
137 afSTFT_destroy(&(pData->hSTFT));
138 free(pData->SHFrameTD);
139 free(pData->outputFrameTD);
140 free(pData->SHframeTF);
141 free(pData->outputframeTF);
142 free(pData->binframeTF);
143
144 /* free codec data */
145 pars = pData->pars;
146 free(pars->hrtf_vbap_gtableComp);
147 free(pars->hrtf_vbap_gtableIdx);
148 free(pars->hrtf_fb);
149 free(pars->hrtf_fb_mag);
150 free(pars->itds_s);
151 free(pars->sofa_filepath);
152 free(pars->hrirs);
153 free(pars->hrir_dirs_deg);
154 free(pars->weights);
155 for (i=0; i<NUM_DECODERS; i++){
156 for(j=0; j<MAX_SH_ORDER; j++){
157 free(pars->M_dec[i][j]);
158 free(pars->M_dec_cmplx[i][j]);
159 free(pars->M_dec_maxrE[i][j]);
160 free(pars->M_dec_cmplx_maxrE[i][j]);
161 }
162 }
163 free(pData->progressBarText);
164 free(pData);
165 pData = NULL;
166 *phAmbi = NULL;
167 }
168}
169
171(
172 void * const hAmbi,
173 int sampleRate
174)
175{
176 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
177
178 /* define frequency vector */
179 pData->fs = sampleRate;
180 afSTFT_getCentreFreqs(pData->hSTFT, (float)sampleRate, HYBRID_BANDS, pData->freqVector);
181}
182
184(
185 void* const hAmbi
186)
187{
188 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
189 ambi_dec_codecPars* pars = pData->pars;
190 int i, ch, d, j, n, ng, nGrid_dirs, masterOrder, nSH_order, max_nSH, nLoudspeakers;
191 float* grid_dirs_deg, *Y, *M_dec_tmp, *g, *a, *e, *a_n, *hrtf_vbap_gtable;;
192 float a_avg[MAX_SH_ORDER], e_avg[MAX_SH_ORDER], azi_incl[2], sum_elev;
193#ifdef SAF_ENABLE_SOFA_READER_MODULE
196#endif
197
199 return; /* re-init not required, or already happening */
200 while (pData->procStatus == PROC_STATUS_ONGOING){
201 /* re-init required, but we need to wait for the current processing loop to end */
202 pData->codecStatus = CODEC_STATUS_INITIALISING; /* indicate that we want to init */
203 SAF_SLEEP(10);
204 }
205
206 /* for progress bar */
208 strcpy(pData->progressBarText,"Initialising");
209 pData->progressBar0_1 = 0.0f;
210
211 /* reinit afSTFT */
212 masterOrder = pData->new_masterOrder;
213 max_nSH = (masterOrder+1)*(masterOrder+1);
214 nLoudspeakers = pData->new_nLoudpkrs;
215 if(pData->hSTFT==NULL){
216 if(pData->new_binauraliseLS)
217 afSTFT_create(&(pData->hSTFT), max_nSH, NUM_EARS, HOP_SIZE, 0, 1, AFSTFT_BANDS_CH_TIME);
218 else
219 afSTFT_create(&(pData->hSTFT), max_nSH, nLoudspeakers, HOP_SIZE, 0, 1, AFSTFT_BANDS_CH_TIME);
221 }
222 else{
223 if(pData->new_binauraliseLS)
224 afSTFT_channelChange(pData->hSTFT, max_nSH, NUM_EARS);
225 else
226 afSTFT_channelChange(pData->hSTFT, max_nSH, nLoudspeakers);
228 }
229 pData->binauraliseLS = pData->new_binauraliseLS;
230 pData->nLoudpkrs = nLoudspeakers;
231
232 /* Quick and dirty check to find loudspeaker dimensionality */
233 strcpy(pData->progressBarText,"Computing decoder");
234 pData->progressBar0_1 = 0.2f;
235 sum_elev = 0.0f;
236 for(ch=0; ch < nLoudspeakers; ch++)
237 sum_elev += fabsf(pData->loudpkrs_dirs_deg[ch][1]);
238 if( (((sum_elev < 5.0f) && (sum_elev > -5.0f))) || (nLoudspeakers < 4) )
239 pData->loudpkrs_nDims = 2;
240 else
241 pData->loudpkrs_nDims = 3;
242
243 /* add virtual loudspeakers for 2D case if using AllRAD, so that the triangulation cannot fail. */
244 if (pData->loudpkrs_nDims == 2 && (pData->dec_method[0]==DECODING_METHOD_ALLRAD || pData->dec_method[1]==DECODING_METHOD_ALLRAD)){
245 assert(nLoudspeakers<=MAX_NUM_LOUDSPEAKERS-2);
246 pData->loudpkrs_dirs_deg[nLoudspeakers][0] = 0.0f;
247 pData->loudpkrs_dirs_deg[nLoudspeakers][1] = -90.0f;
248 pData->loudpkrs_dirs_deg[nLoudspeakers+1][0] = 0.0f;
249 pData->loudpkrs_dirs_deg[nLoudspeakers+1][1] = 90.0f;
250 nLoudspeakers += 2;
251 }
252
253 /* prep */
254 nGrid_dirs = 480; /* Minimum t-design of degree 30, has 480 points */
255 g = malloc1d(nLoudspeakers*sizeof(float));
256 a = malloc1d(nGrid_dirs*sizeof(float));
257 e = malloc1d(nGrid_dirs*sizeof(float));
258
259 /* calculate loudspeaker decoding matrices */
260 for( d=0; d<NUM_DECODERS; d++){
261 M_dec_tmp = malloc1d(nLoudspeakers * max_nSH * sizeof(float));
262 switch(pData->dec_method[d]){
264 getLoudspeakerDecoderMtx((float*)pData->loudpkrs_dirs_deg, nLoudspeakers, LOUDSPEAKER_DECODER_SAD, masterOrder, 0, M_dec_tmp);
265 break;
267 getLoudspeakerDecoderMtx((float*)pData->loudpkrs_dirs_deg, nLoudspeakers, LOUDSPEAKER_DECODER_MMD, masterOrder, 0, M_dec_tmp);
268 break;
270 getLoudspeakerDecoderMtx((float*)pData->loudpkrs_dirs_deg, nLoudspeakers, LOUDSPEAKER_DECODER_EPAD, masterOrder, 0, M_dec_tmp);
271 break;
273 getLoudspeakerDecoderMtx((float*)pData->loudpkrs_dirs_deg, nLoudspeakers, LOUDSPEAKER_DECODER_ALLRAD, masterOrder, 0, M_dec_tmp);
274 break;
275 }
276
277 /* diffuse-field EQ for orders 1..masterOrder */
278 for( n=1; n<=masterOrder; n++){
279 /* truncate M_dec for each order */
280 nSH_order = (n+1)*(n+1);
281 free(pars->M_dec[d][n-1]);
282 pars->M_dec[d][n-1] = malloc1d(nLoudspeakers* nSH_order * sizeof(float));
283 free(pars->M_dec_cmplx[d][n-1]);
284 pars->M_dec_cmplx[d][n-1] = malloc1d(nLoudspeakers * nSH_order * sizeof(float_complex));
285 for(i=0; i<nLoudspeakers; i++){
286 for(j=0; j<nSH_order; j++){
287 pars->M_dec[d][n-1][i*nSH_order+j] = M_dec_tmp[i*max_nSH +j]; /* for applying in the time domain, and... */
288 pars->M_dec_cmplx[d][n-1][i*nSH_order+j] = cmplxf(pars->M_dec[d][n-1][i*nSH_order+j], 0.0f); /* for the time-frequency domain */
289 }
290 }
291
292 /* create dedicated maxrE weighted versions */
293 a_n = malloc1d(nSH_order*nSH_order*sizeof(float));
294 getMaxREweights(n, 1, a_n); /* weights returned as diagonal matrix */
295 free(pars->M_dec_maxrE[d][n-1]);
296 pars->M_dec_maxrE[d][n-1] = malloc1d(nLoudspeakers * nSH_order * sizeof(float));
297 free(pars->M_dec_cmplx_maxrE[d][n-1]);
298 pars->M_dec_cmplx_maxrE[d][n-1] = malloc1d(nLoudspeakers * nSH_order * sizeof(float_complex));
299 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nLoudspeakers, nSH_order, nSH_order, 1.0f,
300 pars->M_dec[d][n-1], nSH_order,
301 a_n, nSH_order, 0.0f,
302 pars->M_dec_maxrE[d][n-1], nSH_order); /* for applying in the time domain */
303 for(i=0; i<nLoudspeakers * nSH_order; i++)
304 pars->M_dec_cmplx_maxrE[d][n-1][i] = cmplxf(pars->M_dec_maxrE[d][n-1][i], 0.0f); /* for the time-frequency domain */
305
306 /* fire a plane-wave from each grid direction to find the total energy/amplitude (using non-maxrE weighted versions) */
307 Y = malloc1d(nSH_order*sizeof(float));
308 grid_dirs_deg = (float*)(&__Tdesign_degree_30_dirs_deg[0][0]);
309 for(ng=0; ng<nGrid_dirs; ng++){
310 azi_incl[0] = grid_dirs_deg[ng*2]*SAF_PI/180.0f;
311 azi_incl[1] = SAF_PI/2.0f-grid_dirs_deg[ng*2+1]*SAF_PI/180.0f;
312 getSHreal(n, (float*)azi_incl, 1, Y);
313 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasTrans, nLoudspeakers, 1, nSH_order, 1.0f,
314 pars->M_dec[d][n-1], nSH_order,
315 Y, nSH_order, 0.0f,
316 g, 1);
317 a[ng] = e[ng] = 0.0f;
318 for(i=0; i<nLoudspeakers; i++){
319 a[ng] += g[i];
320 e[ng] += powf(g[i], 2.0f);
321 }
322 }
323
324 /* determine the order+decoder dependent normalisation factor for energy+amplitude preserving decoding */
325 a_avg[n-1] = e_avg[n-1] = 0.0f;
326 for(ng=0; ng<nGrid_dirs; ng++){
327 a_avg[n-1] += a[ng];
328 e_avg[n-1] += e[ng];
329 }
330 a_avg[n-1] /= (float)nGrid_dirs;
331 e_avg[n-1] /= (float)nGrid_dirs;
332 pars->M_norm[d][n-1][0] = 1.0f/(a_avg[n-1]+2.23e-6f); /* use this to preserve omni amplitude */
333 pars->M_norm[d][n-1][1] = sqrtf(1.0f/(e_avg[n-1]+2.23e-6f)); /* use this to preserve omni energy */
334 free(a_n);
335 free(Y);
336
337 /* remove virtual loudspeakers from the decoder (if needed) */
338 if (pData->loudpkrs_nDims == 2 && (pData->dec_method[0]==DECODING_METHOD_ALLRAD || pData->dec_method[1]==DECODING_METHOD_ALLRAD)){
339 pars->M_dec[d][n-1] = realloc1d(pars->M_dec[d][n-1], pData->nLoudpkrs * nSH_order * sizeof(float));
340 pars->M_dec_cmplx[d][n-1] = realloc1d(pars->M_dec_cmplx[d][n-1], pData->nLoudpkrs * nSH_order * sizeof(float_complex));
341 pars->M_dec_maxrE[d][n-1] = realloc1d(pars->M_dec_maxrE[d][n-1], pData->nLoudpkrs * nSH_order * sizeof(float));
342 pars->M_dec_cmplx_maxrE[d][n-1] = realloc1d(pars->M_dec_cmplx_maxrE[d][n-1], pData->nLoudpkrs * nSH_order * sizeof(float_complex));
343 }
344 }
345 free(M_dec_tmp);
346 }
347
348 /* update order */
349 pData->masterOrder = pData->new_masterOrder;
350
351 /* Binaural-related initialisations */
352 if(pData->reinit_hrtfsFLAG){
353 strcpy(pData->progressBarText,"Computing VBAP gain table");
354 pData->progressBar0_1 = 0.4f;
355
356 /* load sofa file or load default hrir data */
357#ifdef SAF_ENABLE_SOFA_READER_MODULE
358 if(!pData->useDefaultHRIRsFLAG && pars->sofa_filepath!=NULL){
359 /* Load SOFA file */
361
362 /* Load defaults instead */
363 if(error!=SAF_SOFA_OK || sofa.nReceivers!=NUM_EARS){
364 pData->useDefaultHRIRsFLAG = 1;
365 saf_print_warning("Unable to load the specified SOFA file, or it contained something other than 2 channels. Using default HRIR data instead.");
366 }
367 else{
368 /* Copy SOFA data */
369 pars->hrir_fs = (int)sofa.DataSamplingRate;
370 pars->hrir_len = sofa.DataLengthIR;
371 pars->N_hrir_dirs = sofa.nSources;
372 pars->hrirs = realloc1d(pars->hrirs, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
373 memcpy(pars->hrirs, sofa.DataIR, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
374 pars->hrir_dirs_deg = realloc1d(pars->hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
375 cblas_scopy(pars->N_hrir_dirs, sofa.SourcePosition, 3, pars->hrir_dirs_deg, 2); /* azi */
376 cblas_scopy(pars->N_hrir_dirs, &sofa.SourcePosition[1], 3, &pars->hrir_dirs_deg[1], 2); /* elev */
377 }
378
379 /* Clean-up */
380 saf_sofa_close(&sofa);
381 }
382#else
383 pData->useDefaultHRIRsFLAG = 1; /* Can only load the default HRIR data */
384#endif
385 if(pData->useDefaultHRIRsFLAG){
386 /* Copy default HRIR data */
390 pars->hrirs = realloc1d(pars->hrirs, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
391 memcpy(pars->hrirs, (float*)__default_hrirs, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
392 pars->hrir_dirs_deg = realloc1d(pars->hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
393 memcpy(pars->hrir_dirs_deg, (float*)__default_hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
394 }
395
396 /* estimate the ITDs for each HRIR */
397 pars->itds_s = realloc1d(pars->itds_s, pars->N_hrir_dirs*sizeof(float));
398 estimateITDs(pars->hrirs, pars->N_hrir_dirs, pars->hrir_len, pars->hrir_fs, pars->itds_s);
399
400 /* generate VBAP gain table for the hrir_dirs */
401 hrtf_vbap_gtable = NULL;
402 pars->hrtf_vbapTableRes[0] = 2; /* azimuth resolution in degrees */
403 pars->hrtf_vbapTableRes[1] = 5; /* elevation resolution in degrees */
404 generateVBAPgainTable3D(pars->hrir_dirs_deg, pars->N_hrir_dirs, pars->hrtf_vbapTableRes[0], pars->hrtf_vbapTableRes[1], 1, 0, 0.0f,
405 &hrtf_vbap_gtable, &(pars->N_hrtf_vbap_gtable), &(pars->hrtf_nTriangles));
406 if(hrtf_vbap_gtable==NULL){
407 /* if generating vbap gain tabled failed, re-calculate with default HRIR set (which is known to triangulate correctly) */
408 pData->useDefaultHRIRsFLAG = 1;
409 ambi_dec_initCodec(hAmbi);
410 }
411
412 /* compress VBAP table (i.e. remove the zero elements) */
413 pars->hrtf_vbap_gtableComp = realloc1d(pars->hrtf_vbap_gtableComp, pars->N_hrtf_vbap_gtable * 3 * sizeof(float));
414 pars->hrtf_vbap_gtableIdx = realloc1d(pars->hrtf_vbap_gtableIdx, pars->N_hrtf_vbap_gtable * 3 * sizeof(int));
416
417 /* convert hrirs to filterbank coefficients */
418 strcpy(pData->progressBarText,"Preparing HRIRs");
419 pData->progressBar0_1 = 0.85f;
420 pars->hrtf_fb = realloc1d(pars->hrtf_fb, HYBRID_BANDS * NUM_EARS * (pars->N_hrir_dirs)*sizeof(float_complex));
421 HRIRs2HRTFs_afSTFT(pars->hrirs, pars->N_hrir_dirs, pars->hrir_len, HOP_SIZE, 0, 1, pars->hrtf_fb);
422 /* HRIR pre-processing */
423 if(pData->enableHRIRsPreProc){
424 /* get integration weights */
425 strcpy(pData->progressBarText,"Applying HRIR Pre-Processing");
426 pData->progressBar0_1 = 0.95f;
427 if(pars->N_hrir_dirs<=3600){
428 pars->weights = realloc1d(pars->weights, pars->N_hrir_dirs*sizeof(float));
429 //getVoronoiWeights(pars->hrir_dirs_deg, pars->N_hrir_dirs, 0, pars->weights);
430 float * hrir_dirs_rad = (float*) malloc1d(pars->N_hrir_dirs*2*sizeof(float));
431 memcpy(hrir_dirs_rad, pars->hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
432 cblas_sscal(pars->N_hrir_dirs*2, SAF_PI/180.f, hrir_dirs_rad, 1);
433 sphElev2incl(hrir_dirs_rad, pars->N_hrir_dirs, 0, hrir_dirs_rad);
434 int supOrder = calculateGridWeights(hrir_dirs_rad, pars->N_hrir_dirs, -1, pars->weights);
435 if(supOrder < 1){
436 saf_print_warning("Could not calculate grid weights");
437 free(pars->weights);
438 pars->weights = NULL;
439 }
440 }
441 else{
442 saf_print_warning("Too many grid points");
443 free(pars->weights);
444 pars->weights = NULL;
445 }
446 diffuseFieldEqualiseHRTFs(pars->N_hrir_dirs, pars->itds_s, pData->freqVector, HYBRID_BANDS, pars->weights, 1, 0, pars->hrtf_fb);
447 }
448
449 /* calculate magnitude responses */
450 pars->hrtf_fb_mag = realloc1d(pars->hrtf_fb_mag, HYBRID_BANDS*NUM_EARS*(pars->N_hrir_dirs)*sizeof(float));
451 for(i=0; i<HYBRID_BANDS*NUM_EARS* (pars->N_hrir_dirs); i++)
452 pars->hrtf_fb_mag[i] = cabsf(pars->hrtf_fb[i]);
453
454 /* clean-up */
455 free(hrtf_vbap_gtable);
456 pData->reinit_hrtfsFLAG = 0;
457 }
458
459 /* done! */
460 strcpy(pData->progressBarText,"Done!");
461 pData->progressBar0_1 = 1.0f;
463
464 free(g);
465 free(a);
466 free(e);
467}
468
470(
471 void * const hAmbi,
472 const float *const * inputs,
473 float* const* const outputs,
474 int nInputs,
475 int nOutputs,
476 int nSamples
477)
478{
479 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
480 ambi_dec_codecPars* pars = pData->pars;
481 int ch, ear, i, band, orderBand, nSH_band, decIdx, nSH;
482 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
483
484 /* local copies of user parameters */
485 int nLoudspeakers, binauraliseLS, masterOrder;
486 int orderPerBand[HYBRID_BANDS], rE_WEIGHT[NUM_DECODERS];
487 float transitionFreq;
489 NORM_TYPES norm;
490 CH_ORDER chOrdering;
491 masterOrder = pData->masterOrder;
492 nSH = ORDER2NSH(masterOrder);
493 nLoudspeakers = pData->nLoudpkrs;
494 memcpy(orderPerBand, pData->orderPerBand, HYBRID_BANDS*sizeof(int));
495 transitionFreq = pData->transitionFreq;
496 memcpy(diffEQmode, pData->diffEQmode, NUM_DECODERS*sizeof(int));
497 binauraliseLS = pData->binauraliseLS;
498 norm = pData->norm;
499 chOrdering = pData->chOrdering;
500 memcpy(rE_WEIGHT, pData->rE_WEIGHT, NUM_DECODERS*sizeof(int));
501
502 /* Process frame */
503 if (nSamples == AMBI_DEC_FRAME_SIZE && (pData->codecStatus == CODEC_STATUS_INITIALISED) ) {
505
506 /* Load time-domain data */
507 for(i=0; i < SAF_MIN(nSH, nInputs); i++)
508 utility_svvcopy(inputs[i], AMBI_DEC_FRAME_SIZE, pData->SHFrameTD[i]);
509 for(; i<nSH; i++)
510 memset(pData->SHFrameTD[i], 0, AMBI_DEC_FRAME_SIZE * sizeof(float)); /* fill remaining channels with zeros */
511
512 /* account for channel order convention */
513 switch(chOrdering){
514 case CH_ACN: /* already ACN, do nothing */ break; /* Otherwise, convert to ACN... */
516 }
517
518 /* account for input normalisation scheme */
519 switch(norm){
520 case NORM_N3D: /* already in N3D, do nothing */ break; /* Otherwise, convert to N3D... */
523 }
524
525 /* Apply time-frequency transform (TFT) */
527
528 /* Decode to loudspeaker set-up */
529 memset(FLATTEN3D(pData->outputframeTF), 0, HYBRID_BANDS*MAX_NUM_LOUDSPEAKERS*TIME_SLOTS*sizeof(float_complex));
530 for(band=0; band<HYBRID_BANDS; band++){
531 orderBand = SAF_MAX(SAF_MIN(orderPerBand[band], masterOrder),1);
532 nSH_band = (orderBand+1)*(orderBand+1);
533
534 /* There is a different decoder for low (0) and high (1) frequencies, and for max_rE weights enabled/disabled */
535 decIdx = pData->freqVector[band] < transitionFreq ? 0 : 1;
536 if(rE_WEIGHT[decIdx]){
537 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nLoudspeakers, TIME_SLOTS, nSH_band, &calpha,
538 pars->M_dec_cmplx_maxrE[decIdx][orderBand-1], nSH_band,
539 FLATTEN2D(pData->SHframeTF[band]), TIME_SLOTS, &cbeta,
540 FLATTEN2D(pData->outputframeTF[band]), TIME_SLOTS);
541 }
542 else{
543 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nLoudspeakers, TIME_SLOTS, nSH_band, &calpha,
544 pars->M_dec_cmplx[decIdx][orderBand-1], nSH_band,
545 FLATTEN2D(pData->SHframeTF[band]), TIME_SLOTS, &cbeta,
546 FLATTEN2D(pData->outputframeTF[band]), TIME_SLOTS);
547 }
548
549 /* Apply scaling to preserve either the amplitude or energy when the decododing orders are different over frequency */
550 cblas_sscal(/*re+im*/2*nLoudspeakers*TIME_SLOTS, pars->M_norm[decIdx][orderBand-1][diffEQmode[decIdx]==AMPLITUDE_PRESERVING ? 0 : 1],
551 (float*)FLATTEN2D(pData->outputframeTF[band]), 1);
552 }
553
554 /* Binauralise the loudspeaker signals */
555 if(binauraliseLS){
556 /* Initialise the binaural buffer with zeros */
557 memset(FLATTEN3D(pData->binframeTF), 0, HYBRID_BANDS*NUM_EARS*TIME_SLOTS * sizeof(float_complex));
558
559 /* Convolve each loudspeaker signals with the respective HRTFs */
560 for (ch = 0; ch < nLoudspeakers; ch++) {
561 if(pData->recalc_hrtf_interpFLAG[ch]){
562 /* Re-compute the interpolated HRTF (only if loudspeaker direction changed) */
563 ambi_dec_interpHRTFs(hAmbi, pData->loudpkrs_dirs_deg[ch][0], pData->loudpkrs_dirs_deg[ch][1], pars->hrtf_interp[ch]);
564 pData->recalc_hrtf_interpFLAG[ch] = 0;
565 }
566
567 /* Convolve this loudspeaker channel with the interpolated HRTF, and add it to the binaural buffer */
568 for (band = 0; band < HYBRID_BANDS; band++)
569 for (ear = 0; ear < NUM_EARS; ear++)
570 cblas_caxpy(TIME_SLOTS, &pars->hrtf_interp[ch][band][ear], pData->outputframeTF[band][ch], 1, pData->binframeTF[band][ear], 1);
571 }
572
573 /* Scale by sqrt(number of loudspeakers) */
574 cblas_sscal(/*re+im*/2*HYBRID_BANDS*NUM_EARS*TIME_SLOTS, 1.0f/sqrtf((float)nLoudspeakers), (float*)FLATTEN3D(pData->binframeTF), 1);
575 }
576
577 /* inverse-TFT */
578 afSTFT_backward_knownDimensions(pData->hSTFT, binauraliseLS ? pData->binframeTF : pData->outputframeTF,
580
581 /* Copy to output buffer */
582 for(ch = 0; ch < SAF_MIN(binauraliseLS==1 ? NUM_EARS : nLoudspeakers, nOutputs); ch++)
583 utility_svvcopy(pData->outputFrameTD[ch], AMBI_DEC_FRAME_SIZE, outputs[ch]);
584 for (; ch < nOutputs; ch++)
585 memset(outputs[ch], 0, AMBI_DEC_FRAME_SIZE*sizeof(float));
586 }
587 else
588 for (ch=0; ch < nOutputs; ch++)
589 memset(outputs[ch], 0, AMBI_DEC_FRAME_SIZE*sizeof(float));
590
592}
593
594
595/* Set Functions */
596
597void ambi_dec_refreshSettings(void* const hAmbi)
598{
599 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
600 int ch;
601 for(ch=0; ch<MAX_NUM_LOUDSPEAKERS; ch++)
602 pData->recalc_hrtf_interpFLAG[ch] = 1;
603 pData->reinit_hrtfsFLAG = 1;
605}
606
607void ambi_dec_setMasterDecOrder(void * const hAmbi, int newValue)
608{
609 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
610 pData->new_masterOrder = SAF_MIN(SAF_MAX(newValue,1), MAX_SH_ORDER);
612 /* FUMA only supports 1st order */
613 if(pData->new_masterOrder!=SH_ORDER_FIRST && pData->chOrdering == CH_FUMA)
614 pData->chOrdering = CH_ACN;
615 if(pData->new_masterOrder!=SH_ORDER_FIRST && pData->norm == NORM_FUMA)
616 pData->norm = NORM_SN3D;
617}
618
619void ambi_dec_setDecOrder(void * const hAmbi, int newValue, int bandIdx)
620{
621 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
622 pData->orderPerBand[bandIdx] = SAF_MIN(SAF_MAX(newValue,1), pData->new_masterOrder);
623}
624
625void ambi_dec_setDecOrderAllBands(void * const hAmbi, int newValue)
626{
627 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
628 int band;
629
630 for(band=0; band<HYBRID_BANDS; band++)
631 pData->orderPerBand[band] = SAF_MIN(SAF_MAX(newValue,1), pData->new_masterOrder);
632}
633
634void ambi_dec_setLoudspeakerAzi_deg(void* const hAmbi, int index, float newAzi_deg)
635{
636 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
637 if(newAzi_deg>180.0f)
638 newAzi_deg = -360.0f + newAzi_deg;
639 newAzi_deg = SAF_MAX(newAzi_deg, -180.0f);
640 newAzi_deg = SAF_MIN(newAzi_deg, 180.0f);
641 if(pData->loudpkrs_dirs_deg[index][0] != newAzi_deg){
642 pData->loudpkrs_dirs_deg[index][0] = newAzi_deg;
643 pData->recalc_hrtf_interpFLAG[index] = 1;
645 }
646}
647
648void ambi_dec_setLoudspeakerElev_deg(void* const hAmbi, int index, float newElev_deg)
649{
650 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
651 newElev_deg = SAF_MAX(newElev_deg, -90.0f);
652 newElev_deg = SAF_MIN(newElev_deg, 90.0f);
653 if(pData->loudpkrs_dirs_deg[index][1] != newElev_deg){
654 pData->loudpkrs_dirs_deg[index][1] = newElev_deg;
655 pData->recalc_hrtf_interpFLAG[index] = 1;
657 }
658}
659
660void ambi_dec_setNumLoudspeakers(void* const hAmbi, int new_nLoudspeakers)
661{
662 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
663 int ch;
664 pData->new_nLoudpkrs = new_nLoudspeakers > MAX_NUM_LOUDSPEAKERS ? MAX_NUM_LOUDSPEAKERS : new_nLoudspeakers;
666 if(pData->nLoudpkrs != pData->new_nLoudpkrs){
667 for(ch=0; ch<MAX_NUM_LOUDSPEAKERS; ch++)
668 pData->recalc_hrtf_interpFLAG[ch] = 1;
670 }
671}
672
673void ambi_dec_setBinauraliseLSflag(void* const hAmbi, int newState)
674{
675 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
676
677 pData->new_binauraliseLS = newState;
678 if(pData->new_binauraliseLS != pData->binauraliseLS)
680}
681
682void ambi_dec_setUseDefaultHRIRsflag(void* const hAmbi, int newState)
683{
684 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
685
686 if((!pData->useDefaultHRIRsFLAG) && (newState)){
687 pData->useDefaultHRIRsFLAG = newState;
688 ambi_dec_refreshSettings(hAmbi); // re-init and re-calc
689 }
690}
691
692void ambi_dec_setSofaFilePath(void* const hAmbi, const char* path)
693{
694 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
695 ambi_dec_codecPars* pars = pData->pars;
696
697 pars->sofa_filepath = realloc1d(pars->sofa_filepath, strlen(path) + 1);
698 strcpy(pars->sofa_filepath, path);
699 pData->useDefaultHRIRsFLAG = 0;
700 ambi_dec_refreshSettings(hAmbi); // re-init and re-calc
701}
702
703void ambi_dec_setEnableHRIRsPreProc(void* const hAmbi, int newState)
704{
705 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
706 if(newState!=pData->enableHRIRsPreProc){
707 pData->enableHRIRsPreProc = newState;
708 ambi_dec_refreshSettings(hAmbi); // re-init and re-calc
709 }
710}
711
712void ambi_dec_setOutputConfigPreset(void* const hAmbi, int newPresetID)
713{
714 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
715 int ch;
716
717 loadLoudspeakerArrayPreset(newPresetID, pData->loudpkrs_dirs_deg, &(pData->new_nLoudpkrs), &(pData->loudpkrs_nDims));
718 for(ch=0; ch<MAX_NUM_LOUDSPEAKERS; ch++)
719 pData->recalc_hrtf_interpFLAG[ch] = 1;
721}
722
723void ambi_dec_setSourcePreset(void* const hAmbi, int newPresetID)
724{
725 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
726 int band, rangeIdx, curOrder, reverse;
727
728 rangeIdx = 0;
729 curOrder = 1;
730 reverse = 0;
731 switch(newPresetID){
732 /* Ideal spherical harmonics will have SH_ORDER at all frequencies */
733 case MIC_PRESET_IDEAL:
734 for(band=0; band<HYBRID_BANDS; band++)
735 pData->orderPerBand[band] = pData->masterOrder;
736 break;
737
738 /* For real microphone arrays, the maximum usable spherical harmonic order will depend on frequency */
739 case MIC_PRESET_ZYLIA:
740 for(band=0; band<HYBRID_BANDS; band++){
741 if(rangeIdx<2*(__Zylia_maxOrder-1)){
742 if(pData->freqVector[band]>__Zylia_freqRange[rangeIdx]){
743 if(!reverse)
744 curOrder++;
745 else
746 curOrder--;
747 reverse = (curOrder == __Zylia_maxOrder) || (reverse) ? 1 : 0;
748 rangeIdx++;
749 }
750 }
751 pData->orderPerBand[band] = SAF_MIN(pData->masterOrder,curOrder);
752 }
753 break;
754
755 case MIC_PRESET_EIGENMIKE32:
756 for(band=0; band<HYBRID_BANDS; band++){
757 if(rangeIdx<2*(__Eigenmike32_maxOrder-1)){
758 if(pData->freqVector[band]>__Eigenmike32_freqRange[rangeIdx]){
759 if(!reverse)
760 curOrder++;
761 else
762 curOrder--;
763 reverse = (curOrder == __Eigenmike32_maxOrder) || (reverse) ? 1 : 0;
764 rangeIdx++;
765 }
766 }
767 pData->orderPerBand[band] = SAF_MIN(pData->masterOrder,curOrder);
768 }
769 break;
770
771 case MIC_PRESET_DTU_MIC:
772 for(band=0; band<HYBRID_BANDS; band++){
773 if(rangeIdx<2*(__DTU_mic_maxOrder-1)){
774 if(pData->freqVector[band]>__DTU_mic_freqRange[rangeIdx]){
775 if(!reverse)
776 curOrder++;
777 else
778 curOrder--;
779 reverse = (curOrder == __DTU_mic_maxOrder) || (reverse) ? 1 : 0;
780 rangeIdx++;
781 }
782 }
783 pData->orderPerBand[band] = SAF_MIN(pData->masterOrder,curOrder);
784 }
785 break;
786 }
787}
788
789void ambi_dec_setChOrder(void* const hAmbi, int newOrder)
790{
791 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
792 if((CH_ORDER)newOrder != CH_FUMA || pData->new_masterOrder==SH_ORDER_FIRST) /* FUMA only supports 1st order */
793 pData->chOrdering = (CH_ORDER)newOrder;
794}
795
796void ambi_dec_setNormType(void* const hAmbi, int newType)
797{
798 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
799 if((NORM_TYPES)newType != NORM_FUMA || pData->new_masterOrder==SH_ORDER_FIRST) /* FUMA only supports 1st order */
800 pData->norm = (NORM_TYPES)newType;
801}
802
803void ambi_dec_setDecMethod(void* const hAmbi, int index, int newID)
804{
805 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
806 pData->dec_method[index] = newID;
808}
809
810void ambi_dec_setDecEnableMaxrE(void* const hAmbi, int index, int newID)
811{
812 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
813 pData->rE_WEIGHT[index] = newID;
814}
815
816void ambi_dec_setDecNormType(void* const hAmbi, int index, int newID)
817{
818 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
819 pData->diffEQmode[index] = newID;
820}
821
822void ambi_dec_setTransitionFreq(void* const hAmbi, float newValue)
823{
824 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
826}
827
828
829/* Get Functions */
830
832{
833 return AMBI_DEC_FRAME_SIZE;
834}
835
837{
838 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
839 return pData->codecStatus;
840}
841
842float ambi_dec_getProgressBar0_1(void* const hAmbi)
843{
844 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
845 return pData->progressBar0_1;
846}
847
848void ambi_dec_getProgressBarText(void* const hAmbi, char* text)
849{
850 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
851 memcpy(text, pData->progressBarText, PROGRESSBARTEXT_CHAR_LENGTH*sizeof(char));
852}
853
854int ambi_dec_getMasterDecOrder(void * const hAmbi)
855{
856 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
857 return pData->new_masterOrder;
858}
859
860int ambi_dec_getDecOrder(void * const hAmbi, int bandIdx)
861{
862 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
863 return pData->orderPerBand[bandIdx];
864}
865
866int ambi_dec_getDecOrderAllBands(void * const hAmbi)
867{
868 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
869 return pData->orderPerBand[0];
870}
871
873(
874 void* const hAmbi,
875 float** pX_vector,
876 int** pY_values,
877 int* pNpoints
878)
879{
880 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
881 (*pX_vector) = &pData->freqVector[0];
882 (*pY_values) = &pData->orderPerBand[0];
883 (*pNpoints) = HYBRID_BANDS;
884}
885
887{
888 return HYBRID_BANDS;
889}
890
891float ambi_dec_getLoudspeakerAzi_deg(void* const hAmbi, int index)
892{
893 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
894 return pData->loudpkrs_dirs_deg[index][0];
895}
896
897float ambi_dec_getLoudspeakerElev_deg(void* const hAmbi, int index)
898{
899 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
900 return pData->loudpkrs_dirs_deg[index][1];
901}
902
903int ambi_dec_getNumLoudspeakers(void* const hAmbi)
904{
905 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
906 return pData->new_nLoudpkrs;
907}
908
913
914int ambi_dec_getNSHrequired(void* const hAmbi)
915{
916 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
917 return (pData->masterOrder+1)*(pData->masterOrder+1);
918}
919
920int ambi_dec_getBinauraliseLSflag(void* const hAmbi)
921{
922 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
923 return pData->new_binauraliseLS;
924}
925
927{
928 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
929 return pData->useDefaultHRIRsFLAG;
930}
931
932char* ambi_dec_getSofaFilePath(void* const hAmbi)
933{
934 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
935 ambi_dec_codecPars* pars = pData->pars;
936 if(pars->sofa_filepath!=NULL)
937 return pars->sofa_filepath;
938 else
939 return "no_file";
940}
941
942int ambi_dec_getEnableHRIRsPreProc(void* const hAmbi)
943{
944 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
945 return pData->enableHRIRsPreProc;
946}
947
948int ambi_dec_getChOrder(void* const hAmbi)
949{
950 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
951 return (int)pData->chOrdering;
952}
953
954int ambi_dec_getNormType(void* const hAmbi)
955{
956 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
957 return (int)pData->norm;
958}
959
960int ambi_dec_getDecMethod(void* const hAmbi, int index)
961{
962 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
963 return pData->dec_method[index];
964}
965
966int ambi_dec_getDecEnableMaxrE(void* const hAmbi, int index)
967{
968 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
969 return pData->rE_WEIGHT[index];
970}
971
972int ambi_dec_getDecNormType(void* const hAmbi, int index)
973{
974 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
975 return pData->diffEQmode[index];
976}
977
978float ambi_dec_getTransitionFreq(void* const hAmbi)
979{
980 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
981 return pData->transitionFreq;
982}
983
984int ambi_dec_getHRIRsamplerate(void* const hAmbi)
985{
986 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
987 ambi_dec_codecPars* pars = pData->pars;
988 return pars->hrir_fs;
989}
990
991int ambi_dec_getDAWsamplerate(void* const hAmbi)
992{
993 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
994 return pData->fs;
995}
996
998{
999 return 12*HOP_SIZE;
1000}
1001
1002
1003
#define MAX_SH_ORDER
Maximum supported Ambisonic order.
Definition _common.h:52
#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_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
#define TIME_SLOTS
Number of STFT timeslots.
#define HOP_SIZE
STFT hop size.
#define HYBRID_BANDS
Number of frequency bands.
void ambi_dec_setDecOrderAllBands(void *const hAmbi, int newValue)
Sets the decoding order for all frequency bands.
Definition ambi_dec.c:625
void ambi_dec_create(void **const phAmbi)
Creates an instance of the ambi_dec.
Definition ambi_dec.c:49
int ambi_dec_getNumLoudspeakers(void *const hAmbi)
Returns the number of loudspeakers in the current layout.
Definition ambi_dec.c:903
void ambi_dec_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 loudspeaker channels.
Definition ambi_dec.c:470
int ambi_dec_getMasterDecOrder(void *const hAmbi)
Returns the master/maximum decoding order (see SH_ORDERS enum)
Definition ambi_dec.c:854
int ambi_dec_getNSHrequired(void *const hAmbi)
Returns the number of spherical harmonic signals required by the current decoding order: (current_ord...
Definition ambi_dec.c:914
void ambi_dec_setDecOrder(void *const hAmbi, int newValue, int bandIdx)
Sets the decoding order for a given frequency band.
Definition ambi_dec.c:619
float ambi_dec_getProgressBar0_1(void *const hAmbi)
(Optional) Returns current intialisation/processing progress, between 0..1
Definition ambi_dec.c:842
int ambi_dec_getEnableHRIRsPreProc(void *const hAmbi)
Returns the flag indicating whether the pre-processing applied to the HRTFs is enabled (1) or disable...
Definition ambi_dec.c:942
void ambi_dec_setBinauraliseLSflag(void *const hAmbi, int newState)
Sets flag to dictate whether the output loudspeaker signals should be binauralised.
Definition ambi_dec.c:673
float ambi_dec_getLoudspeakerElev_deg(void *const hAmbi, int index)
Returns the loudspeaker elevation in degrees for a given index.
Definition ambi_dec.c:897
void ambi_dec_setChOrder(void *const hAmbi, int newOrder)
Sets the Ambisonic channel ordering convention to decode with, in order to match the convention emplo...
Definition ambi_dec.c:789
int ambi_dec_getDecNormType(void *const hAmbi, int index)
Returns the current equalisation approach for one of the decoders (see AMBI_DEC_DIFFUSE_FIELD_EQ_APPR...
Definition ambi_dec.c:972
int ambi_dec_getDecOrder(void *const hAmbi, int bandIdx)
Returns the decoding order for a given frequency band index (see SH_ORDERS enum)
Definition ambi_dec.c:860
void ambi_dec_getProgressBarText(void *const hAmbi, char *text)
(Optional) Returns current intialisation/processing progress text
Definition ambi_dec.c:848
int ambi_dec_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition ambi_dec.c:831
int ambi_dec_getNormType(void *const hAmbi)
Returns the Ambisonic normalisation convention currently being usedto decode with,...
Definition ambi_dec.c:954
int ambi_dec_getHRIRsamplerate(void *const hAmbi)
Returns the HRIR sample rate.
Definition ambi_dec.c:984
void ambi_dec_setDecEnableMaxrE(void *const hAmbi, int index, int newID)
Sets a flag to enable/disable (1 or 0) the max_rE weighting for one of the decoders.
Definition ambi_dec.c:810
void ambi_dec_initCodec(void *const hAmbi)
Intialises the codec variables, based on current global/user parameters.
Definition ambi_dec.c:184
void ambi_dec_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_dec.c:692
int ambi_dec_getUseDefaultHRIRsflag(void *const hAmbi)
Returns the value of a flag used to dictate whether the default HRIRs in the Spatial_Audio_Framework ...
Definition ambi_dec.c:926
void ambi_dec_setSourcePreset(void *const hAmbi, int newPresetID)
Sets the source preset (ideal SH or SH signals derived from mic arrays)
Definition ambi_dec.c:723
void ambi_dec_refreshSettings(void *const hAmbi)
Sets all intialisation flags to 1.
Definition ambi_dec.c:597
void ambi_dec_getDecOrderHandle(void *const hAmbi, float **pX_vector, int **pY_values, int *pNpoints)
Returns handles for the decoding orders and frequency vector.
Definition ambi_dec.c:873
int ambi_dec_getDecOrderAllBands(void *const hAmbi)
Returns the decoding order for the first band (see SH_ORDERS enum)
Definition ambi_dec.c:866
void ambi_dec_setOutputConfigPreset(void *const hAmbi, int newPresetID)
Sets the output loudspeaker preset.
Definition ambi_dec.c:712
int ambi_dec_getProcessingDelay()
Returns the processing delay in samples; may be used for delay compensation features.
Definition ambi_dec.c:997
void ambi_dec_setDecNormType(void *const hAmbi, int index, int newID)
Sets the equalisation approach for one of the decoders.
Definition ambi_dec.c:816
int ambi_dec_getNumberOfBands(void)
Returns the number of frequency bands employed by ambi_dec.
Definition ambi_dec.c:886
float ambi_dec_getTransitionFreq(void *const hAmbi)
Returns the frequency (in Hz) at which to transition from the low frequency decoder to the high frequ...
Definition ambi_dec.c:978
void ambi_dec_setDecMethod(void *const hAmbi, int index, int newID)
Sets the decoding method for a specific decoder.
Definition ambi_dec.c:803
char * ambi_dec_getSofaFilePath(void *const hAmbi)
Returns the file path for a .sofa file (WITH file extension)
Definition ambi_dec.c:932
void ambi_dec_setLoudspeakerElev_deg(void *const hAmbi, int index, float newElev_deg)
Sets the elevation of a specific loudspeaker.
Definition ambi_dec.c:648
CODEC_STATUS ambi_dec_getCodecStatus(void *const hAmbi)
Returns current codec status (see CODEC_STATUS enum)
Definition ambi_dec.c:836
void ambi_dec_setUseDefaultHRIRsflag(void *const hAmbi, int newState)
Sets flag to dictate whether the default HRIRs in the Spatial_Audio_Framework should be used (1),...
Definition ambi_dec.c:682
void ambi_dec_setMasterDecOrder(void *const hAmbi, int newValue)
Sets the master decoding order.
Definition ambi_dec.c:607
int ambi_dec_getDecMethod(void *const hAmbi, int index)
Returns the currently selected decoding method (see AMBI_DEC_DECODING_METHODS enum)
Definition ambi_dec.c:960
void ambi_dec_setEnableHRIRsPreProc(void *const hAmbi, int newState)
Enable (1) or disable (0) the pre-processing applied to the HRTFs.
Definition ambi_dec.c:703
int ambi_dec_getChOrder(void *const hAmbi)
Returns the Ambisonic channel ordering convention currently being used to decode with,...
Definition ambi_dec.c:948
void ambi_dec_init(void *const hAmbi, int sampleRate)
Initialises an instance of ambi_dec with default settings.
Definition ambi_dec.c:171
void ambi_dec_setTransitionFreq(void *const hAmbi, float newValue)
Sets the frequeny at which to transition from the low frequency decoder to the high frequency decoder...
Definition ambi_dec.c:822
void ambi_dec_setLoudspeakerAzi_deg(void *const hAmbi, int index, float newAzi_deg)
Sets the azimuth of a specific loudspeaker.
Definition ambi_dec.c:634
void ambi_dec_setNumLoudspeakers(void *const hAmbi, int new_nLoudspeakers)
Sets the number of loudspeakers to decode to.
Definition ambi_dec.c:660
void ambi_dec_setNormType(void *const hAmbi, int newType)
Sets the Ambisonic normalisation convention to decode with, in order to match with the convention emp...
Definition ambi_dec.c:796
int ambi_dec_getMaxNumLoudspeakers()
Returns the maximum number of loudspeakers supported by ambi_dec.
Definition ambi_dec.c:909
int ambi_dec_getDecEnableMaxrE(void *const hAmbi, int index)
Returns the value of a flag used to dictate whether the max_rE weighting is being applied by a given ...
Definition ambi_dec.c:966
int ambi_dec_getBinauraliseLSflag(void *const hAmbi)
Returns the value of a flag used to dictate whether the loudspeaker signals should be binauralised (0...
Definition ambi_dec.c:920
void ambi_dec_destroy(void **const phAmbi)
Destroys an instance of the ambi_dec.
Definition ambi_dec.c:120
int ambi_dec_getDAWsamplerate(void *const hAmbi)
Returns the DAW/Host sample rate.
Definition ambi_dec.c:991
float ambi_dec_getLoudspeakerAzi_deg(void *const hAmbi, int index)
Returns the loudspeaker azimuth in degrees for a given index.
Definition ambi_dec.c:891
#define AMBI_DEC_TRANSITION_MIN_VALUE
Minimum transition value between low/high frequency decoders, in Hz.
Definition ambi_dec.h:99
#define AMBI_DEC_TRANSITION_MAX_VALUE
Maximum transition value between low/high frequency decoders, in Hz.
Definition ambi_dec.h:102
AMBI_DEC_DIFFUSE_FIELD_EQ_APPROACH
When using mixed order decoding (i.e.
Definition ambi_dec.h:92
@ AMPLITUDE_PRESERVING
preserve omni amplitude
Definition ambi_dec.h:93
@ ENERGY_PRESERVING
preserve omni energy
Definition ambi_dec.h:94
@ DECODING_METHOD_SAD
Sampling Ambisonic Decoder (SAD)
Definition ambi_dec.h:74
@ DECODING_METHOD_MMD
Mode-Matching Decoder (MMD)
Definition ambi_dec.h:75
@ DECODING_METHOD_EPAD
Energy-Preserving Ambisonic Decoder (EPAD)
Definition ambi_dec.h:76
@ DECODING_METHOD_ALLRAD
All-Round Ambisonic Decoder (AllRAD)
Definition ambi_dec.h:77
void ambi_dec_setCodecStatus(void *const hAmbi, CODEC_STATUS newStatus)
Sets codec status (see CODEC_STATUS enum)
void ambi_dec_interpHRTFs(void *const hAmbi, float azimuth_deg, float elevation_deg, float_complex h_intrp[HYBRID_BANDS][NUM_EARS])
Interpolates between the 3 nearest HRTFs using amplitude-preserving VBAP gains.
void loadLoudspeakerArrayPreset(LOUDSPEAKER_ARRAY_PRESETS preset, float dirs_deg[MAX_NUM_LOUDSPEAKERS][2], int *newNCH, int *nDims)
Returns the loudspeaker directions for a specified loudspeaker array preset.
A frequency-dependent Ambisonic decoder for reproducing Ambisonic sound scenes over loudspeakers.
#define MIN_NUM_LOUDSPEAKERS
To avoid triangulation errors when using AllRAD.
#define AMBI_DEC_FRAME_SIZE
Framesize, in time-domain samples.
#define MAX_NUM_LOUDSPEAKERS
Maximum permitted output channels.
#define NUM_DECODERS
One for low-frequencies and another for high-frequencies.
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 getLoudspeakerDecoderMtx(float *ls_dirs_deg, int nLS, LOUDSPEAKER_AMBI_DECODER_METHODS method, int order, int enableMaxReWeighting, float *decMtx)
Computes an ambisonic decoding matrix of a specific order, for a given loudspeaker layout.
Definition saf_hoa.c:327
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 getMaxREweights(int order, int diagMtxFlag, float *a_n)
Computes the weights required to manipulate a hyper-cardioid beam-pattern, such that it has maximum e...
Definition saf_hoa.c:236
@ 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
@ LOUDSPEAKER_DECODER_ALLRAD
All-Round Ambisonic Decoder (AllRAD): SAD decoding to a t-design, panned for the target loudspeaker d...
Definition saf_hoa.h:109
@ LOUDSPEAKER_DECODER_SAD
Sampling Ambisonic Decoder (SAD): transpose of the loudspeaker spherical harmonic matrix,...
Definition saf_hoa.h:76
@ LOUDSPEAKER_DECODER_EPAD
Energy-Preserving Ambisonic Decoder (EPAD) [1].
Definition saf_hoa.h:96
@ LOUDSPEAKER_DECODER_MMD
Mode-Matching Decoder (MMD): pseudo-inverse of the loudspeaker spherical harmonic matrix.
Definition saf_hoa.h:89
@ 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
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
#define ORDER2NSH(order)
Converts spherical harmonic order to number of spherical harmonic components i.e: (order+1)^2.
Definition saf_sh.h:51
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 getSHreal(int order, float *dirs_rad, int nDirs, float *Y)
Computes real-valued spherical harmonics [1] for each given direction on the unit sphere.
Definition saf_sh.c:191
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_CLAMP(a, min, max)
Ensures value "a" is clamped between the "min" and "max" values.
#define SAF_PI
pi constant (single precision)
#define SAF_MAX(a, b)
Returns the maximum of the two values.
#define NUM_EARS
2 (true for most humans)
void utility_svvcopy(const float *a, const int len, float *c)
Single-precision, vector-vector copy, i.e.
const float __Tdesign_degree_30_dirs_deg[480][2]
Directions [azimuth, Elevation] in degrees, for minimum Tdesign degree: 30.
#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.
const float __Eigenmike32_freqRange[6]
Sensor array frequency ranges for each SH order, for the Eigenmike32 (should only be used as a rough ...
#define saf_print_warning(message)
Macro to print a warning message along with the filename and line number.
const int __Eigenmike32_maxOrder
Max spherical harmonic order for the Eigenmike32.
const float __Zylia_freqRange[4]
Sensor array frequency ranges for each SH order, for the Zylia array (should only be used as a rough ...
const int __DTU_mic_maxOrder
Max spherical harmonic order for the custom 52-sensor array built at the Technical University of Denm...
const float __DTU_mic_freqRange[10]
Sensor array frequency ranges for each SH order, for the DTU mic (should only be used as a rough esti...
const int __Zylia_maxOrder
Max spherical harmonic order for the Zylia mic.
void generateVBAPgainTable3D(float *ls_dirs_deg, int L, int az_res_deg, int el_res_deg, int omitLargeTriangles, int enableDummies, float spread, float **gtable, int *N_gtable, int *nTriangles)
Generates a 3-D VBAP gain table based on specified loudspeaker directions, with optional spreading [2...
Definition saf_vbap.c:172
void compressVBAPgainTable3D(float *vbap_gtable, int nTable, int nDirs, float *vbap_gtableComp, int *vbap_gtableIdx)
Compresses a VBAP gain table to use less memory and CPU (by removing the elements which are just zero...
Definition saf_vbap.c:313
void ** 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 * 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
#define FLATTEN3D(A)
Use this macro when passing a 3-D dynamic multi-dimensional array to memset, memcpy or any other func...
Definition md_malloc.h:72
Contains variables for sofa file loading, HRTF interpolation, and the loudspeaker decoders.
float_complex hrtf_interp[MAX_NUM_LOUDSPEAKERS][HYBRID_BANDS][NUM_EARS]
interpolated HRTFs
char * sofa_filepath
absolute/relevative file path for a sofa file
float * M_dec_maxrE[NUM_DECODERS][MAX_SH_ORDER]
ambisonic decoding matrices with maxrE weighting ([0] for low-freq, [1] for high-freq); FLAT: nLoudsp...
float * M_dec[NUM_DECODERS][MAX_SH_ORDER]
ambisonic decoding matrices ([0] for low-freq, [1] for high-freq); FLAT: nLoudspeakers x nSH
int hrtf_nTriangles
number of triangle groups after triangulation
float * itds_s
interaural-time differences for each HRIR (in seconds); N_hrirs x 1
int * hrtf_vbap_gtableIdx
N_hrtf_vbap_gtable x 3.
int hrtf_vbapTableRes[2]
[azi elev] step sizes in degrees
int hrir_len
length of the HRIRs, this can be truncated, see "saf_sofa_reader.h"
float_complex * hrtf_fb
HRTF filterbank coefficients; nBands x nCH x N_hrirs.
int hrir_fs
sampling rate of the HRIRs, should ideally match the host sampling rate, although not required
float_complex * M_dec_cmplx_maxrE[NUM_DECODERS][MAX_SH_ORDER]
complex ambisonic decoding matrices with maxrE weighting ([0] for low-freq, [1] for high-freq); FLAT:...
float * hrtf_fb_mag
magnitudes of the HRTF filterbank coefficients; nBands x nCH x N_hrirs
int N_hrtf_vbap_gtable
number of interpolation directions
float_complex * M_dec_cmplx[NUM_DECODERS][MAX_SH_ORDER]
complex ambisonic decoding matrices ([0] for low-freq, [1] for high-freq); FLAT: nLoudspeakers x nSH
float * weights
grid integration weights of hrirs; N_hrirs x 1
int N_hrir_dirs
number of HRIR directions in the current sofa file
float * hrtf_vbap_gtableComp
N_hrtf_vbap_gtable x 3.
float * hrirs
time domain HRIRs; N_hrir_dirs x 2 x hrir_len
float M_norm[NUM_DECODERS][MAX_SH_ORDER][2]
norm coefficients to preserve omni energy/amplitude between different orders and decoders
float * hrir_dirs_deg
directions of the HRIRs in degrees [azi elev]; N_hrir_dirs x 2
Main structure for ambi_dec.
CODEC_STATUS codecStatus
see CODEC_STATUS
int new_nLoudpkrs
if new_nLoudpkrs != nLoudpkrs, afSTFT is reinitialised (current value will be replaced by this after ...
int new_masterOrder
if new_masterOrder != masterOrder, ambi_dec is reinitialised (current value will be replaced by this ...
CH_ORDER chOrdering
Ambisonic channel order convention (see CH_ORDER)
int loudpkrs_nDims
dimensionality of the current loudspeaker set-up
float ** SHFrameTD
Input spherical harmonic (SH) signals in the time-domain; MAX_NUM_SH_SIGNALS x AMBI_DEC_FRAME_SIZE.
float loudpkrs_dirs_deg[MAX_NUM_LOUDSPEAKERS][NUM_DECODERS]
loudspeaker directions in degrees [azi, elev]
float_complex *** binframeTF
Output binaural signals in the time-frequency domain; HYBRID_BANDS x NUM_EARS x TIME_SLOTS.
int useDefaultHRIRsFLAG
1: use default HRIRs in database, 0: use those from SOFA file
float transitionFreq
transition frequency for the 2 decoders, in Hz
void * hSTFT
afSTFT handle
int rE_WEIGHT[NUM_DECODERS]
0:disabled, 1: enable max_rE weight
AMBI_DEC_DIFFUSE_FIELD_EQ_APPROACH diffEQmode[NUM_DECODERS]
diffuse-field EQ approach; see AMBI_DEC_DIFFUSE_FIELD_EQ_APPROACH enum
float_complex *** SHframeTF
Input spherical harmonic (SH) signals in the time-frequency domain; HYBRID_BANDS x MAX_NUM_SH_SIGNALS...
int enableHRIRsPreProc
flag to apply pre-processing to the currently loaded HRTFs
float progressBar0_1
Current (re)initialisation progress, between [0..1].
int masterOrder
Current maximum/master decoding order.
NORM_TYPES norm
Ambisonic normalisation convention (see NORM_TYPES)
float ** outputFrameTD
Output loudspeaker or binaural signals in the time-domain; MAX_NUM_LOUDSPEAKERS x AMBI_DEC_FRAME_SIZE...
int fs
host sampling rate
int recalc_hrtf_interpFLAG[MAX_NUM_LOUDSPEAKERS]
0: no init required, 1: init required
int nLoudpkrs
number of loudspeakers/virtual loudspeakers
AMBI_DEC_DECODING_METHODS dec_method[NUM_DECODERS]
decoding methods for each decoder, see AMBI_DEC_DECODING_METHODS enum
PROC_STATUS procStatus
see PROC_STATUS
float freqVector[HYBRID_BANDS]
frequency vector for time-frequency transform, in Hz
char * progressBarText
Current (re)initialisation step, string.
int orderPerBand[HYBRID_BANDS]
Ambisonic decoding order per frequency band 1..SH_ORDER.
int binauraliseLS
1: convolve loudspeaker signals with HRTFs, 0: output loudspeaker signals
ambi_dec_codecPars * pars
codec parameters
float_complex *** outputframeTF
Output loudspeaker signals in the time-frequency domain; HYBRID_BANDS x MAX_NUM_LOUDSPEAKERS x TIME_S...
int new_binauraliseLS
if new_binauraliseLS != binauraliseLS, ambi_dec is reinitialised (current value will be replaced by t...
int reinit_hrtfsFLAG
0: no init required, 1: init required
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.