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
45
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)); /* must match ambi_dec_defaultLoudspeakerDirections */
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->firstInit = 1;
78 pData->hSTFT = NULL;
79 pData->SHFrameTD = (float**)malloc2d(MAX_NUM_SH_SIGNALS, AMBI_DEC_FRAME_SIZE, sizeof(float));
81 pData->SHframeTF = (float_complex***)malloc3d(HYBRID_BANDS, MAX_NUM_SH_SIGNALS, TIME_SLOTS, sizeof(float_complex));
82 pData->outputframeTF = (float_complex***)malloc3d(HYBRID_BANDS, MAX_NUM_LOUDSPEAKERS, TIME_SLOTS, sizeof(float_complex));
83 pData->binframeTF = (float_complex***)malloc3d(HYBRID_BANDS, NUM_EARS, TIME_SLOTS, sizeof(float_complex));
84
85 /* codec data */
86 pData->progressBar0_1 = 0.0f;
88 strcpy(pData->progressBarText,"");
91 ambi_dec_codecPars* pars = pData->pars;
92 for (i=0; i<NUM_DECODERS; i++){
93 for(j=0; j<MAX_SH_ORDER; j++){
94 pars->M_dec[i][j] = NULL;
95 pars->M_dec_cmplx[i][j] = NULL;
96 pars->M_dec_maxrE[i][j] = NULL;
97 pars->M_dec_cmplx_maxrE[i][j] = NULL;
98 }
99 }
100 pars->sofa_filepath = NULL;
101 pars->hrirs = NULL;
103 pars->hrir_dirs_deg = NULL;
104 pars->hrtf_vbap_gtableIdx = NULL;
105 pars->hrtf_vbap_gtableComp = NULL;
106 pars->itds_s = NULL;
107 pars->hrtf_fb = NULL;
108 pars->hrtf_fb_mag = NULL;
109 pars->weights = NULL;
110
111 /* internal parameters */
112 pData->binauraliseLS = pData->new_binauraliseLS = 0;
113
114 /* flags */
116 pData->reinit_hrtfsFLAG = 1;
117 for(ch=0; ch<MAX_NUM_LOUDSPEAKERS; ch++)
118 pData->recalc_hrtf_interpFLAG[ch] = 1;
119}
120
122(
123 void ** const phAmbi
124)
125{
126 ambi_dec_data *pData = (ambi_dec_data*)(*phAmbi);
127 ambi_dec_codecPars *pars;
128 int i, j;
129
130 if (pData != NULL) {
131 /* not safe to free memory during intialisation/processing loop */
132 while (pData->codecStatus == CODEC_STATUS_INITIALISING ||
134 SAF_SLEEP(10);
135 }
136
137 /* free afSTFT and buffers */
138 if(pData->hSTFT!=NULL)
139 afSTFT_destroy(&(pData->hSTFT));
140 free(pData->SHFrameTD);
141 free(pData->outputFrameTD);
142 free(pData->SHframeTF);
143 free(pData->outputframeTF);
144 free(pData->binframeTF);
145
146 /* free codec data */
147 pars = pData->pars;
148 free(pars->hrtf_vbap_gtableComp);
149 free(pars->hrtf_vbap_gtableIdx);
150 free(pars->hrtf_fb);
151 free(pars->hrtf_fb_mag);
152 free(pars->itds_s);
153 free(pars->sofa_filepath);
154 free(pars->hrirs);
155 free(pars->hrir_dirs_deg);
156 free(pars->weights);
157 for (i=0; i<NUM_DECODERS; i++){
158 for(j=0; j<MAX_SH_ORDER; j++){
159 free(pars->M_dec[i][j]);
160 free(pars->M_dec_cmplx[i][j]);
161 free(pars->M_dec_maxrE[i][j]);
162 free(pars->M_dec_cmplx_maxrE[i][j]);
163 }
164 }
165 free(pData->progressBarText);
166 free(pData);
167 pData = NULL;
168 *phAmbi = NULL;
169 }
170}
171
173(
174 void * const hAmbi,
175 int sampleRate
176)
177{
178 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
179
180 /* define frequency vector */
181 if(pData->fs != sampleRate || pData->firstInit){
182 pData->fs = sampleRate;
183 pData->reinit_hrtfsFLAG = 1;
185 pData->firstInit = 0;
186 }
187 afSTFT_getCentreFreqs(pData->hSTFT, (float)pData->fs, HYBRID_BANDS, pData->freqVector);
188}
189
191(
192 void* const hAmbi
193)
194{
195 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
196 ambi_dec_codecPars* pars = pData->pars;
197 int i, ch, d, j, n, ng, nGrid_dirs, masterOrder, nSH_order, max_nSH, nLoudspeakers;
198 float* grid_dirs_deg, *Y, *M_dec_tmp, *g, *a, *e, *a_n, *hrtf_vbap_gtable;;
199 float a_avg[MAX_SH_ORDER], e_avg[MAX_SH_ORDER], azi_incl[2], sum_elev;
200 float loudpkrs_dirs_deg_local[MAX_NUM_LOUDSPEAKERS][2];
201#ifdef SAF_ENABLE_SOFA_READER_MODULE
204#endif
205
207 return; /* re-init not required, or already happening */
208 while (pData->procStatus == PROC_STATUS_ONGOING){
209 /* re-init required, but we need to wait for the current processing loop to end */
210 pData->codecStatus = CODEC_STATUS_INITIALISING; /* indicate that we want to init */
211 SAF_SLEEP(10);
212 }
213
214 /* for progress bar */
216 strcpy(pData->progressBarText,"Initialising");
217 pData->progressBar0_1 = 0.0f;
218
219 /* reinit afSTFT */
220 masterOrder = pData->new_masterOrder;
221 max_nSH = (masterOrder+1)*(masterOrder+1);
222 nLoudspeakers = pData->new_nLoudpkrs;
223 if(pData->hSTFT==NULL){
224 if(pData->new_binauraliseLS)
225 afSTFT_create(&(pData->hSTFT), max_nSH, NUM_EARS, HOP_SIZE, 0, 1, AFSTFT_BANDS_CH_TIME);
226 else
227 afSTFT_create(&(pData->hSTFT), max_nSH, nLoudspeakers, HOP_SIZE, 0, 1, AFSTFT_BANDS_CH_TIME);
229 }
230 else{
231 if(pData->new_binauraliseLS)
232 afSTFT_channelChange(pData->hSTFT, max_nSH, NUM_EARS);
233 else
234 afSTFT_channelChange(pData->hSTFT, max_nSH, nLoudspeakers);
236 }
237 afSTFT_getCentreFreqs(pData->hSTFT, (float)pData->fs, HYBRID_BANDS, pData->freqVector);
238 pData->binauraliseLS = pData->new_binauraliseLS;
239 pData->nLoudpkrs = nLoudspeakers;
240
241 /* Grab local copy */
242 for(ch=0; ch < nLoudspeakers; ch++){
243 loudpkrs_dirs_deg_local[ch][0] = pData->loudpkrs_dirs_deg[ch][0];
244 loudpkrs_dirs_deg_local[ch][1] = pData->loudpkrs_dirs_deg[ch][1];
245 }
246
247 /* Quick and dirty check to find loudspeaker dimensionality */
248 strcpy(pData->progressBarText,"Computing decoder");
249 pData->progressBar0_1 = 0.2f;
250 sum_elev = 0.0f;
251 for(ch=0; ch < nLoudspeakers; ch++)
252 sum_elev += fabsf(loudpkrs_dirs_deg_local[ch][1]);
253 if( (((sum_elev < 5.0f) && (sum_elev > -5.0f))) || (nLoudspeakers < 4) )
254 pData->loudpkrs_nDims = 2;
255 else
256 pData->loudpkrs_nDims = 3;
257
258 /* add virtual loudspeakers for 2D case if using AllRAD, so that the triangulation cannot fail. */
259 if (pData->loudpkrs_nDims == 2 && (pData->dec_method[0]==DECODING_METHOD_ALLRAD || pData->dec_method[1]==DECODING_METHOD_ALLRAD)){
260 assert(nLoudspeakers<=MAX_NUM_LOUDSPEAKERS-2);
261 loudpkrs_dirs_deg_local[nLoudspeakers][0] = 0.0f;
262 loudpkrs_dirs_deg_local[nLoudspeakers][1] = -90.0f;
263 loudpkrs_dirs_deg_local[nLoudspeakers+1][0] = 0.0f;
264 loudpkrs_dirs_deg_local[nLoudspeakers+1][1] = 90.0f;
265 nLoudspeakers += 2;
266 }
267
268 /* prep */
269 nGrid_dirs = 480; /* Minimum t-design of degree 30, has 480 points */
270 g = malloc1d(nLoudspeakers*sizeof(float));
271 a = malloc1d(nGrid_dirs*sizeof(float));
272 e = malloc1d(nGrid_dirs*sizeof(float));
273
274 /* calculate loudspeaker decoding matrices */
275 for( d=0; d<NUM_DECODERS; d++){
276 M_dec_tmp = malloc1d(nLoudspeakers * max_nSH * sizeof(float));
277 AMBI_DEC_DECODING_METHODS dec_method = pData->dec_method[d];
278 switch(dec_method){
280 getLoudspeakerDecoderMtx((float*)loudpkrs_dirs_deg_local, nLoudspeakers, LOUDSPEAKER_DECODER_SAD, masterOrder, 0, M_dec_tmp);
281 break;
283 getLoudspeakerDecoderMtx((float*)loudpkrs_dirs_deg_local, nLoudspeakers, LOUDSPEAKER_DECODER_MMD, masterOrder, 0, M_dec_tmp);
284 break;
286 getLoudspeakerDecoderMtx((float*)loudpkrs_dirs_deg_local, nLoudspeakers, LOUDSPEAKER_DECODER_EPAD, masterOrder, 0, M_dec_tmp);
287 break;
289 getLoudspeakerDecoderMtx((float*)loudpkrs_dirs_deg_local, nLoudspeakers, LOUDSPEAKER_DECODER_ALLRAD, masterOrder, 0, M_dec_tmp);
290 break;
291 }
292
293 /* diffuse-field EQ for orders 1..masterOrder */
294 for( n=1; n<=masterOrder; n++){
295 /* truncate M_dec for each order */
296 nSH_order = (n+1)*(n+1);
297 free(pars->M_dec[d][n-1]);
298 pars->M_dec[d][n-1] = malloc1d(nLoudspeakers* nSH_order * sizeof(float));
299 free(pars->M_dec_cmplx[d][n-1]);
300 pars->M_dec_cmplx[d][n-1] = malloc1d(nLoudspeakers * nSH_order * sizeof(float_complex));
301 for(i=0; i<nLoudspeakers; i++){
302 for(j=0; j<nSH_order; j++){
303 pars->M_dec[d][n-1][i*nSH_order+j] = M_dec_tmp[i*max_nSH +j]; /* for applying in the time domain, and... */
304 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 */
305 }
306 }
307
308 /* create dedicated maxrE weighted versions */
309 a_n = malloc1d(nSH_order*nSH_order*sizeof(float));
310 getMaxREweights(n, 1, a_n); /* weights returned as diagonal matrix */
311 free(pars->M_dec_maxrE[d][n-1]);
312 pars->M_dec_maxrE[d][n-1] = malloc1d(nLoudspeakers * nSH_order * sizeof(float));
313 free(pars->M_dec_cmplx_maxrE[d][n-1]);
314 pars->M_dec_cmplx_maxrE[d][n-1] = malloc1d(nLoudspeakers * nSH_order * sizeof(float_complex));
315 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nLoudspeakers, nSH_order, nSH_order, 1.0f,
316 pars->M_dec[d][n-1], nSH_order,
317 a_n, nSH_order, 0.0f,
318 pars->M_dec_maxrE[d][n-1], nSH_order); /* for applying in the time domain */
319 for(i=0; i<nLoudspeakers * nSH_order; i++)
320 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 */
321
322 /* fire a plane-wave from each grid direction to find the total energy/amplitude (using non-maxrE weighted versions) */
323 Y = malloc1d(nSH_order*sizeof(float));
324 grid_dirs_deg = (float*)(&__Tdesign_degree_30_dirs_deg[0][0]);
325 for(ng=0; ng<nGrid_dirs; ng++){
326 azi_incl[0] = grid_dirs_deg[ng*2]*SAF_PI/180.0f;
327 azi_incl[1] = SAF_PI/2.0f-grid_dirs_deg[ng*2+1]*SAF_PI/180.0f;
328 getSHreal(n, (float*)azi_incl, 1, Y);
329 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasTrans, nLoudspeakers, 1, nSH_order, 1.0f,
330 pars->M_dec[d][n-1], nSH_order,
331 Y, nSH_order, 0.0f,
332 g, 1);
333 a[ng] = e[ng] = 0.0f;
334 for(i=0; i<nLoudspeakers; i++){
335 a[ng] += g[i];
336 e[ng] += powf(g[i], 2.0f);
337 }
338 }
339
340 /* determine the order+decoder dependent normalisation factor for energy+amplitude preserving decoding */
341 a_avg[n-1] = e_avg[n-1] = 0.0f;
342 for(ng=0; ng<nGrid_dirs; ng++){
343 a_avg[n-1] += a[ng];
344 e_avg[n-1] += e[ng];
345 }
346 a_avg[n-1] /= (float)nGrid_dirs;
347 e_avg[n-1] /= (float)nGrid_dirs;
348 pars->M_norm[d][n-1][0] = 1.0f/(a_avg[n-1]+2.23e-6f); /* use this to preserve omni amplitude */
349 pars->M_norm[d][n-1][1] = sqrtf(1.0f/(e_avg[n-1]+2.23e-6f)); /* use this to preserve omni energy */
350 free(a_n);
351 free(Y);
352
353 /* remove virtual loudspeakers from the decoder (if needed) */
354 if (pData->loudpkrs_nDims == 2 && (pData->dec_method[0]==DECODING_METHOD_ALLRAD || pData->dec_method[1]==DECODING_METHOD_ALLRAD)){
355 pars->M_dec[d][n-1] = realloc1d(pars->M_dec[d][n-1], pData->nLoudpkrs * nSH_order * sizeof(float));
356 pars->M_dec_cmplx[d][n-1] = realloc1d(pars->M_dec_cmplx[d][n-1], pData->nLoudpkrs * nSH_order * sizeof(float_complex));
357 pars->M_dec_maxrE[d][n-1] = realloc1d(pars->M_dec_maxrE[d][n-1], pData->nLoudpkrs * nSH_order * sizeof(float));
358 pars->M_dec_cmplx_maxrE[d][n-1] = realloc1d(pars->M_dec_cmplx_maxrE[d][n-1], pData->nLoudpkrs * nSH_order * sizeof(float_complex));
359 }
360 }
361 free(M_dec_tmp);
362 }
363
364 /* update order */
365 pData->masterOrder = pData->new_masterOrder;
366
367 /* Binaural-related initialisations */
368 if(pData->reinit_hrtfsFLAG){
369 strcpy(pData->progressBarText,"Computing VBAP gain table");
370 pData->progressBar0_1 = 0.4f;
371
372 /* load sofa file or load default hrir data */
373#ifdef SAF_ENABLE_SOFA_READER_MODULE
374 if(!pData->useDefaultHRIRsFLAG && pars->sofa_filepath!=NULL){
375 /* Load SOFA file */
377
378 /* Load defaults instead */
379 if(error!=SAF_SOFA_OK || sofa.nReceivers!=NUM_EARS){
380 pData->useDefaultHRIRsFLAG = 1;
381 saf_print_warning("Unable to load the specified SOFA file, or it contained something other than 2 channels. Using default HRIR data instead.");
382 }
383 else{
384 /* Copy SOFA data */
385 pars->hrir_fs = (int)sofa.DataSamplingRate;
386 pars->hrir_len = sofa.DataLengthIR;
387 pars->N_hrir_dirs = sofa.nSources;
388 pars->hrirs = realloc1d(pars->hrirs, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
389 memcpy(pars->hrirs, sofa.DataIR, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
390 pars->hrir_dirs_deg = realloc1d(pars->hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
391 cblas_scopy(pars->N_hrir_dirs, sofa.SourcePosition, 3, pars->hrir_dirs_deg, 2); /* azi */
392 cblas_scopy(pars->N_hrir_dirs, &sofa.SourcePosition[1], 3, &pars->hrir_dirs_deg[1], 2); /* elev */
393 }
394
395 /* Clean-up */
396 saf_sofa_close(&sofa);
397 }
398#else
399 pData->useDefaultHRIRsFLAG = 1; /* Can only load the default HRIR data */
400#endif
401 if(pData->useDefaultHRIRsFLAG){
402 /* Copy default HRIR data */
406 pars->hrirs = realloc1d(pars->hrirs, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
407 memcpy(pars->hrirs, (float*)__default_hrirs, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
408 pars->hrir_dirs_deg = realloc1d(pars->hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
409 memcpy(pars->hrir_dirs_deg, (float*)__default_hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
410 }
411
412 /* Resample HRIRs if needed */
413 pars->hrir_orig_fs = pars->hrir_fs;
414 if(pars->hrir_fs!=pData->fs){
415 strcpy(pData->progressBarText, "Resampling HRIRs");
416 pData->progressBar0_1 = 0.6f;
417 float* hrirs_resampled;
418 int hrir_length_resample;
419 resampleHRIRs(pars->hrirs, pars->N_hrir_dirs, pars->hrir_len, pars->hrir_fs, pData->fs, 1, &hrirs_resampled, &hrir_length_resample);
420
421 /* Replace with resampled HRIRs */
422 pars->hrir_fs = pData->fs;
423 pars->hrir_len = hrir_length_resample;
424 pars->hrirs = realloc1d(pars->hrirs, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
425 memcpy(pars->hrirs, hrirs_resampled, pars->N_hrir_dirs*NUM_EARS*(pars->hrir_len)*sizeof(float));
426
427 /* Clean-up */
428 free(hrirs_resampled);
429 }
430
431 /* estimate the ITDs for each HRIR */
432 pars->itds_s = realloc1d(pars->itds_s, pars->N_hrir_dirs*sizeof(float));
433 estimateITDs(pars->hrirs, pars->N_hrir_dirs, pars->hrir_len, pars->hrir_fs, pars->itds_s);
434
435 /* generate VBAP gain table for the hrir_dirs */
436 hrtf_vbap_gtable = NULL;
437 pars->hrtf_vbapTableRes[0] = 2; /* azimuth resolution in degrees */
438 pars->hrtf_vbapTableRes[1] = 5; /* elevation resolution in degrees */
439 generateVBAPgainTable3D(pars->hrir_dirs_deg, pars->N_hrir_dirs, pars->hrtf_vbapTableRes[0], pars->hrtf_vbapTableRes[1], 1, 0, 0.0f,
440 &hrtf_vbap_gtable, &(pars->N_hrtf_vbap_gtable), &(pars->hrtf_nTriangles));
441 if(hrtf_vbap_gtable==NULL){
442 /* if generating vbap gain tabled failed, re-calculate with default HRIR set (which is known to triangulate correctly) */
443 pData->useDefaultHRIRsFLAG = 1;
444 ambi_dec_initCodec(hAmbi);
445 }
446
447 /* compress VBAP table (i.e. remove the zero elements) */
448 pars->hrtf_vbap_gtableComp = realloc1d(pars->hrtf_vbap_gtableComp, pars->N_hrtf_vbap_gtable * 3 * sizeof(float));
449 pars->hrtf_vbap_gtableIdx = realloc1d(pars->hrtf_vbap_gtableIdx, pars->N_hrtf_vbap_gtable * 3 * sizeof(int));
451
452 /* convert hrirs to filterbank coefficients */
453 strcpy(pData->progressBarText,"Preparing HRIRs");
454 pData->progressBar0_1 = 0.85f;
455 pars->hrtf_fb = realloc1d(pars->hrtf_fb, HYBRID_BANDS * NUM_EARS * (pars->N_hrir_dirs)*sizeof(float_complex));
456 HRIRs2HRTFs_afSTFT(pars->hrirs, pars->N_hrir_dirs, pars->hrir_len, HOP_SIZE, 0, 1, pars->hrtf_fb);
457 /* HRIR pre-processing */
458 if(pData->enableHRIRsPreProc){
459 /* get integration weights */
460 strcpy(pData->progressBarText,"Applying HRIR Pre-Processing");
461 pData->progressBar0_1 = 0.95f;
462 if(pars->N_hrir_dirs<=3600){
463 pars->weights = realloc1d(pars->weights, pars->N_hrir_dirs*sizeof(float));
464 //getVoronoiWeights(pars->hrir_dirs_deg, pars->N_hrir_dirs, 0, pars->weights);
465 float * hrir_dirs_rad = (float*) malloc1d(pars->N_hrir_dirs*2*sizeof(float));
466 memcpy(hrir_dirs_rad, pars->hrir_dirs_deg, pars->N_hrir_dirs*2*sizeof(float));
467 cblas_sscal(pars->N_hrir_dirs*2, SAF_PI/180.f, hrir_dirs_rad, 1);
468 sphElev2incl(hrir_dirs_rad, pars->N_hrir_dirs, 0, hrir_dirs_rad);
469 int supOrder = calculateGridWeights(hrir_dirs_rad, pars->N_hrir_dirs, -1, pars->weights);
470 if(supOrder < 1){
471 saf_print_warning("Could not calculate grid weights");
472 free(pars->weights);
473 pars->weights = NULL;
474 }
475 }
476 else{
477 saf_print_warning("Too many grid points");
478 free(pars->weights);
479 pars->weights = NULL;
480 }
481 diffuseFieldEqualiseHRTFs(pars->N_hrir_dirs, pars->itds_s, pData->freqVector, HYBRID_BANDS, pars->weights, 1, 0, pars->hrtf_fb);
482 }
483
484 /* calculate magnitude responses */
485 pars->hrtf_fb_mag = realloc1d(pars->hrtf_fb_mag, HYBRID_BANDS*NUM_EARS*(pars->N_hrir_dirs)*sizeof(float));
486 for(i=0; i<HYBRID_BANDS*NUM_EARS* (pars->N_hrir_dirs); i++)
487 pars->hrtf_fb_mag[i] = cabsf(pars->hrtf_fb[i]);
488
489 /* clean-up */
490 free(hrtf_vbap_gtable);
491 pData->reinit_hrtfsFLAG = 0;
492 }
493
494 /* HRTFs should be reinterpolated */
495 for(ch=0; ch<MAX_NUM_LOUDSPEAKERS; ch++)
496 pData->recalc_hrtf_interpFLAG[ch] = 1;
497
498 /* done! */
499 strcpy(pData->progressBarText,"Done!");
500 pData->progressBar0_1 = 1.0f;
502
503 free(g);
504 free(a);
505 free(e);
506}
507
509(
510 void * const hAmbi,
511 const float *const * inputs,
512 float* const* const outputs,
513 int nInputs,
514 int nOutputs,
515 int nSamples
516)
517{
518 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
519 ambi_dec_codecPars* pars = pData->pars;
520 int ch, ear, i, band, orderBand, nSH_band, decIdx, nSH;
521 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
522
523 /* local copies of user parameters */
524 int nLoudspeakers, binauraliseLS, masterOrder;
525 int orderPerBand[HYBRID_BANDS], rE_WEIGHT[NUM_DECODERS];
526 float transitionFreq;
528 NORM_TYPES norm;
529 CH_ORDER chOrdering;
530 masterOrder = pData->masterOrder;
531 nSH = ORDER2NSH(masterOrder);
532 nLoudspeakers = pData->nLoudpkrs;
533 memcpy(orderPerBand, pData->orderPerBand, HYBRID_BANDS*sizeof(int));
534 transitionFreq = pData->transitionFreq;
535 memcpy(diffEQmode, pData->diffEQmode, NUM_DECODERS*sizeof(int));
536 binauraliseLS = pData->binauraliseLS;
537 norm = pData->norm;
538 chOrdering = pData->chOrdering;
539 memcpy(rE_WEIGHT, pData->rE_WEIGHT, NUM_DECODERS*sizeof(int));
540
541 /* Process frame */
542 if (nSamples == AMBI_DEC_FRAME_SIZE && (pData->codecStatus == CODEC_STATUS_INITIALISED) ) {
544
545 /* Load time-domain data */
546 for(i=0; i < SAF_MIN(nSH, nInputs); i++)
547 utility_svvcopy(inputs[i], AMBI_DEC_FRAME_SIZE, pData->SHFrameTD[i]);
548 for(; i<nSH; i++)
549 memset(pData->SHFrameTD[i], 0, AMBI_DEC_FRAME_SIZE * sizeof(float)); /* fill remaining channels with zeros */
550
551 /* account for channel order convention */
552 switch(chOrdering){
553 case CH_ACN: /* already ACN, do nothing */ break; /* Otherwise, convert to ACN... */
555 }
556
557 /* account for input normalisation scheme */
558 switch(norm){
559 case NORM_N3D: /* already in N3D, do nothing */ break; /* Otherwise, convert to N3D... */
562 }
563
564 /* Apply time-frequency transform (TFT) */
566
567 /* Decode to loudspeaker set-up */
568 memset(FLATTEN3D(pData->outputframeTF), 0, HYBRID_BANDS*MAX_NUM_LOUDSPEAKERS*TIME_SLOTS*sizeof(float_complex));
569 for(band=0; band<HYBRID_BANDS; band++){
570 orderBand = SAF_MAX(SAF_MIN(orderPerBand[band], masterOrder),1);
571 nSH_band = (orderBand+1)*(orderBand+1);
572
573 /* There is a different decoder for low (0) and high (1) frequencies, and for max_rE weights enabled/disabled */
574 decIdx = pData->freqVector[band] < transitionFreq ? 0 : 1;
575 if(rE_WEIGHT[decIdx]){
576 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nLoudspeakers, TIME_SLOTS, nSH_band, &calpha,
577 pars->M_dec_cmplx_maxrE[decIdx][orderBand-1], nSH_band,
578 FLATTEN2D(pData->SHframeTF[band]), TIME_SLOTS, &cbeta,
579 FLATTEN2D(pData->outputframeTF[band]), TIME_SLOTS);
580 }
581 else{
582 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nLoudspeakers, TIME_SLOTS, nSH_band, &calpha,
583 pars->M_dec_cmplx[decIdx][orderBand-1], nSH_band,
584 FLATTEN2D(pData->SHframeTF[band]), TIME_SLOTS, &cbeta,
585 FLATTEN2D(pData->outputframeTF[band]), TIME_SLOTS);
586 }
587
588 /* Apply scaling to preserve either the amplitude or energy when the decododing orders are different over frequency */
589 cblas_sscal(/*re+im*/2*nLoudspeakers*TIME_SLOTS, pars->M_norm[decIdx][orderBand-1][diffEQmode[decIdx]==AMPLITUDE_PRESERVING ? 0 : 1],
590 (float*)FLATTEN2D(pData->outputframeTF[band]), 1);
591 }
592
593 /* Binauralise the loudspeaker signals */
594 if(binauraliseLS){
595 /* Initialise the binaural buffer with zeros */
596 memset(FLATTEN3D(pData->binframeTF), 0, HYBRID_BANDS*NUM_EARS*TIME_SLOTS * sizeof(float_complex));
597
598 /* Convolve each loudspeaker signals with the respective HRTFs */
599 for (ch = 0; ch < nLoudspeakers; ch++) {
600 if(pData->recalc_hrtf_interpFLAG[ch]){
601 /* Re-compute the interpolated HRTF (only if loudspeaker direction changed) */
602 ambi_dec_interpHRTFs(hAmbi, pData->loudpkrs_dirs_deg[ch][0], pData->loudpkrs_dirs_deg[ch][1], pars->hrtf_interp[ch]);
603 pData->recalc_hrtf_interpFLAG[ch] = 0;
604 }
605
606 /* Convolve this loudspeaker channel with the interpolated HRTF, and add it to the binaural buffer */
607 for (band = 0; band < HYBRID_BANDS; band++)
608 for (ear = 0; ear < NUM_EARS; ear++)
609 cblas_caxpy(TIME_SLOTS, &pars->hrtf_interp[ch][band][ear], pData->outputframeTF[band][ch], 1, pData->binframeTF[band][ear], 1);
610 }
611
612 /* Scale by sqrt(number of loudspeakers) */
613 cblas_sscal(/*re+im*/2*HYBRID_BANDS*NUM_EARS*TIME_SLOTS, 1.0f/sqrtf((float)nLoudspeakers), (float*)FLATTEN3D(pData->binframeTF), 1);
614 }
615
616 /* inverse-TFT */
617 afSTFT_backward_knownDimensions(pData->hSTFT, binauraliseLS ? pData->binframeTF : pData->outputframeTF,
619
620 /* Copy to output buffer */
621 for(ch = 0; ch < SAF_MIN(binauraliseLS==1 ? NUM_EARS : nLoudspeakers, nOutputs); ch++)
622 utility_svvcopy(pData->outputFrameTD[ch], AMBI_DEC_FRAME_SIZE, outputs[ch]);
623 for (; ch < nOutputs; ch++)
624 memset(outputs[ch], 0, AMBI_DEC_FRAME_SIZE*sizeof(float));
625 }
626 else
627 for (ch=0; ch < nOutputs; ch++)
628 memset(outputs[ch], 0, AMBI_DEC_FRAME_SIZE*sizeof(float));
629
631}
632
633
634/* Set Functions */
635
636void ambi_dec_refreshSettings(void* const hAmbi)
637{
638 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
639 pData->reinit_hrtfsFLAG = 1;
641}
642
643void ambi_dec_setMasterDecOrder(void * const hAmbi, int newValue)
644{
645 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
646 pData->new_masterOrder = SAF_MIN(SAF_MAX(newValue,1), MAX_SH_ORDER);
648 /* FUMA only supports 1st order */
649 if(pData->new_masterOrder!=SH_ORDER_FIRST && pData->chOrdering == CH_FUMA)
650 pData->chOrdering = CH_ACN;
651 if(pData->new_masterOrder!=SH_ORDER_FIRST && pData->norm == NORM_FUMA)
652 pData->norm = NORM_SN3D;
653}
654
655void ambi_dec_setDecOrder(void * const hAmbi, int newValue, int bandIdx)
656{
657 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
658 pData->orderPerBand[bandIdx] = SAF_MIN(SAF_MAX(newValue,1), pData->new_masterOrder);
659}
660
661void ambi_dec_setDecOrderAllBands(void * const hAmbi, int newValue)
662{
663 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
664 int band;
665
666 for(band=0; band<HYBRID_BANDS; band++)
667 pData->orderPerBand[band] = SAF_MIN(SAF_MAX(newValue,1), pData->new_masterOrder);
668}
669
670void ambi_dec_setLoudspeakerAzi_deg(void* const hAmbi, int index, float newAzi_deg)
671{
672 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
673 if(newAzi_deg>180.0f)
674 newAzi_deg = -360.0f + newAzi_deg;
675 newAzi_deg = SAF_MAX(newAzi_deg, -180.0f);
676 newAzi_deg = SAF_MIN(newAzi_deg, 180.0f);
677 if(pData->loudpkrs_dirs_deg[index][0] != newAzi_deg){
678 pData->loudpkrs_dirs_deg[index][0] = newAzi_deg;
679 pData->recalc_hrtf_interpFLAG[index] = 1;
681 }
682}
683
684void ambi_dec_setLoudspeakerElev_deg(void* const hAmbi, int index, float newElev_deg)
685{
686 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
687 newElev_deg = SAF_MAX(newElev_deg, -90.0f);
688 newElev_deg = SAF_MIN(newElev_deg, 90.0f);
689 if(pData->loudpkrs_dirs_deg[index][1] != newElev_deg){
690 pData->loudpkrs_dirs_deg[index][1] = newElev_deg;
691 pData->recalc_hrtf_interpFLAG[index] = 1;
693 }
694}
695
696void ambi_dec_setNumLoudspeakers(void* const hAmbi, int new_nLoudspeakers)
697{
698 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
699 int ch;
700 pData->new_nLoudpkrs = new_nLoudspeakers > MAX_NUM_LOUDSPEAKERS ? MAX_NUM_LOUDSPEAKERS : new_nLoudspeakers;
702 if(pData->nLoudpkrs != pData->new_nLoudpkrs){
703 for(ch=0; ch<MAX_NUM_LOUDSPEAKERS; ch++)
704 pData->recalc_hrtf_interpFLAG[ch] = 1;
706 }
707}
708
709void ambi_dec_setBinauraliseLSflag(void* const hAmbi, int newState)
710{
711 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
712
713 pData->new_binauraliseLS = newState;
714 if(pData->new_binauraliseLS != pData->binauraliseLS)
716}
717
718void ambi_dec_setUseDefaultHRIRsflag(void* const hAmbi, int newState)
719{
720 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
721
722 if((!pData->useDefaultHRIRsFLAG) && (newState)){
723 pData->useDefaultHRIRsFLAG = newState;
724 ambi_dec_refreshSettings(hAmbi); // re-init and re-calc
725 }
726}
727
728void ambi_dec_setSofaFilePath(void* const hAmbi, const char* path)
729{
730 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
731 ambi_dec_codecPars* pars = pData->pars;
732
733 pars->sofa_filepath = realloc1d(pars->sofa_filepath, strlen(path) + 1);
734 strcpy(pars->sofa_filepath, path);
735 pData->useDefaultHRIRsFLAG = 0;
736 ambi_dec_refreshSettings(hAmbi); // re-init and re-calc
737}
738
739void ambi_dec_setEnableHRIRsPreProc(void* const hAmbi, int newState)
740{
741 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
742 if(newState!=pData->enableHRIRsPreProc){
743 pData->enableHRIRsPreProc = newState;
744 ambi_dec_refreshSettings(hAmbi); // re-init and re-calc
745 }
746}
747
748void ambi_dec_setOutputConfigPreset(void* const hAmbi, int newPresetID)
749{
750 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
751 int ch;
752
753 loadLoudspeakerArrayPreset(newPresetID, pData->loudpkrs_dirs_deg, &(pData->new_nLoudpkrs), &(pData->loudpkrs_nDims));
754 for(ch=0; ch<MAX_NUM_LOUDSPEAKERS; ch++)
755 pData->recalc_hrtf_interpFLAG[ch] = 1;
757}
758
759void ambi_dec_setSourcePreset(void* const hAmbi, int newPresetID)
760{
761 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
762 int band, rangeIdx, curOrder, reverse;
763
764 rangeIdx = 0;
765 curOrder = 1;
766 reverse = 0;
767 switch(newPresetID){
768 /* Ideal spherical harmonics will have SH_ORDER at all frequencies */
769 case MIC_PRESET_IDEAL:
770 for(band=0; band<HYBRID_BANDS; band++)
771 pData->orderPerBand[band] = pData->masterOrder;
772 break;
773
774 /* For real microphone arrays, the maximum usable spherical harmonic order will depend on frequency */
775 case MIC_PRESET_ZYLIA:
776 for(band=0; band<HYBRID_BANDS; band++){
777 if(rangeIdx<2*(__Zylia_maxOrder-1)){
778 if(pData->freqVector[band]>__Zylia_freqRange[rangeIdx]){
779 if(!reverse)
780 curOrder++;
781 else
782 curOrder--;
783 reverse = (curOrder == __Zylia_maxOrder) || (reverse) ? 1 : 0;
784 rangeIdx++;
785 }
786 }
787 pData->orderPerBand[band] = SAF_MIN(pData->masterOrder,curOrder);
788 }
789 break;
790
791 case MIC_PRESET_EIGENMIKE32:
792 for(band=0; band<HYBRID_BANDS; band++){
793 if(rangeIdx<2*(__Eigenmike32_maxOrder-1)){
794 if(pData->freqVector[band]>__Eigenmike32_freqRange[rangeIdx]){
795 if(!reverse)
796 curOrder++;
797 else
798 curOrder--;
799 reverse = (curOrder == __Eigenmike32_maxOrder) || (reverse) ? 1 : 0;
800 rangeIdx++;
801 }
802 }
803 pData->orderPerBand[band] = SAF_MIN(pData->masterOrder,curOrder);
804 }
805 break;
806
807 case MIC_PRESET_DTU_MIC:
808 for(band=0; band<HYBRID_BANDS; band++){
809 if(rangeIdx<2*(__DTU_mic_maxOrder-1)){
810 if(pData->freqVector[band]>__DTU_mic_freqRange[rangeIdx]){
811 if(!reverse)
812 curOrder++;
813 else
814 curOrder--;
815 reverse = (curOrder == __DTU_mic_maxOrder) || (reverse) ? 1 : 0;
816 rangeIdx++;
817 }
818 }
819 pData->orderPerBand[band] = SAF_MIN(pData->masterOrder,curOrder);
820 }
821 break;
822 }
823}
824
825void ambi_dec_setChOrder(void* const hAmbi, int newOrder)
826{
827 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
828 if((CH_ORDER)newOrder != CH_FUMA || pData->new_masterOrder==SH_ORDER_FIRST) /* FUMA only supports 1st order */
829 pData->chOrdering = (CH_ORDER)newOrder;
830}
831
832void ambi_dec_setNormType(void* const hAmbi, int newType)
833{
834 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
835 if((NORM_TYPES)newType != NORM_FUMA || pData->new_masterOrder==SH_ORDER_FIRST) /* FUMA only supports 1st order */
836 pData->norm = (NORM_TYPES)newType;
837}
838
839void ambi_dec_setDecMethod(void* const hAmbi, int index, int newID)
840{
841 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
842 pData->dec_method[index] = newID;
844}
845
846void ambi_dec_setDecEnableMaxrE(void* const hAmbi, int index, int newID)
847{
848 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
849 pData->rE_WEIGHT[index] = newID;
850}
851
852void ambi_dec_setDecNormType(void* const hAmbi, int index, int newID)
853{
854 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
855 pData->diffEQmode[index] = newID;
856}
857
858void ambi_dec_setTransitionFreq(void* const hAmbi, float newValue)
859{
860 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
862}
863
864
865/* Get Functions */
866
868{
869 return AMBI_DEC_FRAME_SIZE;
870}
871
873{
874 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
875 return pData->codecStatus;
876}
877
878float ambi_dec_getProgressBar0_1(void* const hAmbi)
879{
880 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
881 return pData->progressBar0_1;
882}
883
884void ambi_dec_getProgressBarText(void* const hAmbi, char* text)
885{
886 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
887 memcpy(text, pData->progressBarText, PROGRESSBARTEXT_CHAR_LENGTH*sizeof(char));
888}
889
890int ambi_dec_getMasterDecOrder(void * const hAmbi)
891{
892 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
893 return pData->new_masterOrder;
894}
895
896int ambi_dec_getDecOrder(void * const hAmbi, int bandIdx)
897{
898 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
899 return pData->orderPerBand[bandIdx];
900}
901
902int ambi_dec_getDecOrderAllBands(void * const hAmbi)
903{
904 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
905 return pData->orderPerBand[0];
906}
907
909(
910 void* const hAmbi,
911 float** pX_vector,
912 int** pY_values,
913 int* pNpoints
914)
915{
916 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
917 (*pX_vector) = &pData->freqVector[0];
918 (*pY_values) = (int*)&pData->orderPerBand[0];
919 (*pNpoints) = HYBRID_BANDS;
920}
921
923{
924 return HYBRID_BANDS;
925}
926
927float ambi_dec_getLoudspeakerAzi_deg(void* const hAmbi, int index)
928{
929 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
930 return pData->loudpkrs_dirs_deg[index][0];
931}
932
933float ambi_dec_getLoudspeakerElev_deg(void* const hAmbi, int index)
934{
935 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
936 return pData->loudpkrs_dirs_deg[index][1];
937}
938
939int ambi_dec_getNumLoudspeakers(void* const hAmbi)
940{
941 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
942 return pData->new_nLoudpkrs;
943}
944
949
950int ambi_dec_getNSHrequired(void* const hAmbi)
951{
952 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
953 return (pData->masterOrder+1)*(pData->masterOrder+1);
954}
955
956int ambi_dec_getBinauraliseLSflag(void* const hAmbi)
957{
958 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
959 return pData->new_binauraliseLS;
960}
961
963{
964 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
965 return pData->useDefaultHRIRsFLAG;
966}
967
968char* ambi_dec_getSofaFilePath(void* const hAmbi)
969{
970 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
971 ambi_dec_codecPars* pars = pData->pars;
972 if(pars->sofa_filepath!=NULL)
973 return pars->sofa_filepath;
974 else
975 return "/Spatial_Audio_Framework/Default";
976}
977
978int ambi_dec_getEnableHRIRsPreProc(void* const hAmbi)
979{
980 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
981 return pData->enableHRIRsPreProc;
982}
983
984int ambi_dec_getChOrder(void* const hAmbi)
985{
986 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
987 return (int)pData->chOrdering;
988}
989
990int ambi_dec_getNormType(void* const hAmbi)
991{
992 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
993 return (int)pData->norm;
994}
995
996int ambi_dec_getDecMethod(void* const hAmbi, int index)
997{
998 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
999 return pData->dec_method[index];
1000}
1001
1002int ambi_dec_getDecEnableMaxrE(void* const hAmbi, int index)
1003{
1004 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
1005 return pData->rE_WEIGHT[index];
1006}
1007
1008int ambi_dec_getDecNormType(void* const hAmbi, int index)
1009{
1010 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
1011 return pData->diffEQmode[index];
1012}
1013
1014float ambi_dec_getTransitionFreq(void* const hAmbi)
1015{
1016 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
1017 return pData->transitionFreq;
1018}
1019
1020int ambi_dec_getHRIRsamplerate(void* const hAmbi)
1021{
1022 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
1023 ambi_dec_codecPars* pars = pData->pars;
1024 return pars->hrir_orig_fs;
1025}
1026
1027int ambi_dec_getDAWsamplerate(void* const hAmbi)
1028{
1029 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
1030 return pData->fs;
1031}
1032
1034{
1035 return 12*HOP_SIZE;
1036}
1037
1038
1039
#define MAX_SH_ORDER
Maximum supported Ambisonic order.
Definition _common.h:56
#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_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
#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:661
void ambi_dec_create(void **const phAmbi)
Creates an instance of the ambi_dec.
Definition ambi_dec.c:49
int ambi_dec_getMaxNumLoudspeakers(void)
Returns the maximum number of loudspeakers supported by ambi_dec.
Definition ambi_dec.c:945
int ambi_dec_getNumLoudspeakers(void *const hAmbi)
Returns the number of loudspeakers in the current layout.
Definition ambi_dec.c:939
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:509
int ambi_dec_getMasterDecOrder(void *const hAmbi)
Returns the master/maximum decoding order (see SH_ORDERS enum)
Definition ambi_dec.c:890
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:950
void ambi_dec_setDecOrder(void *const hAmbi, int newValue, int bandIdx)
Sets the decoding order for a given frequency band.
Definition ambi_dec.c:655
float ambi_dec_getProgressBar0_1(void *const hAmbi)
(Optional) Returns current intialisation/processing progress, between 0..1
Definition ambi_dec.c:878
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:978
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:709
float ambi_dec_getLoudspeakerElev_deg(void *const hAmbi, int index)
Returns the loudspeaker elevation in degrees for a given index.
Definition ambi_dec.c:933
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:825
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:1008
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:896
void ambi_dec_getProgressBarText(void *const hAmbi, char *text)
(Optional) Returns current intialisation/processing progress text
Definition ambi_dec.c:884
int ambi_dec_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition ambi_dec.c:867
int ambi_dec_getNormType(void *const hAmbi)
Returns the Ambisonic normalisation convention currently being usedto decode with,...
Definition ambi_dec.c:990
int ambi_dec_getHRIRsamplerate(void *const hAmbi)
Returns the HRIR sample rate.
Definition ambi_dec.c:1020
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:846
void ambi_dec_initCodec(void *const hAmbi)
Intialises the codec variables, based on current global/user parameters.
Definition ambi_dec.c:191
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:728
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:962
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:759
void ambi_dec_refreshSettings(void *const hAmbi)
Sets all intialisation flags to 1.
Definition ambi_dec.c:636
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:909
int ambi_dec_getDecOrderAllBands(void *const hAmbi)
Returns the decoding order for the first band (see SH_ORDERS enum)
Definition ambi_dec.c:902
void ambi_dec_setOutputConfigPreset(void *const hAmbi, int newPresetID)
Sets the output loudspeaker preset.
Definition ambi_dec.c:748
int ambi_dec_getProcessingDelay(void)
Returns the processing delay in samples; may be used for delay compensation features.
Definition ambi_dec.c:1033
void ambi_dec_setDecNormType(void *const hAmbi, int index, int newID)
Sets the equalisation approach for one of the decoders.
Definition ambi_dec.c:852
int ambi_dec_getNumberOfBands(void)
Returns the number of frequency bands employed by ambi_dec.
Definition ambi_dec.c:922
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:1014
void ambi_dec_setDecMethod(void *const hAmbi, int index, int newID)
Sets the decoding method for a specific decoder.
Definition ambi_dec.c:839
char * ambi_dec_getSofaFilePath(void *const hAmbi)
Returns the file path for a .sofa file (WITH file extension)
Definition ambi_dec.c:968
void ambi_dec_setLoudspeakerElev_deg(void *const hAmbi, int index, float newElev_deg)
Sets the elevation of a specific loudspeaker.
Definition ambi_dec.c:684
CODEC_STATUS ambi_dec_getCodecStatus(void *const hAmbi)
Returns current codec status (see CODEC_STATUS enum)
Definition ambi_dec.c:872
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:718
void ambi_dec_setMasterDecOrder(void *const hAmbi, int newValue)
Sets the master decoding order.
Definition ambi_dec.c:643
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:996
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:739
int ambi_dec_getChOrder(void *const hAmbi)
Returns the Ambisonic channel ordering convention currently being used to decode with,...
Definition ambi_dec.c:984
void ambi_dec_init(void *const hAmbi, int sampleRate)
Initialises an instance of ambi_dec with default settings.
Definition ambi_dec.c:173
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:858
void ambi_dec_setLoudspeakerAzi_deg(void *const hAmbi, int index, float newAzi_deg)
Sets the azimuth of a specific loudspeaker.
Definition ambi_dec.c:670
void ambi_dec_setNumLoudspeakers(void *const hAmbi, int new_nLoudspeakers)
Sets the number of loudspeakers to decode to.
Definition ambi_dec.c:696
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:832
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:1002
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:956
void ambi_dec_destroy(void **const phAmbi)
Destroys an instance of the ambi_dec.
Definition ambi_dec.c:122
int ambi_dec_getDAWsamplerate(void *const hAmbi)
Returns the DAW/Host sample rate.
Definition ambi_dec.c:1027
float ambi_dec_getLoudspeakerAzi_deg(void *const hAmbi, int index)
Returns the loudspeaker azimuth in degrees for a given index.
Definition ambi_dec.c:927
#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
AMBI_DEC_DECODING_METHODS
Available decoding methods.
Definition ambi_dec.h:73
@ 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, _Atomic_FLOAT32 dirs_deg[MAX_NUM_LOUDSPEAKERS][2], _Atomic_INT32 *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 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
#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.
_Atomic_INT32 N_hrir_dirs
number of HRIR directions in the current sofa file
float_complex hrtf_interp[MAX_NUM_LOUDSPEAKERS][HYBRID_BANDS][NUM_EARS]
interpolated HRTFs
_Atomic_INT32 hrir_len
length of the HRIRs, this can be truncated, see "saf_sofa_reader.h"
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
float_complex * hrtf_fb
HRTF filterbank coefficients; nBands x nCH x N_hrirs.
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:...
_Atomic_INT32 hrir_fs
sampling rate of the HRIRs, should ideally match the host sampling rate, although not required
float * hrtf_fb_mag
magnitudes of the HRTF filterbank coefficients; nBands x nCH x N_hrirs
_Atomic_INT32 hrir_orig_fs
Can be different from hrir_fs if HRIRs were resampled.
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
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.
_Atomic_AMBI_DEC_DIFFUSE_FIELD_EQ_APPROACH diffEQmode[NUM_DECODERS]
diffuse-field EQ approach; see AMBI_DEC_DIFFUSE_FIELD_EQ_APPROACH enum
_Atomic_INT32 masterOrder
Current maximum/master decoding order.
_Atomic_INT32 new_masterOrder
if new_masterOrder != masterOrder, ambi_dec is reinitialised (current value will be replaced by this ...
_Atomic_INT32 reinit_hrtfsFLAG
0: no init required, 1: init required
_Atomic_CH_ORDER chOrdering
Ambisonic channel order convention (see CH_ORDER)
_Atomic_INT32 nLoudpkrs
number of loudspeakers/virtual loudspeakers
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.
_Atomic_FLOAT32 transitionFreq
transition frequency for the 2 decoders, in Hz
float_complex *** binframeTF
Output binaural signals in the time-frequency domain; HYBRID_BANDS x NUM_EARS x TIME_SLOTS.
_Atomic_INT32 recalc_hrtf_interpFLAG[MAX_NUM_LOUDSPEAKERS]
0: no init required, 1: init required
_Atomic_INT32 enableHRIRsPreProc
flag to apply pre-processing to the currently loaded HRTFs
_Atomic_NORM_TYPES norm
Ambisonic normalisation convention (see NORM_TYPES)
_Atomic_FLOAT32 loudpkrs_dirs_deg[MAX_NUM_LOUDSPEAKERS][2]
loudspeaker directions in degrees [azi, elev]
_Atomic_INT32 orderPerBand[HYBRID_BANDS]
Ambisonic decoding order per frequency band 1..SH_ORDER.
_Atomic_AMBI_DEC_DECODING_METHODS dec_method[NUM_DECODERS]
decoding methods for each decoder, see AMBI_DEC_DECODING_METHODS enum
void * hSTFT
afSTFT handle
_Atomic_INT32 useDefaultHRIRsFLAG
1: use default HRIRs in database, 0: use those from SOFA file
float_complex *** SHframeTF
Input spherical harmonic (SH) signals in the time-frequency domain; HYBRID_BANDS x MAX_NUM_SH_SIGNALS...
float ** outputFrameTD
Output loudspeaker or binaural signals in the time-domain; MAX_NUM_LOUDSPEAKERS x AMBI_DEC_FRAME_SIZE...
int firstInit
flag, 1: _init() function has never been called, 0: _init() function has been called
_Atomic_INT32 new_binauraliseLS
if new_binauraliseLS != binauraliseLS, ambi_dec is reinitialised (current value will be replaced by t...
_Atomic_PROC_STATUS procStatus
see PROC_STATUS
_Atomic_INT32 binauraliseLS
1: convolve loudspeaker signals with HRTFs, 0: output loudspeaker signals
_Atomic_INT32 fs
host sampling rate
_Atomic_CODEC_STATUS codecStatus
see CODEC_STATUS
_Atomic_INT32 rE_WEIGHT[NUM_DECODERS]
0:disabled, 1: enable max_rE weight
float freqVector[HYBRID_BANDS]
frequency vector for time-frequency transform, in Hz
char * progressBarText
Current (re)initialisation step, string.
_Atomic_FLOAT32 progressBar0_1
Current (re)initialisation progress, between [0..1].
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...
_Atomic_INT32 new_nLoudpkrs
if new_nLoudpkrs != nLoudpkrs, afSTFT is reinitialised (current value will be replaced by this after ...
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.