SAF
Loading...
Searching...
No Matches
array2sh.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
49
50#include "array2sh_internal.h"
51
53(
54 void ** const phA2sh
55)
56{
58 *phA2sh = (void*)pData;
59
60 /* defualt parameters */
63 pData->regPar = 15.0f;
64 pData->chOrdering = CH_ACN;
65 pData->norm = NORM_SN3D;
66 pData->c = 343.0f;
67 pData->gain_dB = 0.0f; /* post-gain */
68 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
69 array2sh_initArray(arraySpecs, MICROPHONE_ARRAY_PRESET_DEFAULT, &(pData->order), 1);
70 pData->enableDiffEQpastAliasing = 1;
71
72 /* time-frequency transform + buffers */
73 pData->fs = 48000.0f;
74 pData->firstInit = 1;
75 pData->hSTFT = NULL;
76 pData->inputFrameTD = (float**)malloc2d(MAX_NUM_SENSORS, ARRAY2SH_FRAME_SIZE, sizeof(float));
77 pData->SHframeTD = (float**)malloc2d(MAX_NUM_SH_SIGNALS, ARRAY2SH_FRAME_SIZE, sizeof(float));
78 pData->inputframeTF = (float_complex***)malloc3d(HYBRID_BANDS, MAX_NUM_SENSORS, TIME_SLOTS, sizeof(float_complex));
79 pData->SHframeTF = (float_complex***)malloc3d(HYBRID_BANDS, MAX_NUM_SH_SIGNALS, TIME_SLOTS, sizeof(float_complex));
80
81 /* internal */
82 pData->progressBar0_1 = 0.0f;
84 strcpy(pData->progressBarText,"");
86 pData->evalRequestedFLAG = 0;
87 pData->reinitSHTmatrixFLAG = 1;
88 pData->new_order = pData->order;
89 pData->bN = NULL;
90
91 /* For diffuse-field equalisation */
92 pData->L_diff_fal = malloc1d(MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS*sizeof(double_complex));
93 pData->L_diff = malloc1d(MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS*sizeof(double_complex));
94 pData->E_diff = malloc1d(MAX_NUM_SH_SIGNALS*MAX_NUM_SENSORS*sizeof(double_complex));
95 pData->W_diffEQ_tmp = malloc1d(MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS*sizeof(double_complex));
96 pData->W_tmp = malloc1d(MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS*sizeof(double_complex));
97
98 /* display related stuff */
99 pData->bN_modal_dB = (float**)calloc2d(HYBRID_BANDS, MAX_SH_ORDER + 1, sizeof(float));
100 pData->bN_inv_dB = (float**)calloc2d(HYBRID_BANDS, MAX_SH_ORDER + 1, sizeof(float));
101 pData->cSH = (float*)calloc1d((HYBRID_BANDS)*(MAX_SH_ORDER + 1),sizeof(float));
102 pData->lSH = (float*)calloc1d((HYBRID_BANDS)*(MAX_SH_ORDER + 1),sizeof(float));
103}
104
106(
107 void ** const phM2sh
108)
109{
110 array2sh_data *pData = (array2sh_data*)(*phM2sh);
111
112 if (pData != NULL) {
113 /* not safe to free memory during evaluation */
114 while (pData->evalStatus == EVAL_STATUS_EVALUATING)
115 SAF_SLEEP(10);
116
117 /* free afSTFT and buffers */
118 if (pData->hSTFT != NULL)
119 afSTFT_destroy(&(pData->hSTFT));
120 free(pData->inputFrameTD);
121 free(pData->SHframeTD);
122 free(pData->inputframeTF);
123 free(pData->SHframeTF);
125
126 /* For diffuse-field equalisation */
127 free(pData->L_diff_fal);
128 free(pData->L_diff);
129 free(pData->E_diff);
130 free(pData->W_diffEQ_tmp);
131 free(pData->W_tmp);
132
133 /* Display stuff */
134 free(pData->bN_modal_dB);
135 free(pData->bN_inv_dB);
136
137 free(pData->progressBarText);
138
139 free(pData->bN);
140 free(pData->cSH);
141 free(pData->lSH);
142
143 free(pData);
144 pData = NULL;
145 *phM2sh = NULL;
146 }
147}
148
150(
151 void * const hA2sh,
152 int sampleRate
153)
154{
155 array2sh_data *pData = (array2sh_data*)(hA2sh);
156
157 if(pData->fs != sampleRate || pData->firstInit){
158 pData->fs = sampleRate;
159 pData->reinitSHTmatrixFLAG = 1;
161 pData->firstInit = 0;
162 }
163 afSTFT_getCentreFreqs(pData->hSTFT, (float)pData->fs, HYBRID_BANDS, pData->freqVector);
164 pData->freqVector[0] = pData->freqVector[1]/4.0f; /* avoids NaNs at DC */
165}
166
168(
169 void* const hA2sh
170)
171{
172 array2sh_data *pData = (array2sh_data*)(hA2sh);
173
175 return; /* eval not required */
176
177 /* for progress bar */
179 strcpy(pData->progressBarText,"Initialising evaluation");
180 pData->progressBar0_1 = 0.0f;
181
182 /* Evaluate Encoder */
184
185 /* done! */
186 strcpy(pData->progressBarText,"Done!");
187 pData->progressBar0_1 = 1.0f;
189}
190
192(
193 void * const hA2sh,
194 const float *const * inputs,
195 float* const* const outputs,
196 int nInputs,
197 int nOutputs,
198 int nSamples
199)
200{
201 array2sh_data *pData = (array2sh_data*)(hA2sh);
202 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
203 int ch, i, band, Q, order, nSH;
204 const float_complex calpha = cmplxf(1.0f,0.0f), cbeta = cmplxf(0.0f, 0.0f);
205 CH_ORDER chOrdering;
206 NORM_TYPES norm;
207 float gain_lin;
208
209 /* reinit TFT if needed */
210 array2sh_initTFT(hA2sh);
211
212 /* compute encoding matrix if needed */
213 if (pData->reinitSHTmatrixFLAG) {
214 array2sh_calculate_sht_matrix(hA2sh); /* compute encoding matrix */
215 array2sh_calculate_mag_curves(hA2sh); /* calculate magnitude response curves */
216 pData->reinitSHTmatrixFLAG = 0;
217 }
218
219 /* local copy of user parameters */
220 chOrdering = pData->chOrdering;
221 norm = pData->norm;
222 gain_lin = powf(10.0f, pData->gain_dB/20.0f);
223 Q = arraySpecs->Q;
224 order = pData->order;
225 nSH = (order+1)*(order+1);
226
227 /* processing loop */
228 if ((nSamples == ARRAY2SH_FRAME_SIZE) && (pData->reinitSHTmatrixFLAG==0) ) {
230
231 /* Load time-domain data */
232 for(i=0; i < nInputs; i++)
233 utility_svvcopy(inputs[i], ARRAY2SH_FRAME_SIZE, pData->inputFrameTD[i]);
234 for(; i<Q; i++)
235 memset(pData->inputFrameTD[i], 0, ARRAY2SH_FRAME_SIZE * sizeof(float));
236
237 /* Apply time-frequency transform (TFT) */
239
240 /* Apply spherical harmonic transform (SHT) */
241 for(band=0; band<HYBRID_BANDS; band++){
242 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, TIME_SLOTS, Q, &calpha,
243 (float_complex*)pData->W[band], MAX_NUM_SENSORS,
244 FLATTEN2D(pData->inputframeTF[band]), TIME_SLOTS, &cbeta,
245 FLATTEN2D(pData->SHframeTF[band]), TIME_SLOTS);
246 }
247
248 /* inverse-TFT */
250
251 /* account for output channel order */
252 switch(chOrdering){
253 case CH_ACN: /* already ACN, do nothing */ break;
255 }
256
257 /* account for normalisation scheme */
258 switch(norm){
259 case NORM_N3D: /* already N3D, do nothing */ break;
262 }
263
264 /* Apply post-gain */
265 utility_svsmul(FLATTEN2D(pData->SHframeTD), &gain_lin, nSH*ARRAY2SH_FRAME_SIZE, NULL);
266
267 /* Copy to output */
268 for(i = 0; i < SAF_MIN(nSH,nOutputs); i++)
269 utility_svvcopy(pData->SHframeTD[i], ARRAY2SH_FRAME_SIZE, outputs[i]);
270 for(; i < nOutputs; i++)
271 memset(outputs[i], 0, ARRAY2SH_FRAME_SIZE * sizeof(float));
272 }
273 else{
274 for (ch=0; ch < nOutputs; ch++)
275 memset(outputs[ch],0, ARRAY2SH_FRAME_SIZE*sizeof(float));
276 }
277
279}
280
281/* Set Functions */
282
283void array2sh_refreshSettings(void* const hA2sh)
284{
285 array2sh_data *pData = (array2sh_data*)(hA2sh);
286 pData->reinitSHTmatrixFLAG = 1;
288}
289
290void array2sh_setEncodingOrder(void* const hA2sh, int newOrder)
291{
292 array2sh_data *pData = (array2sh_data*)(hA2sh);
293
294 if(pData->new_order != newOrder){
295 pData->new_order = newOrder;
296 pData->reinitSHTmatrixFLAG = 1;
298 }
299 /* FUMA only supports 1st order */
300 if(pData->new_order!=SH_ORDER_FIRST && pData->chOrdering == CH_FUMA)
301 pData->chOrdering = CH_ACN;
302 if(pData->new_order!=SH_ORDER_FIRST && pData->norm == NORM_FUMA)
303 pData->norm = NORM_SN3D;
304}
305
306void array2sh_setRequestEncoderEvalFLAG(void* const hA2sh, int newState)
307{
308 array2sh_data *pData = (array2sh_data*)(hA2sh);
309 pData->evalRequestedFLAG = newState;
310}
311
312void array2sh_setEvalStatus(void* const hA2sh, ARRAY2SH_EVAL_STATUS new_evalStatus)
313{
314 array2sh_data *pData = (array2sh_data*)(hA2sh);
315 if(new_evalStatus==EVAL_STATUS_NOT_EVALUATED){
316 /* Pause until current initialisation is complete */
317 while(pData->evalStatus == EVAL_STATUS_EVALUATING)
318 SAF_SLEEP(10);
319 }
320 pData->evalStatus = new_evalStatus;
321}
322
323void array2sh_setDiffEQpastAliasing(void* const hA2sh, int newState)
324{
325 array2sh_data *pData = (array2sh_data*)(hA2sh);
326 if(pData->enableDiffEQpastAliasing != newState){
327 pData->enableDiffEQpastAliasing = newState;
328 pData->reinitSHTmatrixFLAG = 1;
330 }
331}
332
334{
335 array2sh_data *pData = (array2sh_data*)(hA2sh);
336 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
337
338 array2sh_initArray(arraySpecs,(ARRAY2SH_MICROPHONE_ARRAY_PRESETS)preset, &(pData->new_order), 0);
339 pData->c = (ARRAY2SH_MICROPHONE_ARRAY_PRESETS)preset == MICROPHONE_ARRAY_PRESET_AALTO_HYDROPHONE ? 1484.0f : 343.0f;
340 pData->reinitSHTmatrixFLAG = 1;
342}
343
344void array2sh_setSensorAzi_rad(void* const hA2sh, int index, float newAzi_rad)
345{
346 array2sh_data *pData = (array2sh_data*)(hA2sh);
347 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
348
349 if(arraySpecs->sensorCoords_rad[index][0] != newAzi_rad){
350 arraySpecs->sensorCoords_rad[index][0] = newAzi_rad;
351 arraySpecs->sensorCoords_deg[index][0] = newAzi_rad * (180.0f/SAF_PI);
352 pData->reinitSHTmatrixFLAG = 1;
354 }
355}
356
357void array2sh_setSensorElev_rad(void* const hA2sh, int index, float newElev_rad)
358{
359 array2sh_data *pData = (array2sh_data*)(hA2sh);
360 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
361
362 if(arraySpecs->sensorCoords_rad[index][1] != newElev_rad){
363 arraySpecs->sensorCoords_rad[index][1] = newElev_rad;
364 arraySpecs->sensorCoords_deg[index][1] = newElev_rad * (180.0f/SAF_PI);
365 pData->reinitSHTmatrixFLAG = 1;
367 }
368}
369
370void array2sh_setSensorAzi_deg(void* const hA2sh, int index, float newAzi_deg)
371
372{
373 array2sh_data *pData = (array2sh_data*)(hA2sh);
374 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
375
376 if(arraySpecs->sensorCoords_deg[index][0] != newAzi_deg){
377 arraySpecs->sensorCoords_rad[index][0] = newAzi_deg * (SAF_PI/180.0f);
378 arraySpecs->sensorCoords_deg[index][0] = newAzi_deg;
379 pData->reinitSHTmatrixFLAG = 1;
381 }
382}
383
384void array2sh_setSensorElev_deg(void* const hA2sh, int index, float newElev_deg)
385{
386 array2sh_data *pData = (array2sh_data*)(hA2sh);
387 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
388
389 if(arraySpecs->sensorCoords_deg[index][1] != newElev_deg){
390 arraySpecs->sensorCoords_rad[index][1] = newElev_deg * (SAF_PI/180.0f);
391 arraySpecs->sensorCoords_deg[index][1] = newElev_deg;
392 pData->reinitSHTmatrixFLAG = 1;
394 }
395}
396
397void array2sh_setNumSensors(void* const hA2sh, int newQ)
398{
399 array2sh_data *pData = (array2sh_data*)(hA2sh);
400 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
401 int nSH;
402
403 nSH = (pData->new_order+1)*(pData->new_order+1);
404 if (newQ < nSH){
405 pData->new_order = 1;
406 pData->reinitSHTmatrixFLAG = 1;
408 }
409 if(arraySpecs->Q != newQ){
410 arraySpecs->newQ = newQ;
411 pData->reinitSHTmatrixFLAG = 1;
413 }
414}
415
416void array2sh_setr(void* const hA2sh, float newr)
417{
418 array2sh_data *pData = (array2sh_data*)(hA2sh);
419 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
420
422 if(arraySpecs->r!=newr){
423 arraySpecs->r = newr;
424 pData->reinitSHTmatrixFLAG = 1;
426 }
427}
428
429void array2sh_setR(void* const hA2sh, float newR)
430{
431 array2sh_data *pData = (array2sh_data*)(hA2sh);
432 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
433
435 if(arraySpecs->R!=newR){
436 arraySpecs->R = newR;
437 pData->reinitSHTmatrixFLAG = 1;
439 }
440}
441
442void array2sh_setArrayType(void* const hA2sh, int newType)
443{
444 array2sh_data *pData = (array2sh_data*)(hA2sh);
445 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
446
447 if(arraySpecs->arrayType != (ARRAY2SH_ARRAY_TYPES)newType){
448 arraySpecs->arrayType = (ARRAY2SH_ARRAY_TYPES)newType;
449 if( !(arraySpecs->weightType == WEIGHT_RIGID_OMNI || arraySpecs->weightType == WEIGHT_OPEN_OMNI)){
450 arraySpecs->weightType = WEIGHT_RIGID_OMNI;
451 }
452 pData->reinitSHTmatrixFLAG = 1;
454 }
455}
456
457void array2sh_setWeightType(void* const hA2sh, int newType)
458{
459 array2sh_data *pData = (array2sh_data*)(hA2sh);
460 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
461
462 if(arraySpecs->weightType!=(ARRAY2SH_WEIGHT_TYPES)newType){
463 arraySpecs->weightType = (ARRAY2SH_WEIGHT_TYPES)newType;
464 pData->reinitSHTmatrixFLAG = 1;
466 }
467}
468
469void array2sh_setFilterType(void* const hA2sh, int newType)
470{
471 array2sh_data *pData = (array2sh_data*)(hA2sh);
472
473 if(pData->filterType!=(ARRAY2SH_FILTER_TYPES)newType){
474 pData->filterType = (ARRAY2SH_FILTER_TYPES)newType;
475 pData->reinitSHTmatrixFLAG = 1;
477 }
478}
479
480void array2sh_setRegPar(void* const hA2sh, float newVal)
481{
482 array2sh_data *pData = (array2sh_data*)(hA2sh);
484 if(pData->regPar!=newVal){
485 pData->regPar = newVal;
486 pData->reinitSHTmatrixFLAG = 1;
488 }
489}
490
491void array2sh_setChOrder(void* const hA2sh, int newOrder)
492{
493 array2sh_data *pData = (array2sh_data*)(hA2sh);
494 if((CH_ORDER)newOrder != CH_FUMA || pData->order==SH_ORDER_FIRST)/* FUMA only supports 1st order */
495 pData->chOrdering = (CH_ORDER)newOrder;
496}
497
498void array2sh_setNormType(void* const hA2sh, int newType)
499{
500 array2sh_data *pData = (array2sh_data*)(hA2sh);
501 if((NORM_TYPES)newType != NORM_FUMA || pData->order==SH_ORDER_FIRST)/* FUMA only supports 1st order */
502 pData->norm = (NORM_TYPES)newType;
503}
504
505void array2sh_setc(void* const hA2sh, float newc)
506{
507 array2sh_data *pData = (array2sh_data*)(hA2sh);
509 if(newc!=pData->c){
510 pData->c = newc;
511 pData->reinitSHTmatrixFLAG = 1;
513 }
514}
515
516void array2sh_setGain(void* const hA2sh, float newGain)
517{
518 array2sh_data *pData = (array2sh_data*)(hA2sh);
520}
521
522
523/* Get Functions */
524
526{
527 return ARRAY2SH_FRAME_SIZE;
528}
529
531{
532 array2sh_data *pData = (array2sh_data*)(hA2sh);
533 return pData->evalStatus;
534}
535
537{
538 array2sh_data *pData = (array2sh_data*)(hA2sh);
539 return pData->reinitSHTmatrixFLAG;
540}
541
542float array2sh_getProgressBar0_1(void* const hA2sh)
543{
544 array2sh_data *pData = (array2sh_data*)(hA2sh);
545 return pData->progressBar0_1;
546}
547
548void array2sh_getProgressBarText(void* const hA2sh, char* text)
549{
550 array2sh_data *pData = (array2sh_data*)(hA2sh);
551 memcpy(text, pData->progressBarText, PROGRESSBARTEXT_CHAR_LENGTH*sizeof(char));
552}
553
555{
556 array2sh_data *pData = (array2sh_data*)(hA2sh);
557 return pData->evalRequestedFLAG;
558}
559
560int array2sh_getDiffEQpastAliasing(void* const hA2sh)
561{
562 array2sh_data *pData = (array2sh_data*)(hA2sh);
563 return pData->enableDiffEQpastAliasing;
564}
565
566int array2sh_getEncodingOrder(void* const hA2sh)
567{
568 array2sh_data *pData = (array2sh_data*)(hA2sh);
569 return pData->new_order;
570}
571
572float array2sh_getSensorAzi_rad(void* const hA2sh, int index)
573{
574 array2sh_data *pData = (array2sh_data*)(hA2sh);
575 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
576 return arraySpecs->sensorCoords_rad[index][0];
577}
578
579float array2sh_getSensorElev_rad(void* const hA2sh, int index)
580{
581 array2sh_data *pData = (array2sh_data*)(hA2sh);
582 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
583 return arraySpecs->sensorCoords_rad[index][1];
584}
585
586float array2sh_getSensorAzi_deg(void* const hA2sh, int index)
587{
588 array2sh_data *pData = (array2sh_data*)(hA2sh);
589 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
590 return arraySpecs->sensorCoords_deg[index][0];
591}
592
593float array2sh_getSensorElev_deg(void* const hA2sh, int index)
594{
595 array2sh_data *pData = (array2sh_data*)(hA2sh);
596 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
597 return arraySpecs->sensorCoords_deg[index][1];
598}
599
600int array2sh_getNumSensors(void* const hA2sh)
601{
602 array2sh_data *pData = (array2sh_data*)(hA2sh);
603 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
604 // return arraySpecs->Q;
605 return arraySpecs->newQ; /* return the new Q, incase the plug-in is still waiting for a refresh */
606}
607
609{
610 return MAX_NUM_SENSORS;
611}
612
613int array2sh_getMinNumSensors(void* const hA2sh)
614{
615 array2sh_data *pData = (array2sh_data*)(hA2sh);
616 return (pData->new_order+1)*(pData->new_order+1);
617}
618
619int array2sh_getNSHrequired(void* const hA2sh)
620{
621 array2sh_data *pData = (array2sh_data*)(hA2sh);
622 return (pData->new_order+1)*(pData->new_order+1);
623}
624
625float array2sh_getr(void* const hA2sh)
626{
627 array2sh_data *pData = (array2sh_data*)(hA2sh);
628 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
629 return arraySpecs->r;
630}
631
632float array2sh_getR(void* const hA2sh)
633{
634 array2sh_data *pData = (array2sh_data*)(hA2sh);
635 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
636 return arraySpecs->R;
637}
638
639int array2sh_getArrayType(void* const hA2sh)
640{
641 array2sh_data *pData = (array2sh_data*)(hA2sh);
642 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
643 return (int)arraySpecs->arrayType;
644}
645
646int array2sh_getWeightType(void* const hA2sh)
647{
648 array2sh_data *pData = (array2sh_data*)(hA2sh);
649 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
650 return (int)arraySpecs->weightType;
651}
652
653int array2sh_getFilterType(void* const hA2sh)
654{
655 array2sh_data *pData = (array2sh_data*)(hA2sh);
656 return (int)pData->filterType;
657}
658
659float array2sh_getRegPar(void* const hA2sh)
660{
661 array2sh_data *pData = (array2sh_data*)(hA2sh);
662 return pData->regPar;
663}
664
665int array2sh_getChOrder(void* const hA2sh)
666{
667 array2sh_data *pData = (array2sh_data*)(hA2sh);
668 return (int)pData->chOrdering;
669}
670
671int array2sh_getNormType(void* const hA2sh)
672{
673 array2sh_data *pData = (array2sh_data*)(hA2sh);
674 return (int)pData->norm;
675}
676
677float array2sh_getc(void* const hA2sh)
678{
679 array2sh_data *pData = (array2sh_data*)(hA2sh);
680 return pData->c;
681}
682
683float array2sh_getGain(void* const hA2sh)
684{
685 array2sh_data *pData = (array2sh_data*)(hA2sh);
686 return pData->gain_dB;
687}
688
689float* array2sh_getFreqVector(void* const hA2sh, int* nFreqPoints)
690{
691 array2sh_data *pData = (array2sh_data*)(hA2sh);
692 (*nFreqPoints) = HYBRID_BANDS;
693 return &(pData->freqVector[0]);
694}
695
696float** array2sh_getbN_inv(void* const hA2sh, int* nCurves, int* nFreqPoints)
697{
698 array2sh_data *pData = (array2sh_data*)(hA2sh);
699 (*nCurves) = pData->order+1;
700 (*nFreqPoints) = HYBRID_BANDS;
701 return pData->bN_inv_dB;
702}
703
704float** array2sh_getbN_modal(void* const hA2sh, int* nCurves, int* nFreqPoints)
705{
706 array2sh_data *pData = (array2sh_data*)(hA2sh);
707 (*nCurves) = pData->order+1;
708 (*nFreqPoints) = HYBRID_BANDS;
709 return pData->bN_modal_dB;
710}
711
712float* array2sh_getSpatialCorrelation_Handle(void* const hA2sh, int* nCurves, int* nFreqPoints)
713{
714 array2sh_data *pData = (array2sh_data*)(hA2sh);
715 (*nCurves) = pData->order+1;
716 (*nFreqPoints) = HYBRID_BANDS;
717 return pData->cSH;
718}
719
720float* array2sh_getLevelDifference_Handle(void* const hA2sh, int* nCurves, int* nFreqPoints)
721{
722 array2sh_data *pData = (array2sh_data*)(hA2sh);
723 (*nCurves) = pData->order+1;
724 (*nFreqPoints) = HYBRID_BANDS;
725 return pData->lSH;
726}
727
728int array2sh_getSamplingRate(void* const hA2sh)
729{
730 array2sh_data *pData = (array2sh_data*)(hA2sh);
731 return pData->fs;
732}
733
735{
736 return 12*HOP_SIZE;
737}
#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
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
#define TIME_SLOTS
Number of STFT timeslots.
#define HOP_SIZE
STFT hop size.
#define HYBRID_BANDS
Number of frequency bands.
void array2sh_process(void *const hA2sh, const float *const *inputs, float *const *const outputs, int nInputs, int nOutputs, int nSamples)
Spatially encode microphone/hydrophone array signals into spherical harmonic signals.
Definition array2sh.c:192
float array2sh_getR(void *const hA2sh)
Returns the radius of the scatterer, in meters.
Definition array2sh.c:632
void array2sh_setNormType(void *const hA2sh, int newType)
Sets the Ambisonic normalisation convention to encode with, in order to match with the convention emp...
Definition array2sh.c:498
float * array2sh_getSpatialCorrelation_Handle(void *const hA2sh, int *nCurves, int *nFreqPoints)
Returns a pointer to the spatial correlation [1] data.
Definition array2sh.c:712
float array2sh_getSensorElev_deg(void *const hA2sh, int index)
Returns a particular sensor's elevation w.r.t to the origin of the array, in DEGREES.
Definition array2sh.c:593
float array2sh_getr(void *const hA2sh)
Returns the radius of the array, in meters.
Definition array2sh.c:625
void array2sh_setNumSensors(void *const hA2sh, int newQ)
Sets the number of sensors in the array.
Definition array2sh.c:397
float ** array2sh_getbN_inv(void *const hA2sh, int *nCurves, int *nFreqPoints)
Returns the regularised inversion of the modal coefficients per frequency (may be used for optional p...
Definition array2sh.c:696
void array2sh_setSensorElev_rad(void *const hA2sh, int index, float newElev_rad)
Sets a particular sensor's elevation (radians) w.r.t to the origin of the array.
Definition array2sh.c:357
void array2sh_setR(void *const hA2sh, float newR)
Sets the radius (in meters) of the scatterer (only for Rigid arrays).
Definition array2sh.c:429
void array2sh_setGain(void *const hA2sh, float newGain)
Sets the amount of post gain to apply after the encoding, in DECIBELS.
Definition array2sh.c:516
float array2sh_getSensorAzi_deg(void *const hA2sh, int index)
Returns a particular sensor's azimuth w.r.t to the origin of the array, in DEGREES.
Definition array2sh.c:586
float * array2sh_getFreqVector(void *const hA2sh, int *nFreqPoints)
Returns a pointer to the frequency vector.
Definition array2sh.c:689
void array2sh_destroy(void **const phM2sh)
Destroys an instance of array2sh.
Definition array2sh.c:106
void array2sh_create(void **const phA2sh)
Creates an instance of array2sh.
Definition array2sh.c:53
void array2sh_setRegPar(void *const hA2sh, float newVal)
Sets the value of the regularisation parameter (the maximum permitted gain of the filters),...
Definition array2sh.c:480
int array2sh_getRequestEncoderEvalFLAG(void *const hA2sh)
Returns a flag, which is '1' if there has been a recent request to evaluate the current encoding perf...
Definition array2sh.c:554
int array2sh_getMaxNumSensors(void)
Returns the maximum supported number of sensors which can be in the array.
Definition array2sh.c:608
void array2sh_setArrayType(void *const hA2sh, int newType)
Sets the type of array (see ARRAY2SH_ARRAY_TYPES enum)
Definition array2sh.c:442
int array2sh_getEncodingOrder(void *const hA2sh)
Returns the current encoding order (see SH_ORDERS enum)
Definition array2sh.c:566
float array2sh_getProgressBar0_1(void *const hA2sh)
(Optional) Returns current intialisation/processing progress, between 0..1
Definition array2sh.c:542
void array2sh_refreshSettings(void *const hA2sh)
Sets all intialisation flags to 1; re-initialising all settings/variables as array2sh is currently co...
Definition array2sh.c:283
void array2sh_setEncodingOrder(void *const hA2sh, int newOrder)
Sets the encoding order (see SH_ORDERS enum)
Definition array2sh.c:290
void array2sh_setFilterType(void *const hA2sh, int newType)
Sets the type filter design to employ for computing the encoding matrices (see ARRAY2SH_FILTER_TYPES ...
Definition array2sh.c:469
int array2sh_getSamplingRate(void *const hA2sh)
Returns the DAW/Host sample rate.
Definition array2sh.c:728
void array2sh_init(void *const hA2sh, int sampleRate)
Initialises an instance of array2sh with default settings.
Definition array2sh.c:150
void array2sh_setSensorElev_deg(void *const hA2sh, int index, float newElev_deg)
Sets a particular sensor's elevation (degrees) w.r.t to the origin of the array.
Definition array2sh.c:384
float array2sh_getRegPar(void *const hA2sh)
Returns the value of the regurlisation parameter; the maximum permitted gain provided by the filters,...
Definition array2sh.c:659
void array2sh_setEvalStatus(void *const hA2sh, ARRAY2SH_EVAL_STATUS new_evalStatus)
Sets current eval status (see ARRAY2SH_EVAL_STATUS enum)
Definition array2sh.c:312
float * array2sh_getLevelDifference_Handle(void *const hA2sh, int *nCurves, int *nFreqPoints)
Returns a pointer to the level-difference [1] data.
Definition array2sh.c:720
int array2sh_getArrayType(void *const hA2sh)
Returns the type of array.
Definition array2sh.c:639
void array2sh_setPreset(void *const hA2sh, ARRAY2SH_MICROPHONE_ARRAY_PRESETS preset)
Sets a pre-defined microphone/hydrophone array preset (See ARRAY2SH_MICROPHONE_ARRAY_PRESETS enum)
Definition array2sh.c:333
int array2sh_getNormType(void *const hA2sh)
Returns the Ambisonic normalisation convention currently being usedto decode with,...
Definition array2sh.c:671
int array2sh_getDiffEQpastAliasing(void *const hA2sh)
Flag to enabled/disable diffuse equalisation above the spatial aliasing limit of the array (0: disabl...
Definition array2sh.c:560
float ** array2sh_getbN_modal(void *const hA2sh, int *nCurves, int *nFreqPoints)
Returns the direct inversion of the modal coefficients per frequency (may be used for optional plotti...
Definition array2sh.c:704
int array2sh_getMinNumSensors(void *const hA2sh)
Returns the minimum number of sensors which can be in the array [(current_order+1)^2].
Definition array2sh.c:613
float array2sh_getc(void *const hA2sh)
Returns the speed of sound of the medium (~343m/s air, ~1480m/s water), in m/s.
Definition array2sh.c:677
void array2sh_getProgressBarText(void *const hA2sh, char *text)
(Optional) Returns current intialisation/processing progress text
Definition array2sh.c:548
void array2sh_setc(void *const hA2sh, float newc)
Sets the speed of sound of the medium (~343m/s air, ~1480m/s water), in m/s.
Definition array2sh.c:505
void array2sh_evalEncoder(void *const hA2sh)
Evaluates the encoder, based on current global/user parameters.
Definition array2sh.c:168
void array2sh_setr(void *const hA2sh, float newr)
Sets the radius of the array.
Definition array2sh.c:416
void array2sh_setSensorAzi_rad(void *const hA2sh, int index, float newAzi_rad)
Sets a particular sensor's azimuth (radians) w.r.t to the origin of the array.
Definition array2sh.c:344
void array2sh_setSensorAzi_deg(void *const hA2sh, int index, float newAzi_deg)
Sets a particular sensor's azimuth (degrees) w.r.t to the origin of the array.
Definition array2sh.c:370
int array2sh_getNSHrequired(void *const hA2sh)
Returns the number of spherical harmonic signals required by the current encoding order: (current_ord...
Definition array2sh.c:619
void array2sh_setWeightType(void *const hA2sh, int newType)
Sets the type of weights to use (see ARRAY2SH_WEIGHT_TYPES enum)
Definition array2sh.c:457
void array2sh_setDiffEQpastAliasing(void *const hA2sh, int newState)
Analyses what the theoretical spatial aliasing frequency is, and conducts diffuse-field equalisation ...
Definition array2sh.c:323
float array2sh_getGain(void *const hA2sh)
Returns the amount of post gain to apply after the encoding, in DECIBELS.
Definition array2sh.c:683
void array2sh_setChOrder(void *const hA2sh, int newOrder)
Sets the Ambisonic channel ordering convention to encode with, in order to match the convention emplo...
Definition array2sh.c:491
float array2sh_getSensorAzi_rad(void *const hA2sh, int index)
Returns a particular sensor's azimuth w.r.t to the origin of the array, in RADIANS.
Definition array2sh.c:572
int array2sh_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition array2sh.c:525
float array2sh_getSensorElev_rad(void *const hA2sh, int index)
Returns a particular sensor's elevation w.r.t to the origin of the array, in RADIANS.
Definition array2sh.c:579
int array2sh_getChOrder(void *const hA2sh)
Returns the Ambisonic channel ordering convention currently being used to decode with,...
Definition array2sh.c:665
int array2sh_getFilterType(void *const hA2sh)
Returns the type filter design to employ for computing the encoding matrices (see ARRAY2SH_FILTER_TYP...
Definition array2sh.c:653
int array2sh_getWeightType(void *const hA2sh)
Returns the type of weights to use see ARRAY2SH_WEIGHT_TYPES enum.
Definition array2sh.c:646
int array2sh_getReinitSHTmatrixFLAG(void *const hA2sh)
Returns 0 if SHT is not be reinitialised, 1: if it is.
Definition array2sh.c:536
int array2sh_getProcessingDelay(void)
Returns the processing delay in samples (may be used for delay compensation features)
Definition array2sh.c:734
int array2sh_getNumSensors(void *const hA2sh)
Returns the number of sensors in the array.
Definition array2sh.c:600
void array2sh_setRequestEncoderEvalFLAG(void *const hA2sh, int newState)
Evaluates the performance of the current encoding filters when applied to a theoretical model of the ...
Definition array2sh.c:306
ARRAY2SH_EVAL_STATUS array2sh_getEvalStatus(void *const hA2sh)
Returns current eval status (see ARRAY2SH_EVAL_STATUS enum)
Definition array2sh.c:530
ARRAY2SH_MICROPHONE_ARRAY_PRESETS
Available microphone array presets.
Definition array2sh.h:105
#define ARRAY2SH_POST_GAIN_MIN_VALUE
Minimum post-gain, dB.
Definition array2sh.h:204
#define ARRAY2SH_BAFFLE_RADIUS_MAX_VALUE
Maximum baffle radius supported, mm.
Definition array2sh.h:225
ARRAY2SH_FILTER_TYPES
Available encoding filter approaches.
Definition array2sh.h:134
@ FILTER_TIKHONOV
Encoding filters based on a 'Tikhonov' regularised inversion of the modal responses [2].
Definition array2sh.h:138
#define ARRAY2SH_SPEED_OF_SOUND_MAX_VALUE
Maximum speed of sound value, m/s.
Definition array2sh.h:213
#define ARRAY2SH_ARRAY_RADIUS_MIN_VALUE
Minimum array radius supported, mm.
Definition array2sh.h:216
ARRAY2SH_WEIGHT_TYPES
List of supported sensor directivities and array construction types.
Definition array2sh.h:166
@ WEIGHT_RIGID_OMNI
Rigid baffle construction with omni sensors.
Definition array2sh.h:167
@ WEIGHT_OPEN_OMNI
Open array construction with omni sensors.
Definition array2sh.h:171
#define ARRAY2SH_BAFFLE_RADIUS_MIN_VALUE
Minimum baffle radius supported, mm.
Definition array2sh.h:222
#define ARRAY2SH_POST_GAIN_MAX_VALUE
Maximum post-gain, dB.
Definition array2sh.h:207
#define ARRAY2SH_MAX_GAIN_MAX_VALUE
Maximum gain value used for regularised inverse of modal coeffs, dB.
Definition array2sh.h:201
ARRAY2SH_ARRAY_TYPES
List of supported array types.
Definition array2sh.h:156
#define ARRAY2SH_ARRAY_RADIUS_MAX_VALUE
Maximum array radius supported, mm.
Definition array2sh.h:219
#define ARRAY2SH_SPEED_OF_SOUND_MIN_VALUE
Minimum speed of sound value, m/s.
Definition array2sh.h:210
#define ARRAY2SH_MAX_GAIN_MIN_VALUE
Minimum gain value used for regularised inverse of modal coeffs, dB.
Definition array2sh.h:198
ARRAY2SH_EVAL_STATUS
Current status of the encoder evaluation output data.
Definition array2sh.h:186
@ EVAL_STATUS_RECENTLY_EVALUATED
Encoder has recently been evaluated.
Definition array2sh.h:188
@ EVAL_STATUS_EVALUATING
Encoder is being evaluated.
Definition array2sh.h:190
@ EVAL_STATUS_NOT_EVALUATED
Encoder has not been evaluated.
Definition array2sh.h:189
void array2sh_evaluateSHTfilters(void *hA2sh)
Evaluates the spherical harmonic transform performance with the currently configured microphone/hydro...
void array2sh_calculate_sht_matrix(void *const hA2sh)
Computes the spherical harmonic transform (SHT) matrix, to spatially encode input microphone/hydropho...
void array2sh_initTFT(void *const hA2sh)
Initialise the filterbank used by array2sh.
void array2sh_initArray(void *const hPars, ARRAY2SH_MICROPHONE_ARRAY_PRESETS preset, _Atomic_INT32 *arrayOrder, int firstInitFlag)
Intialises an instance of a struct based on a preset, which contains the array configuration data.
void array2sh_calculate_mag_curves(void *const hA2sh)
Computes the magnitude responses of the equalisation filters; the absolute values of the regularised ...
void array2sh_destroyArray(void **const hPars)
Destroys an instance of a struct, which contains the array configuration data.
void array2sh_createArray(void **const hPars)
Creates an instance of a struct, which contains the array configuration data.
Spatially encodes spherical microphone array signals into spherical harmonic signals (aka: Ambisonic ...
#define ARRAY2SH_FRAME_SIZE
Framesize, in time-domain samples.
#define MAX_NUM_SENSORS
Maximum permitted number of inputs/sensors.
void convertHOAChannelConvention(float *insig, int order, int signalLength, HOA_CH_ORDER inConvention, HOA_CH_ORDER outConvention)
Converts an Ambisonic signal from one channel ordering convention to another.
Definition saf_hoa.c:41
void convertHOANormConvention(float *insig, int order, int signalLength, HOA_NORM inConvention, HOA_NORM outConvention)
Converts an Ambisonic signal from one normalisation convention to another.
Definition saf_hoa.c:73
@ HOA_CH_ORDER_FUMA
Furse-Malham (FuMa) convention, often used by older recordings.
Definition saf_hoa.h:187
@ HOA_CH_ORDER_ACN
Ambisonic Channel numbering (ACN) convention, which is employed by all spherical harmonic related fun...
Definition saf_hoa.h:184
@ HOA_NORM_FUMA
Furse-Malham (FuMa) convention.
Definition saf_hoa.h:208
@ HOA_NORM_SN3D
Schmidt semi-normalisation (SN3D) convention, as used by the AmbiX standard.
Definition saf_hoa.h:206
@ HOA_NORM_N3D
Orthonormalised (N3D) convention, which is the default convention used by SAF.
Definition saf_hoa.h:204
#define SAF_CLAMP(a, min, max)
Ensures value "a" is clamped between the "min" and "max" values.
#define SAF_PI
pi constant (single precision)
void utility_svvcopy(const float *a, const int len, float *c)
Single-precision, vector-vector copy, i.e.
#define SAF_MIN(a, b)
Returns the minimum of the two values.
void utility_svsmul(float *a, const float *s, const int len, float *c)
Single-precision, multiplies each element in vector 'a' with a scalar 's', i.e.
void ** malloc2d(size_t dim1, size_t dim2, size_t data_size)
2-D malloc (contiguously allocated, so use free() as usual to deallocate)
Definition md_malloc.c:89
void * malloc1d(size_t dim1_data_size)
1-D malloc (same as malloc, but with error checking)
Definition md_malloc.c:59
void * calloc1d(size_t dim1, size_t data_size)
1-D calloc (same as calloc, but with error checking)
Definition md_malloc.c:69
void *** 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
void ** calloc2d(size_t dim1, size_t dim2, size_t data_size)
2-D calloc (contiguously allocated, so use free() as usual to deallocate)
Definition md_malloc.c:102
#define FLATTEN2D(A)
Use this macro when passing a 2-D dynamic multi-dimensional array to memset, memcpy or any other func...
Definition md_malloc.h:65
Contains variables for describing the microphone/hydrophone array.
_Atomic_FLOAT32 r
radius of sensors
_Atomic_ARRAY2SH_WEIGHT_TYPES weightType
see ARRAY2SH_WEIGHT_TYPES
_Atomic_ARRAY2SH_ARRAY_TYPES arrayType
see ARRAY2SH_ARRAY_TYPES
_Atomic_FLOAT32 R
radius of scatterer (only for rigid arrays)
_Atomic_INT32 Q
Current number of sensors.
_Atomic_INT32 newQ
New number of sensors (current value replaced by this after next re-init)
_Atomic_FLOAT32 sensorCoords_deg[MAX_NUM_SENSORS][2]
Sensor directions in degrees.
_Atomic_FLOAT32 sensorCoords_rad[MAX_NUM_SENSORS][2]
Sensor directions in radians.
Main structure for array2sh.
float ** SHframeTD
Output SH signals in the time-domain; MAX_NUM_SH_SIGNALS x ARRAY2SH_FRAME_SIZE.
float_complex *** inputframeTF
Input sensor signals in the time-domain; HYBRID_BANDS x MAX_NUM_SENSORS x TIME_SLOTS.
_Atomic_FLOAT32 progressBar0_1
Current (re)initialisation progress, between [0..1].
_Atomic_FLOAT32 gain_dB
post gain, dB
_Atomic_FLOAT32 regPar
regularisation upper gain limit, dB;
int fs
sampling rate, hz
float freqVector[HYBRID_BANDS]
frequency vector
double_complex * bN
Temp vector for the modal coefficients.
char * progressBarText
Current (re)initialisation step, string.
_Atomic_INT32 reinitSHTmatrixFLAG
0: do not reinit; 1: reinit;
_Atomic_PROC_STATUS procStatus
see PROC_STATUS
void * hSTFT
filterbank handle
float ** bN_modal_dB
modal responses / no regulaisation; HYBRID_BANDS x (MAX_SH_ORDER +1)
void * arraySpecs
array configuration
_Atomic_INT32 enableDiffEQpastAliasing
0: disabled, 1: enabled
int firstInit
flag, 1: _init() function has never been called, 0: _init() function has been called
float ** inputFrameTD
Input sensor signals in the time-domain; MAX_NUM_SENSORS x ARRAY2SH_FRAME_SIZE.
float_complex *** SHframeTF
Output SH signals in the time-domain; HYBRID_BANDS x MAX_NUM_SH_SIGNALS x TIME_SLOTS.
float * cSH
spatial correlation; HYBRID_BANDS x 1
_Atomic_INT32 new_order
new encoding order (current value will be replaced by this after next re-init)
_Atomic_INT32 evalRequestedFLAG
0: do not reinit; 1: reinit;
_Atomic_FLOAT32 c
speed of sound, m/s
_Atomic_ARRAY2SH_FILTER_TYPES filterType
encoding filter approach
_Atomic_ARRAY2SH_EVAL_STATUS evalStatus
see ARRAY2SH_EVAL_STATUS
_Atomic_NORM_TYPES norm
Ambisonic normalisation convention (see NORM_TYPES)
float ** bN_inv_dB
modal responses / with regularisation; HYBRID_BANDS x (MAX_SH_ORDER +1)
float * lSH
level difference; HYBRID_BANDS x 1
_Atomic_INT32 order
current encoding order
_Atomic_CH_ORDER chOrdering
Ambisonic channel order convention (see CH_ORDER)
float_complex W[HYBRID_BANDS][MAX_NUM_SH_SIGNALS][MAX_NUM_SENSORS]
Encoding weights.