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
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->hSTFT = NULL;
75 pData->inputFrameTD = (float**)malloc2d(MAX_NUM_SENSORS, ARRAY2SH_FRAME_SIZE, sizeof(float));
76 pData->SHframeTD = (float**)malloc2d(MAX_NUM_SH_SIGNALS, ARRAY2SH_FRAME_SIZE, sizeof(float));
77 pData->inputframeTF = (float_complex***)malloc3d(HYBRID_BANDS, MAX_NUM_SENSORS, TIME_SLOTS, sizeof(float_complex));
78 pData->SHframeTF = (float_complex***)malloc3d(HYBRID_BANDS, MAX_NUM_SH_SIGNALS, TIME_SLOTS, sizeof(float_complex));
79
80 /* internal */
81 pData->progressBar0_1 = 0.0f;
83 strcpy(pData->progressBarText,"");
85 pData->evalRequestedFLAG = 0;
86 pData->reinitSHTmatrixFLAG = 1;
87 pData->new_order = pData->order;
88 pData->bN = NULL;
89
90 /* For diffuse-field equalisation */
91 pData->L_diff_fal = malloc1d(MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS*sizeof(double_complex));
92 pData->L_diff = malloc1d(MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS*sizeof(double_complex));
93 pData->E_diff = malloc1d(MAX_NUM_SH_SIGNALS*MAX_NUM_SENSORS*sizeof(double_complex));
94 pData->W_diffEQ_tmp = malloc1d(MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS*sizeof(double_complex));
95 pData->W_tmp = malloc1d(MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS*sizeof(double_complex));
96
97 /* display related stuff */
98 pData->bN_modal_dB = (float**)calloc2d(HYBRID_BANDS, MAX_SH_ORDER + 1, sizeof(float));
99 pData->bN_inv_dB = (float**)calloc2d(HYBRID_BANDS, MAX_SH_ORDER + 1, sizeof(float));
100 pData->cSH = (float*)calloc1d((HYBRID_BANDS)*(MAX_SH_ORDER + 1),sizeof(float));
101 pData->lSH = (float*)calloc1d((HYBRID_BANDS)*(MAX_SH_ORDER + 1),sizeof(float));
102}
103
105(
106 void ** const phM2sh
107)
108{
109 array2sh_data *pData = (array2sh_data*)(*phM2sh);
110
111 if (pData != NULL) {
112 /* not safe to free memory during evaluation */
113 while (pData->evalStatus == EVAL_STATUS_EVALUATING)
114 SAF_SLEEP(10);
115
116 /* free afSTFT and buffers */
117 if (pData->hSTFT != NULL)
118 afSTFT_destroy(&(pData->hSTFT));
119 free(pData->inputFrameTD);
120 free(pData->SHframeTD);
121 free(pData->inputframeTF);
122 free(pData->SHframeTF);
124
125 /* For diffuse-field equalisation */
126 free(pData->L_diff_fal);
127 free(pData->L_diff);
128 free(pData->E_diff);
129 free(pData->W_diffEQ_tmp);
130 free(pData->W_tmp);
131
132 /* Display stuff */
133 free(pData->bN_modal_dB);
134 free(pData->bN_inv_dB);
135
136 free(pData->progressBarText);
137
138 free(pData->bN);
139 free(pData->cSH);
140 free(pData->lSH);
141
142 free(pData);
143 pData = NULL;
144 *phM2sh = NULL;
145 }
146}
147
149(
150 void * const hA2sh,
151 int sampleRate
152)
153{
154 array2sh_data *pData = (array2sh_data*)(hA2sh);
155
156 pData->fs = sampleRate;
157 afSTFT_getCentreFreqs(pData->hSTFT, (float)pData->fs, HYBRID_BANDS, pData->freqVector);
158 pData->freqVector[0] = pData->freqVector[1]/4.0f; /* avoids NaNs at DC */
159}
160
162(
163 void* const hA2sh
164)
165{
166 array2sh_data *pData = (array2sh_data*)(hA2sh);
167
169 return; /* eval not required */
170
171 /* for progress bar */
173 strcpy(pData->progressBarText,"Initialising evaluation");
174 pData->progressBar0_1 = 0.0f;
175
176 /* Evaluate Encoder */
178
179 /* done! */
180 strcpy(pData->progressBarText,"Done!");
181 pData->progressBar0_1 = 1.0f;
183}
184
186(
187 void * const hA2sh,
188 const float *const * inputs,
189 float* const* const outputs,
190 int nInputs,
191 int nOutputs,
192 int nSamples
193)
194{
195 array2sh_data *pData = (array2sh_data*)(hA2sh);
196 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
197 int ch, i, band, Q, order, nSH;
198 const float_complex calpha = cmplxf(1.0f,0.0f), cbeta = cmplxf(0.0f, 0.0f);
199 CH_ORDER chOrdering;
200 NORM_TYPES norm;
201 float gain_lin;
202
203 /* reinit TFT if needed */
204 array2sh_initTFT(hA2sh);
205
206 /* compute encoding matrix if needed */
207 if (pData->reinitSHTmatrixFLAG) {
208 array2sh_calculate_sht_matrix(hA2sh); /* compute encoding matrix */
209 array2sh_calculate_mag_curves(hA2sh); /* calculate magnitude response curves */
210 pData->reinitSHTmatrixFLAG = 0;
211 }
212
213 /* local copy of user parameters */
214 chOrdering = pData->chOrdering;
215 norm = pData->norm;
216 gain_lin = powf(10.0f, pData->gain_dB/20.0f);
217 Q = arraySpecs->Q;
218 order = pData->order;
219 nSH = (order+1)*(order+1);
220
221 /* processing loop */
222 if ((nSamples == ARRAY2SH_FRAME_SIZE) && (pData->reinitSHTmatrixFLAG==0) ) {
224
225 /* Load time-domain data */
226 for(i=0; i < nInputs; i++)
227 utility_svvcopy(inputs[i], ARRAY2SH_FRAME_SIZE, pData->inputFrameTD[i]);
228 for(; i<Q; i++)
229 memset(pData->inputFrameTD[i], 0, ARRAY2SH_FRAME_SIZE * sizeof(float));
230
231 /* Apply time-frequency transform (TFT) */
233
234 /* Apply spherical harmonic transform (SHT) */
235 for(band=0; band<HYBRID_BANDS; band++){
236 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, TIME_SLOTS, Q, &calpha,
237 pData->W[band], MAX_NUM_SENSORS,
238 FLATTEN2D(pData->inputframeTF[band]), TIME_SLOTS, &cbeta,
239 FLATTEN2D(pData->SHframeTF[band]), TIME_SLOTS);
240 }
241
242 /* inverse-TFT */
244
245 /* account for output channel order */
246 switch(chOrdering){
247 case CH_ACN: /* already ACN, do nothing */ break;
249 }
250
251 /* account for normalisation scheme */
252 switch(norm){
253 case NORM_N3D: /* already N3D, do nothing */ break;
256 }
257
258 /* Apply post-gain */
259 utility_svsmul(FLATTEN2D(pData->SHframeTD), &gain_lin, nSH*ARRAY2SH_FRAME_SIZE, NULL);
260
261 /* Copy to output */
262 for(i = 0; i < SAF_MIN(nSH,nOutputs); i++)
263 utility_svvcopy(pData->SHframeTD[i], ARRAY2SH_FRAME_SIZE, outputs[i]);
264 for(; i < nOutputs; i++)
265 memset(outputs[i], 0, ARRAY2SH_FRAME_SIZE * sizeof(float));
266 }
267 else{
268 for (ch=0; ch < nOutputs; ch++)
269 memset(outputs[ch],0, ARRAY2SH_FRAME_SIZE*sizeof(float));
270 }
271
273}
274
275/* Set Functions */
276
277void array2sh_refreshSettings(void* const hA2sh)
278{
279 array2sh_data *pData = (array2sh_data*)(hA2sh);
280 pData->reinitSHTmatrixFLAG = 1;
282}
283
284void array2sh_setEncodingOrder(void* const hA2sh, int newOrder)
285{
286 array2sh_data *pData = (array2sh_data*)(hA2sh);
287
288 if(pData->new_order != newOrder){
289 pData->new_order = newOrder;
290 pData->reinitSHTmatrixFLAG = 1;
292 }
293 /* FUMA only supports 1st order */
294 if(pData->new_order!=SH_ORDER_FIRST && pData->chOrdering == CH_FUMA)
295 pData->chOrdering = CH_ACN;
296 if(pData->new_order!=SH_ORDER_FIRST && pData->norm == NORM_FUMA)
297 pData->norm = NORM_SN3D;
298}
299
300void array2sh_setRequestEncoderEvalFLAG(void* const hA2sh, int newState)
301{
302 array2sh_data *pData = (array2sh_data*)(hA2sh);
303 pData->evalRequestedFLAG = newState;
304}
305
306void array2sh_setEvalStatus(void* const hA2sh, ARRAY2SH_EVAL_STATUS new_evalStatus)
307{
308 array2sh_data *pData = (array2sh_data*)(hA2sh);
309 if(new_evalStatus==EVAL_STATUS_NOT_EVALUATED){
310 /* Pause until current initialisation is complete */
311 while(pData->evalStatus == EVAL_STATUS_EVALUATING)
312 SAF_SLEEP(10);
313 }
314 pData->evalStatus = new_evalStatus;
315}
316
317void array2sh_setDiffEQpastAliasing(void* const hA2sh, int newState)
318{
319 array2sh_data *pData = (array2sh_data*)(hA2sh);
320 if(pData->enableDiffEQpastAliasing != newState){
321 pData->enableDiffEQpastAliasing = newState;
322 pData->reinitSHTmatrixFLAG = 1;
324 }
325}
326
328{
329 array2sh_data *pData = (array2sh_data*)(hA2sh);
330 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
331
332 array2sh_initArray(arraySpecs,(ARRAY2SH_MICROPHONE_ARRAY_PRESETS)preset, &(pData->new_order), 0);
333 pData->c = (ARRAY2SH_MICROPHONE_ARRAY_PRESETS)preset == MICROPHONE_ARRAY_PRESET_AALTO_HYDROPHONE ? 1484.0f : 343.0f;
334 pData->reinitSHTmatrixFLAG = 1;
336}
337
338void array2sh_setSensorAzi_rad(void* const hA2sh, int index, float newAzi_rad)
339{
340 array2sh_data *pData = (array2sh_data*)(hA2sh);
341 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
342
343 if(arraySpecs->sensorCoords_rad[index][0] != newAzi_rad){
344 arraySpecs->sensorCoords_rad[index][0] = newAzi_rad;
345 arraySpecs->sensorCoords_deg[index][0] = newAzi_rad * (180.0f/SAF_PI);
346 pData->reinitSHTmatrixFLAG = 1;
348 }
349}
350
351void array2sh_setSensorElev_rad(void* const hA2sh, int index, float newElev_rad)
352{
353 array2sh_data *pData = (array2sh_data*)(hA2sh);
354 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
355
356 if(arraySpecs->sensorCoords_rad[index][1] != newElev_rad){
357 arraySpecs->sensorCoords_rad[index][1] = newElev_rad;
358 arraySpecs->sensorCoords_deg[index][1] = newElev_rad * (180.0f/SAF_PI);
359 pData->reinitSHTmatrixFLAG = 1;
361 }
362}
363
364void array2sh_setSensorAzi_deg(void* const hA2sh, int index, float newAzi_deg)
365
366{
367 array2sh_data *pData = (array2sh_data*)(hA2sh);
368 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
369
370 if(arraySpecs->sensorCoords_deg[index][0] != newAzi_deg){
371 arraySpecs->sensorCoords_rad[index][0] = newAzi_deg * (SAF_PI/180.0f);
372 arraySpecs->sensorCoords_deg[index][0] = newAzi_deg;
373 pData->reinitSHTmatrixFLAG = 1;
375 }
376}
377
378void array2sh_setSensorElev_deg(void* const hA2sh, int index, float newElev_deg)
379{
380 array2sh_data *pData = (array2sh_data*)(hA2sh);
381 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
382
383 if(arraySpecs->sensorCoords_deg[index][1] != newElev_deg){
384 arraySpecs->sensorCoords_rad[index][1] = newElev_deg * (SAF_PI/180.0f);
385 arraySpecs->sensorCoords_deg[index][1] = newElev_deg;
386 pData->reinitSHTmatrixFLAG = 1;
388 }
389}
390
391void array2sh_setNumSensors(void* const hA2sh, int newQ)
392{
393 array2sh_data *pData = (array2sh_data*)(hA2sh);
394 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
395 int nSH;
396
397 nSH = (pData->new_order+1)*(pData->new_order+1);
398 if (newQ < nSH){
399 pData->new_order = 1;
400 pData->reinitSHTmatrixFLAG = 1;
402 }
403 if(arraySpecs->Q != newQ){
404 arraySpecs->newQ = newQ;
405 pData->reinitSHTmatrixFLAG = 1;
407 }
408}
409
410void array2sh_setr(void* const hA2sh, float newr)
411{
412 array2sh_data *pData = (array2sh_data*)(hA2sh);
413 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
414
416 if(arraySpecs->r!=newr){
417 arraySpecs->r = newr;
418 pData->reinitSHTmatrixFLAG = 1;
420 }
421}
422
423void array2sh_setR(void* const hA2sh, float newR)
424{
425 array2sh_data *pData = (array2sh_data*)(hA2sh);
426 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
427
429 if(arraySpecs->R!=newR){
430 arraySpecs->R = newR;
431 pData->reinitSHTmatrixFLAG = 1;
433 }
434}
435
436void array2sh_setArrayType(void* const hA2sh, int newType)
437{
438 array2sh_data *pData = (array2sh_data*)(hA2sh);
439 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
440
441 if(arraySpecs->arrayType != (ARRAY2SH_ARRAY_TYPES)newType){
442 arraySpecs->arrayType = (ARRAY2SH_ARRAY_TYPES)newType;
443 pData->reinitSHTmatrixFLAG = 1;
445 }
446}
447
448void array2sh_setWeightType(void* const hA2sh, int newType)
449{
450 array2sh_data *pData = (array2sh_data*)(hA2sh);
451 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
452
453 if(arraySpecs->weightType!=(ARRAY2SH_WEIGHT_TYPES)newType){
454 arraySpecs->weightType = (ARRAY2SH_WEIGHT_TYPES)newType;
455 pData->reinitSHTmatrixFLAG = 1;
457 }
458}
459
460void array2sh_setFilterType(void* const hA2sh, int newType)
461{
462 array2sh_data *pData = (array2sh_data*)(hA2sh);
463
464 if(pData->filterType!=(ARRAY2SH_FILTER_TYPES)newType){
465 pData->filterType = (ARRAY2SH_FILTER_TYPES)newType;
466 pData->reinitSHTmatrixFLAG = 1;
468 }
469}
470
471void array2sh_setRegPar(void* const hA2sh, float newVal)
472{
473 array2sh_data *pData = (array2sh_data*)(hA2sh);
475 if(pData->regPar!=newVal){
476 pData->regPar = newVal;
477 pData->reinitSHTmatrixFLAG = 1;
479 }
480}
481
482void array2sh_setChOrder(void* const hA2sh, int newOrder)
483{
484 array2sh_data *pData = (array2sh_data*)(hA2sh);
485 if((CH_ORDER)newOrder != CH_FUMA || pData->order==SH_ORDER_FIRST)/* FUMA only supports 1st order */
486 pData->chOrdering = (CH_ORDER)newOrder;
487}
488
489void array2sh_setNormType(void* const hA2sh, int newType)
490{
491 array2sh_data *pData = (array2sh_data*)(hA2sh);
492 if((NORM_TYPES)newType != NORM_FUMA || pData->order==SH_ORDER_FIRST)/* FUMA only supports 1st order */
493 pData->norm = (NORM_TYPES)newType;
494}
495
496void array2sh_setc(void* const hA2sh, float newc)
497{
498 array2sh_data *pData = (array2sh_data*)(hA2sh);
500 if(newc!=pData->c){
501 pData->c = newc;
502 pData->reinitSHTmatrixFLAG = 1;
504 }
505}
506
507void array2sh_setGain(void* const hA2sh, float newGain)
508{
509 array2sh_data *pData = (array2sh_data*)(hA2sh);
511}
512
513
514/* Get Functions */
515
517{
518 return ARRAY2SH_FRAME_SIZE;
519}
520
522{
523 array2sh_data *pData = (array2sh_data*)(hA2sh);
524 return pData->evalStatus;
525}
526
528{
529 array2sh_data *pData = (array2sh_data*)(hA2sh);
530 return pData->reinitSHTmatrixFLAG;
531}
532
533float array2sh_getProgressBar0_1(void* const hA2sh)
534{
535 array2sh_data *pData = (array2sh_data*)(hA2sh);
536 return pData->progressBar0_1;
537}
538
539void array2sh_getProgressBarText(void* const hA2sh, char* text)
540{
541 array2sh_data *pData = (array2sh_data*)(hA2sh);
542 memcpy(text, pData->progressBarText, PROGRESSBARTEXT_CHAR_LENGTH*sizeof(char));
543}
544
546{
547 array2sh_data *pData = (array2sh_data*)(hA2sh);
548 return pData->evalRequestedFLAG;
549}
550
551int array2sh_getDiffEQpastAliasing(void* const hA2sh)
552{
553 array2sh_data *pData = (array2sh_data*)(hA2sh);
554 return pData->enableDiffEQpastAliasing;
555}
556
557int array2sh_getEncodingOrder(void* const hA2sh)
558{
559 array2sh_data *pData = (array2sh_data*)(hA2sh);
560 return pData->new_order;
561}
562
563float array2sh_getSensorAzi_rad(void* const hA2sh, int index)
564{
565 array2sh_data *pData = (array2sh_data*)(hA2sh);
566 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
567 return arraySpecs->sensorCoords_rad[index][0];
568}
569
570float array2sh_getSensorElev_rad(void* const hA2sh, int index)
571{
572 array2sh_data *pData = (array2sh_data*)(hA2sh);
573 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
574 return arraySpecs->sensorCoords_rad[index][1];
575}
576
577float array2sh_getSensorAzi_deg(void* const hA2sh, int index)
578{
579 array2sh_data *pData = (array2sh_data*)(hA2sh);
580 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
581 return arraySpecs->sensorCoords_deg[index][0];
582}
583
584float array2sh_getSensorElev_deg(void* const hA2sh, int index)
585{
586 array2sh_data *pData = (array2sh_data*)(hA2sh);
587 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
588 return arraySpecs->sensorCoords_deg[index][1];
589}
590
591int array2sh_getNumSensors(void* const hA2sh)
592{
593 array2sh_data *pData = (array2sh_data*)(hA2sh);
594 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
595 // return arraySpecs->Q;
596 return arraySpecs->newQ; /* return the new Q, incase the plug-in is still waiting for a refresh */
597}
598
600{
601 return MAX_NUM_SENSORS;
602}
603
604int array2sh_getMinNumSensors(void* const hA2sh)
605{
606 array2sh_data *pData = (array2sh_data*)(hA2sh);
607 return (pData->new_order+1)*(pData->new_order+1);
608}
609
610int array2sh_getNSHrequired(void* const hA2sh)
611{
612 array2sh_data *pData = (array2sh_data*)(hA2sh);
613 return (pData->new_order+1)*(pData->new_order+1);
614}
615
616float array2sh_getr(void* const hA2sh)
617{
618 array2sh_data *pData = (array2sh_data*)(hA2sh);
619 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
620 return arraySpecs->r;
621}
622
623float array2sh_getR(void* const hA2sh)
624{
625 array2sh_data *pData = (array2sh_data*)(hA2sh);
626 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
627 return arraySpecs->R;
628}
629
630int array2sh_getArrayType(void* const hA2sh)
631{
632 array2sh_data *pData = (array2sh_data*)(hA2sh);
633 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
634 return (int)arraySpecs->arrayType;
635}
636
637int array2sh_getWeightType(void* const hA2sh)
638{
639 array2sh_data *pData = (array2sh_data*)(hA2sh);
640 array2sh_arrayPars* arraySpecs = (array2sh_arrayPars*)(pData->arraySpecs);
641 return (int)arraySpecs->weightType;
642}
643
644int array2sh_getFilterType(void* const hA2sh)
645{
646 array2sh_data *pData = (array2sh_data*)(hA2sh);
647 return (int)pData->filterType;
648}
649
650float array2sh_getRegPar(void* const hA2sh)
651{
652 array2sh_data *pData = (array2sh_data*)(hA2sh);
653 return pData->regPar;
654}
655
656int array2sh_getChOrder(void* const hA2sh)
657{
658 array2sh_data *pData = (array2sh_data*)(hA2sh);
659 return (int)pData->chOrdering;
660}
661
662int array2sh_getNormType(void* const hA2sh)
663{
664 array2sh_data *pData = (array2sh_data*)(hA2sh);
665 return (int)pData->norm;
666}
667
668float array2sh_getc(void* const hA2sh)
669{
670 array2sh_data *pData = (array2sh_data*)(hA2sh);
671 return pData->c;
672}
673
674float array2sh_getGain(void* const hA2sh)
675{
676 array2sh_data *pData = (array2sh_data*)(hA2sh);
677 return pData->gain_dB;
678}
679
680float* array2sh_getFreqVector(void* const hA2sh, int* nFreqPoints)
681{
682 array2sh_data *pData = (array2sh_data*)(hA2sh);
683 (*nFreqPoints) = HYBRID_BANDS;
684 return &(pData->freqVector[0]);
685}
686
687float** array2sh_getbN_inv(void* const hA2sh, int* nCurves, int* nFreqPoints)
688{
689 array2sh_data *pData = (array2sh_data*)(hA2sh);
690 (*nCurves) = pData->order+1;
691 (*nFreqPoints) = HYBRID_BANDS;
692 return pData->bN_inv_dB;
693}
694
695float** array2sh_getbN_modal(void* const hA2sh, int* nCurves, int* nFreqPoints)
696{
697 array2sh_data *pData = (array2sh_data*)(hA2sh);
698 (*nCurves) = pData->order+1;
699 (*nFreqPoints) = HYBRID_BANDS;
700 return pData->bN_modal_dB;
701}
702
703float* array2sh_getSpatialCorrelation_Handle(void* const hA2sh, int* nCurves, int* nFreqPoints)
704{
705 array2sh_data *pData = (array2sh_data*)(hA2sh);
706 (*nCurves) = pData->order+1;
707 (*nFreqPoints) = HYBRID_BANDS;
708 return pData->cSH;
709}
710
711float* array2sh_getLevelDifference_Handle(void* const hA2sh, int* nCurves, int* nFreqPoints)
712{
713 array2sh_data *pData = (array2sh_data*)(hA2sh);
714 (*nCurves) = pData->order+1;
715 (*nFreqPoints) = HYBRID_BANDS;
716 return pData->lSH;
717}
718
719int array2sh_getSamplingRate(void* const hA2sh)
720{
721 array2sh_data *pData = (array2sh_data*)(hA2sh);
722 return pData->fs;
723}
724
726{
727 return 12*HOP_SIZE;
728}
#define MAX_SH_ORDER
Maximum supported Ambisonic order.
Definition _common.h:52
#define PROGRESSBARTEXT_CHAR_LENGTH
Length of progress bar string.
Definition _common.h:227
@ PROC_STATUS_ONGOING
Codec is processing input audio, and should not be reinitialised at this time.
Definition _common.h:220
@ PROC_STATUS_NOT_ONGOING
Codec is not processing input audio, and may be reinitialised if needed.
Definition _common.h:222
NORM_TYPES
Available Ambisonic normalisation conventions.
Definition _common.h:74
@ NORM_SN3D
Schmidt semi-normalisation (SN3D)
Definition _common.h:76
@ NORM_FUMA
(Legacy) Furse-Malham scaling
Definition _common.h:77
@ NORM_N3D
orthonormalised (N3D)
Definition _common.h:75
CH_ORDER
Available Ambisonic channel ordering conventions.
Definition _common.h:59
@ CH_ACN
Ambisonic Channel Numbering (ACN)
Definition _common.h:60
@ CH_FUMA
(Legacy) Furse-Malham/B-format (WXYZ)
Definition _common.h:61
#define MAX_NUM_SH_SIGNALS
Maximum number of spherical harmonic components/signals supported.
Definition _common.h:239
@ SH_ORDER_FIRST
First-order (4 channels)
Definition _common.h:39
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:186
float array2sh_getR(void *const hA2sh)
Returns the radius of the scatterer, in meters.
Definition array2sh.c:623
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:489
float * array2sh_getSpatialCorrelation_Handle(void *const hA2sh, int *nCurves, int *nFreqPoints)
Returns a pointer to the spatial correlation [1] data.
Definition array2sh.c:703
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:584
float array2sh_getr(void *const hA2sh)
Returns the radius of the array, in meters.
Definition array2sh.c:616
void array2sh_setNumSensors(void *const hA2sh, int newQ)
Sets the number of sensors in the array.
Definition array2sh.c:391
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:687
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:351
void array2sh_setR(void *const hA2sh, float newR)
Sets the radius (in meters) of the scatterer (only for Rigid arrays).
Definition array2sh.c:423
void array2sh_setGain(void *const hA2sh, float newGain)
Sets the amount of post gain to apply after the encoding, in DECIBELS.
Definition array2sh.c:507
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:577
float * array2sh_getFreqVector(void *const hA2sh, int *nFreqPoints)
Returns a pointer to the frequency vector.
Definition array2sh.c:680
void array2sh_destroy(void **const phM2sh)
Destroys an instance of array2sh.
Definition array2sh.c:105
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:471
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:545
int array2sh_getMaxNumSensors(void)
Returns the maximum supported number of sensors which can be in the array.
Definition array2sh.c:599
void array2sh_setArrayType(void *const hA2sh, int newType)
Sets the type of array (see ARRAY2SH_ARRAY_TYPES enum)
Definition array2sh.c:436
int array2sh_getEncodingOrder(void *const hA2sh)
Returns the current encoding order (see SH_ORDERS enum)
Definition array2sh.c:557
float array2sh_getProgressBar0_1(void *const hA2sh)
(Optional) Returns current intialisation/processing progress, between 0..1
Definition array2sh.c:533
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:277
void array2sh_setEncodingOrder(void *const hA2sh, int newOrder)
Sets the encoding order (see SH_ORDERS enum)
Definition array2sh.c:284
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:460
int array2sh_getSamplingRate(void *const hA2sh)
Returns the DAW/Host sample rate.
Definition array2sh.c:719
void array2sh_init(void *const hA2sh, int sampleRate)
Initialises an instance of array2sh with default settings.
Definition array2sh.c:149
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:378
float array2sh_getRegPar(void *const hA2sh)
Returns the value of the regurlisation parameter; the maximum permitted gain provided by the filters,...
Definition array2sh.c:650
void array2sh_setEvalStatus(void *const hA2sh, ARRAY2SH_EVAL_STATUS new_evalStatus)
Sets current eval status (see ARRAY2SH_EVAL_STATUS enum)
Definition array2sh.c:306
int array2sh_getProcessingDelay()
Returns the processing delay in samples (may be used for delay compensation features)
Definition array2sh.c:725
float * array2sh_getLevelDifference_Handle(void *const hA2sh, int *nCurves, int *nFreqPoints)
Returns a pointer to the level-difference [1] data.
Definition array2sh.c:711
int array2sh_getArrayType(void *const hA2sh)
Returns the type of array.
Definition array2sh.c:630
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:327
int array2sh_getNormType(void *const hA2sh)
Returns the Ambisonic normalisation convention currently being usedto decode with,...
Definition array2sh.c:662
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:551
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:695
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:604
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:668
void array2sh_getProgressBarText(void *const hA2sh, char *text)
(Optional) Returns current intialisation/processing progress text
Definition array2sh.c:539
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:496
void array2sh_evalEncoder(void *const hA2sh)
Evaluates the encoder, based on current global/user parameters.
Definition array2sh.c:162
void array2sh_setr(void *const hA2sh, float newr)
Sets the radius of the array.
Definition array2sh.c:410
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:338
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:364
int array2sh_getNSHrequired(void *const hA2sh)
Returns the number of spherical harmonic signals required by the current encoding order: (current_ord...
Definition array2sh.c:610
void array2sh_setWeightType(void *const hA2sh, int newType)
Sets the type of weights to use (see ARRAY2SH_WEIGHT_TYPES enum)
Definition array2sh.c:448
void array2sh_setDiffEQpastAliasing(void *const hA2sh, int newState)
Analyses what the theoretical spatial aliasing frequency is, and conducts diffuse-field equalisation ...
Definition array2sh.c:317
float array2sh_getGain(void *const hA2sh)
Returns the amount of post gain to apply after the encoding, in DECIBELS.
Definition array2sh.c:674
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:482
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:563
int array2sh_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition array2sh.c:516
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:570
int array2sh_getChOrder(void *const hA2sh)
Returns the Ambisonic channel ordering convention currently being used to decode with,...
Definition array2sh.c:656
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:644
int array2sh_getWeightType(void *const hA2sh)
Returns the type of weights to use see ARRAY2SH_WEIGHT_TYPES enum.
Definition array2sh.c:637
int array2sh_getReinitSHTmatrixFLAG(void *const hA2sh)
Returns 0 if SHT is not be reinitialised, 1: if it is.
Definition array2sh.c:527
int array2sh_getNumSensors(void *const hA2sh)
Returns the number of sensors in the array.
Definition array2sh.c:591
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:300
ARRAY2SH_EVAL_STATUS array2sh_getEvalStatus(void *const hA2sh)
Returns current eval status (see ARRAY2SH_EVAL_STATUS enum)
Definition array2sh.c:521
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
#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_calculate_mag_curves(void *const hA2sh)
Computes the magnitude responses of the equalisation filters; the absolute values of the regularised ...
void array2sh_initArray(void *const hPars, ARRAY2SH_MICROPHONE_ARRAY_PRESETS preset, int *arrayOrder, int firstInitFlag)
Intialises an instance of a struct based on a preset, which contains the array configuration data.
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.
float sensorCoords_deg[MAX_NUM_SENSORS][2]
Sensor directions in degrees.
int Q
Current number of sensors.
float R
radius of scatterer (only for rigid arrays)
ARRAY2SH_ARRAY_TYPES arrayType
see ARRAY2SH_ARRAY_TYPES
ARRAY2SH_WEIGHT_TYPES weightType
see ARRAY2SH_WEIGHT_TYPES
int newQ
New number of sensors (current value replaced by this after next re-init)
float sensorCoords_rad[MAX_NUM_SENSORS][2]
Sensor directions in radians.
float r
radius of sensors
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.
int fs
sampling rate, hz
float progressBar0_1
Current (re)initialisation progress, between [0..1].
float freqVector[HYBRID_BANDS]
frequency vector
double_complex * bN
Temp vector for the modal coefficients.
PROC_STATUS procStatus
see PROC_STATUS
char * progressBarText
Current (re)initialisation step, string.
float c
speed of sound, m/s
void * hSTFT
filterbank handle
float ** bN_modal_dB
modal responses / no regulaisation; HYBRID_BANDS x (MAX_SH_ORDER +1)
void * arraySpecs
array configuration
float gain_dB
post gain, dB
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.
ARRAY2SH_EVAL_STATUS evalStatus
see ARRAY2SH_EVAL_STATUS
float * cSH
spatial correlation; HYBRID_BANDS x 1
int reinitSHTmatrixFLAG
0: do not reinit; 1: reinit;
int new_order
new encoding order (current value will be replaced by this after next re-init)
float ** bN_inv_dB
modal responses / with regularisation; HYBRID_BANDS x (MAX_SH_ORDER +1)
float regPar
regularisation upper gain limit, dB;
float * lSH
level difference; HYBRID_BANDS x 1
NORM_TYPES norm
Ambisonic normalisation convention (see NORM_TYPES)
ARRAY2SH_FILTER_TYPES filterType
encoding filter approach
int enableDiffEQpastAliasing
0: disabled, 1: enabled
int order
current encoding order
float_complex W[HYBRID_BANDS][MAX_NUM_SH_SIGNALS][MAX_NUM_SENSORS]
Encoding weights.
int evalRequestedFLAG
0: do not reinit; 1: reinit;
CH_ORDER chOrdering
Ambisonic channel order convention (see CH_ORDER)