SAF
Loading...
Searching...
No Matches
powermap.c
Go to the documentation of this file.
1/*
2 * Copyright 2016-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
31
32#include "powermap.h"
33#include "powermap_internal.h"
34
36(
37 void ** const phPm
38)
39{
41 *phPm = (void*)pData;
42 int n, i, band;
43
44 /* Default user parameters */
46 for(band=0; band<HYBRID_BANDS; band++){
47 pData->analysisOrderPerBand[band] = pData->masterOrder;
48 pData->pmapEQ[band] = 1.0f;
49 }
50 pData->covAvgCoeff = 0.0f;
51 pData->pmapAvgCoeff = 0.25f;
52 pData->nSources = 1;
53 pData->pmap_mode = PM_MODE_MUSIC;
54 pData->HFOVoption = HFOV_360;
56 pData->chOrdering = CH_ACN;
57 pData->norm = NORM_SN3D;
58
60 pData->SHframeTD = (float**)malloc2d(MAX_NUM_SH_SIGNALS, POWERMAP_FRAME_SIZE, sizeof(float));
61 pData->SHframeTF = (float_complex***)malloc3d(HYBRID_BANDS, MAX_NUM_SH_SIGNALS, TIME_SLOTS, sizeof(float_complex));
62
63 /* codec data */
65 powermap_codecPars* pars = pData->pars;
66 pars->interp_dirs_deg = NULL;
67 for(n=0; n<MAX_SH_ORDER; n++){
68 pars->Y_grid[n] = NULL;
69 pars->Y_grid_cmplx[n] = NULL;
70 }
71 pars->interp_table = NULL;
72
73 /* internal */
74 pData->isFirstInit = 1;
75 pData->progressBar0_1 = 0.0f;
77 strcpy(pData->progressBarText,"");
80 pData->dispWidth = 140;
81
82 /* display */
83 pData->pmap = NULL;
84 pData->prev_pmap = NULL;
85 for(i=0; i<NUM_DISP_SLOTS; i++)
86 pData->pmap_grid[i] = NULL;
87 pData->pmapReady = 0;
88 pData->recalcPmap = 1;
89
90 /* set FIFO buffer */
91 pData->fs = 48000.0f;
92 pData->FIFO_idx = 0;
93 memset(pData->inFIFO, 0, MAX_NUM_SH_SIGNALS*POWERMAP_FRAME_SIZE*sizeof(float));
94}
95
97(
98 void ** const phPm
99)
100{
101 powermap_data *pData = (powermap_data*)(*phPm);
102 powermap_codecPars* pars;
103 int i;
104
105 if (pData != NULL) {
106 /* not safe to free memory during intialisation/processing loop */
107 while (pData->codecStatus == CODEC_STATUS_INITIALISING ||
109 SAF_SLEEP(10);
110 }
111
112 pars = pData->pars;
113
114 /* free afSTFT and buffers */
115 afSTFT_destroy(&(pData->hSTFT));
116 free(pData->SHframeTD);
117 free(pData->SHframeTF);
118
119 free(pData->pmap);
120 free(pData->prev_pmap);
121 for(i=0; i<NUM_DISP_SLOTS; i++)
122 free(pData->pmap_grid[i]);
123 free(pars->interp_dirs_deg);
124 for(i=0; i<MAX_SH_ORDER; i++){
125 free(pars->Y_grid[i]);
126 free(pars->Y_grid_cmplx[i]);
127 }
128 free(pars->interp_table);
129 free(pData->pars);
130 free(pData->progressBarText);
131 free(pData);
132 pData = NULL;
133 *phPm = NULL;
134 }
135}
136
138(
139 void * const hPm,
140 float sampleRate
141)
142{
143 powermap_data *pData = (powermap_data*)(hPm);
144 powermap_codecPars* pars = pData->pars;
145
146 pData->fs = sampleRate;
147
148 /* specify frequency vector and determine the number of bands */
149 afSTFT_getCentreFreqs(pData->hSTFT, sampleRate, HYBRID_BANDS, pData->freqVector);
150
151 /* intialise parameters */
152 memset(pData->Cx, 0 , MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS*HYBRID_BANDS*sizeof(float_complex));
153 if(pData->prev_pmap!=NULL)
154 memset(pData->prev_pmap, 0, pars->grid_nDirs*sizeof(float));
155 pData->pmapReady = 0;
156 pData->dispSlotIdx = 0;
157}
158
160(
161 void* const hPm
162)
163{
164 powermap_data *pData = (powermap_data*)(hPm);
165
167 return; /* re-init not required, or already happening */
168 while (pData->procStatus == PROC_STATUS_ONGOING){
169 /* re-init required, but we need to wait for the current processing loop to end */
170 pData->codecStatus = CODEC_STATUS_INITIALISING; /* indicate that we want to init */
171 SAF_SLEEP(10);
172 }
173
174 /* for progress bar */
176 strcpy(pData->progressBarText,"Initialising");
177 pData->progressBar0_1 = 0.5f;
178
179 powermap_initTFT(hPm);
180 powermap_initAna(hPm);
181
182 /* done! */
183 strcpy(pData->progressBarText,"Done!");
184 pData->progressBar0_1 = 1.0f;
186}
187
189(
190 void * const hPm,
191 const float *const * inputs,
192 int nInputs,
193 int nSamples,
194 int isPlaying
195)
196{
197 powermap_data *pData = (powermap_data*)(hPm);
198 powermap_codecPars* pars = pData->pars;
199 int s, i, j, ch, band, nSH_order, order_band, nSH_maxOrder, maxOrder;
200 float C_grp_trace, pmapEQ_band;
201 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
202 float_complex new_Cx[MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS];
203 float_complex C_grp[MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS];
204
205 /* local parameters */
206 int analysisOrderPerBand[HYBRID_BANDS];
207 int nSources, masterOrder, nSH;
208 float covAvgCoeff, pmapAvgCoeff;
209 float pmapEQ[HYBRID_BANDS];
210 NORM_TYPES norm;
211 CH_ORDER chOrdering;
212 POWERMAP_MODES pmap_mode;
213 memcpy(analysisOrderPerBand, pData->analysisOrderPerBand, HYBRID_BANDS*sizeof(int));
214 memcpy(pmapEQ, pData->pmapEQ, HYBRID_BANDS*sizeof(float));
215 norm = pData->norm;
216 chOrdering = pData->chOrdering;
217 nSources = pData->nSources;
218 covAvgCoeff = SAF_MIN(pData->covAvgCoeff, MAX_COV_AVG_COEFF);
219 pmapAvgCoeff = pData->pmapAvgCoeff;
220 pmap_mode = pData->pmap_mode;
221 masterOrder = pData->masterOrder;
222 nSH = (masterOrder+1)*(masterOrder+1);
223
224 /* Loop over all samples */
225 for(s=0; s<nSamples; s++){
226 /* Load input signals into inFIFO buffer */
227 for(ch=0; ch<SAF_MIN(nInputs,nSH); ch++)
228 pData->inFIFO[ch][pData->FIFO_idx] = inputs[ch][s];
229 for(; ch<nSH; ch++) /* Zero any channels that were not given */
230 pData->inFIFO[ch][pData->FIFO_idx] = 0.0f;
231
232 /* Increment buffer index */
233 pData->FIFO_idx++;
234
235 /* Process frame if inFIFO is full and codec is ready for it */
236 if (pData->FIFO_idx >= POWERMAP_FRAME_SIZE && (pData->codecStatus == CODEC_STATUS_INITIALISED) && isPlaying ) {
237 pData->FIFO_idx = 0;
239
240 /* Load time-domain data */
241 for(ch=0; ch<nSH; ch++)
242 memcpy(pData->SHframeTD[ch], pData->inFIFO[ch], POWERMAP_FRAME_SIZE*sizeof(float));
243
244 /* account for input channel order */
245 switch(chOrdering){
246 case CH_ACN: /* already ACN */ break; /* Otherwise, convert to ACN... */
248 }
249
250 /* account for input normalisation scheme */
251 switch(norm){
252 case NORM_N3D: /* already in N3D, do nothing */ break; /* Otherwise, convert to N3D... */
255 }
256
257 /* apply the time-frequency transform */
259
260 /* Update covarience matrix per band */
261 for(band=0; band<HYBRID_BANDS; band++){
262 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasConjTrans, nSH, nSH, TIME_SLOTS, &calpha,
263 FLATTEN2D(pData->SHframeTF[band]), TIME_SLOTS,
264 FLATTEN2D(pData->SHframeTF[band]), TIME_SLOTS, &cbeta,
265 new_Cx, nSH);
266
267 /* average over time */
268 cblas_sscal(nSH*nSH*2, covAvgCoeff, (float*)pData->Cx[band], 1);
269 cblas_saxpy(nSH*nSH*2, 1.0f-covAvgCoeff, (float*)new_Cx, 1, (float*)pData->Cx[band], 1);
270 }
271
272 /* update the powermap */
273 if(pData->recalcPmap==1){
274 pData->recalcPmap = 0;
275 pData->pmapReady = 0;
276
277 /* determine maximum analysis order */
278 maxOrder = 1;
279 for(i=0; i<HYBRID_BANDS; i++)
280 maxOrder = SAF_MAX(maxOrder, SAF_MIN(analysisOrderPerBand[i], masterOrder));
281 nSH_maxOrder = (maxOrder+1)*(maxOrder+1);
282
283 /* group covarience matrices */
284 memset(C_grp, 0, nSH_maxOrder*nSH_maxOrder*sizeof(float_complex));
285 for (band=0; band<HYBRID_BANDS; band++){
286 order_band = SAF_MAX(SAF_MIN(pData->analysisOrderPerBand[band], masterOrder),1);
287 nSH_order = (order_band+1)*(order_band+1);
288 pmapEQ_band = SAF_MIN(SAF_MAX(pmapEQ[band], 0.0f), 2.0f);
289 for(i=0; i<nSH_order; i++)
290 for(j=0; j<nSH_order; j++)
291 C_grp[i*nSH_maxOrder+j] = ccaddf(C_grp[i*nSH_maxOrder+j], crmulf(pData->Cx[band][i*nSH+j], 1e3f*pmapEQ_band));
292 }
293
294 /* generate powermap */
295 C_grp_trace = 0.0f;
296 for(i=0; i<nSH_maxOrder; i++)
297 C_grp_trace+=crealf(C_grp[i*nSH_maxOrder+ i]);
298 switch(pmap_mode){
299 default:
300 case PM_MODE_PWD:
301 generatePWDmap(maxOrder, (float_complex*)C_grp, pars->Y_grid_cmplx[maxOrder-1], pars->grid_nDirs, pData->pmap);
302 break;
303
304 case PM_MODE_MVDR:
305 if(C_grp_trace>1e-8f)
306 generateMVDRmap(maxOrder, (float_complex*)C_grp, pars->Y_grid_cmplx[maxOrder-1], pars->grid_nDirs, 8.0f, pData->pmap, NULL);
307 else
308 memset(pData->pmap, 0, pars->grid_nDirs*sizeof(float));
309 break;
310
312 if(C_grp_trace>1e-8f)
313 generateCroPaCLCMVmap(maxOrder, (float_complex*)C_grp, pars->Y_grid_cmplx[maxOrder-1], pars->grid_nDirs, 8.0f, 0.0f, pData->pmap);
314 else
315 memset(pData->pmap, 0, pars->grid_nDirs*sizeof(float));
316 break;
317
318 case PM_MODE_MUSIC:
319 if(C_grp_trace>1e-8f)
320 generateMUSICmap(maxOrder, (float_complex*)C_grp, pars->Y_grid_cmplx[maxOrder-1], nSources, pars->grid_nDirs, 0, pData->pmap);
321 else
322 memset(pData->pmap, 0, pars->grid_nDirs*sizeof(float));
323 break;
324
326 if(C_grp_trace>1e-8f)
327 generateMUSICmap(maxOrder, (float_complex*)C_grp, pars->Y_grid_cmplx[maxOrder-1], nSources, pars->grid_nDirs, 1, pData->pmap);
328 else
329 memset(pData->pmap, 0, pars->grid_nDirs*sizeof(float));
330 break;
331
332 case PM_MODE_MINNORM:
333 if(C_grp_trace>1e-8f)
334 generateMinNormMap(maxOrder, (float_complex*)C_grp, pars->Y_grid_cmplx[maxOrder-1], nSources, pars->grid_nDirs, 0, pData->pmap);
335 else
336 memset(pData->pmap, 0, pars->grid_nDirs*sizeof(float));
337 break;
338
340 if(C_grp_trace>1e-8f)
341 generateMinNormMap(maxOrder, (float_complex*)C_grp, pars->Y_grid_cmplx[maxOrder-1], nSources, pars->grid_nDirs, 1, pData->pmap);
342 else
343 memset(pData->pmap, 0, pars->grid_nDirs*sizeof(float));
344 break;
345 }
346
347 /* average powermap over time */
348 for(i=0; i<pars->grid_nDirs; i++)
349 pData->pmap[i] = (1.0f-pmapAvgCoeff) * (pData->pmap[i] )+ pmapAvgCoeff * (pData->prev_pmap[i]);
350 utility_svvcopy(pData->pmap, pars->grid_nDirs, pData->prev_pmap);
351
352 /* interpolate powermap */
353 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, pars->interp_nDirs, 1, pars->grid_nDirs, 1.0f,
354 pars->interp_table, pars->grid_nDirs,
355 pData->pmap, 1, 0.0f,
356 pData->pmap_grid[pData->dispSlotIdx], 1);
357
358 /* ascertain minimum and maximum values for powermap colour scaling */
359 int ind;
360 utility_siminv(pData->pmap_grid[pData->dispSlotIdx], pars->interp_nDirs, &ind);
361 pData->pmap_grid_minVal = pData->pmap_grid[pData->dispSlotIdx][ind];
362 utility_simaxv(pData->pmap_grid[pData->dispSlotIdx], pars->interp_nDirs, &ind);
363 pData->pmap_grid_maxVal = pData->pmap_grid[pData->dispSlotIdx][ind];
364
365 /* normalise the powermap to 0..1 */
366 for(i=0; i<pars->interp_nDirs; i++)
367 pData->pmap_grid[pData->dispSlotIdx][i] = (pData->pmap_grid[pData->dispSlotIdx][i]-pData->pmap_grid_minVal)/(pData->pmap_grid_maxVal-pData->pmap_grid_minVal+1e-11f);
368
369 /* signify that the powermap in current slot is ready for plotting */
370 pData->dispSlotIdx++;
371 if(pData->dispSlotIdx>=NUM_DISP_SLOTS)
372 pData->dispSlotIdx = 0;
373 pData->pmapReady = 1;
374 }
375 }
376 else if(pData->FIFO_idx >= POWERMAP_FRAME_SIZE){
377 /* reset FIFO_idx if codec was not ready */
378 pData->FIFO_idx = 0;
379 }
380 }
381
383}
384
385/* SETS */
386
391
392void powermap_setPowermapMode(void* const hPm, int newMode)
393{
394 powermap_data *pData = (powermap_data*)(hPm);
395 powermap_codecPars* pars = pData->pars;
396 pData->pmap_mode = (POWERMAP_MODES)newMode;
397 if(pData->prev_pmap!=NULL)
398 memset(pData->prev_pmap, 0, pars->grid_nDirs*sizeof(float));
399}
400
401void powermap_setMasterOrder(void* const hPm, int newValue)
402{
403 powermap_data *pData = (powermap_data*)(hPm);
404 if(pData->new_masterOrder != newValue){
405 pData->new_masterOrder = newValue;
407 }
408 /* FUMA only supports 1st order */
409 if(pData->new_masterOrder!=SH_ORDER_FIRST && pData->chOrdering == CH_FUMA)
410 pData->chOrdering = CH_ACN;
411 if(pData->new_masterOrder!=SH_ORDER_FIRST && pData->norm == NORM_FUMA)
412 pData->norm = NORM_SN3D;
413}
414
415void powermap_setCovAvgCoeff(void* const hPm, float newAvg)
416{
417 powermap_data *pData = (powermap_data*)(hPm);
418 pData->covAvgCoeff = SAF_MIN(SAF_MAX(0.0f, newAvg), 0.99999999f);
419}
420
421void powermap_setNumSources(void* const hPm, int newValue)
422{
423 powermap_data *pData = (powermap_data*)(hPm);
424 pData->nSources = newValue;
425}
426
427void powermap_setSourcePreset(void* const hPm, int newPresetID)
428{
429 powermap_data *pData = (powermap_data*)(hPm);
430 int band, rangeIdx, curOrder, reverse;
431
432 rangeIdx = 0;
433 curOrder = 1;
434 reverse = 0;
435 switch(newPresetID){
436 case MIC_PRESET_IDEAL:
437 /* Ideal SH should have maximum order per frequency */
438 for(band=0; band<HYBRID_BANDS; band++)
439 pData->analysisOrderPerBand[band] = pData->new_masterOrder;
440 break;
441
442 /* In the case of real microphone arrays, the analysis order should be frequency dependent
443 * and the frequencies above the spatial-aliasing limit should be EQ's out. */
444 case MIC_PRESET_ZYLIA:
445 for(band=0; band<HYBRID_BANDS; band++){
446 if(rangeIdx<2*(__Zylia_maxOrder-1)){
447 if(pData->freqVector[band]>__Zylia_freqRange[rangeIdx]){
448 if(!reverse)
449 curOrder++;
450 else
451 curOrder--;
452 reverse = (curOrder == __Zylia_maxOrder) || (reverse) ? 1 : 0;
453 rangeIdx++;
454 }
455 }
456 pData->analysisOrderPerBand[band] = SAF_MIN(pData->new_masterOrder,curOrder);
457 if(pData->freqVector[band] > __Zylia_freqRange[(__Zylia_maxOrder-1)*2 - 1])
458 pData->pmapEQ[band] = 0.0f;
459 }
460 break;
461
462 case MIC_PRESET_EIGENMIKE32:
463 for(band=0; band<HYBRID_BANDS; band++){
464 if(rangeIdx<2*(__Eigenmike32_maxOrder-1)){
465 if(pData->freqVector[band]>__Eigenmike32_freqRange[rangeIdx]){
466 if(!reverse)
467 curOrder++;
468 else
469 curOrder--;
470 reverse = (curOrder == __Eigenmike32_maxOrder) || (reverse) ? 1 : 0;
471 rangeIdx++;
472 }
473 }
474 pData->analysisOrderPerBand[band] = SAF_MIN(pData->new_masterOrder,curOrder);
475 if(pData->freqVector[band] > __Eigenmike32_freqRange[(__Eigenmike32_maxOrder-1)*2 - 1])
476 pData->pmapEQ[band] = 0.0f;
477 }
478 break;
479
480 case MIC_PRESET_DTU_MIC:
481 for(band=0; band<HYBRID_BANDS; band++){
482 if(rangeIdx<2*(__DTU_mic_maxOrder-1)){
483 if(pData->freqVector[band]>__DTU_mic_freqRange[rangeIdx]){
484 if(!reverse)
485 curOrder++;
486 else
487 curOrder--;
488 reverse = (curOrder == __DTU_mic_maxOrder) || (reverse) ? 1 : 0;
489 rangeIdx++;
490 }
491 }
492 pData->analysisOrderPerBand[band] = SAF_MIN(pData->new_masterOrder,curOrder);
493 if(pData->freqVector[band] > __DTU_mic_freqRange[(__DTU_mic_maxOrder-1)*2 - 1])
494 pData->pmapEQ[band] = 0.0f;
495 }
496 break;
497 }
498}
499
500void powermap_setAnaOrder(void * const hPm, int newValue, int bandIdx)
501{
502 powermap_data *pData = (powermap_data*)(hPm);
503 pData->analysisOrderPerBand[bandIdx] = SAF_MIN(SAF_MAX(newValue,1), pData->new_masterOrder);
504}
505
506void powermap_setAnaOrderAllBands(void * const hPm, int newValue)
507{
508 powermap_data *pData = (powermap_data*)(hPm);
509 int band;
510
511 for(band=0; band<HYBRID_BANDS; band++)
512 pData->analysisOrderPerBand[band] = SAF_MIN(SAF_MAX(newValue,1), pData->new_masterOrder);
513}
514
515void powermap_setPowermapEQ(void * const hPm, float newValue, int bandIdx)
516{
517 powermap_data *pData = (powermap_data*)(hPm);
518 pData->pmapEQ[bandIdx] = newValue;
519}
520
521void powermap_setPowermapEQAllBands(void * const hPm, float newValue)
522{
523 powermap_data *pData = (powermap_data*)(hPm);
524 int band;
525
526 for(band=0; band<HYBRID_BANDS; band++)
527 pData->pmapEQ[band] = newValue;
528}
529
530void powermap_setChOrder(void* const hPm, int newOrder)
531{
532 powermap_data *pData = (powermap_data*)(hPm);
533 if((CH_ORDER)newOrder != CH_FUMA || pData->new_masterOrder==SH_ORDER_FIRST)/* FUMA only supports 1st order */
534 pData->chOrdering = (CH_ORDER)newOrder;
535}
536
537void powermap_setNormType(void* const hPm, int newType)
538{
539 powermap_data *pData = (powermap_data*)(hPm);
540 if((NORM_TYPES)newType != NORM_FUMA || pData->new_masterOrder==SH_ORDER_FIRST)/* FUMA only supports 1st order */
541 pData->norm = (NORM_TYPES)newType;
542}
543
544void powermap_setDispFOV(void* const hPm, int newOption)
545{
546 powermap_data *pData = (powermap_data*)(hPm);
547 if(pData->HFOVoption != (HFOV_OPTIONS)newOption){
548 pData->HFOVoption = (HFOV_OPTIONS)newOption;
550 }
551}
552
553void powermap_setAspectRatio(void* const hPm, int newOption)
554{
555 powermap_data *pData = (powermap_data*)(hPm);
556 if(pData->aspectRatioOption != (ASPECT_RATIO_OPTIONS)newOption){
557 pData->aspectRatioOption = (ASPECT_RATIO_OPTIONS)newOption;
559 }
560}
561
562void powermap_setPowermapAvgCoeff(void* const hPm, float newValue)
563{
564 powermap_data *pData = (powermap_data*)(hPm);
565 pData->pmapAvgCoeff = SAF_MIN(SAF_MAX(0.0f, newValue), 0.99999999f);
566}
567
568void powermap_requestPmapUpdate(void* const hPm)
569{
570 powermap_data *pData = (powermap_data*)(hPm);
571 pData->recalcPmap = 1;
572}
573
574/* GETS */
575
577{
578 return POWERMAP_FRAME_SIZE;
579}
580
582{
583 powermap_data *pData = (powermap_data*)(hPm);
584 return pData->codecStatus;
585}
586
587float powermap_getProgressBar0_1(void* const hPm)
588{
589 powermap_data *pData = (powermap_data*)(hPm);
590 return pData->progressBar0_1;
591}
592
593void powermap_getProgressBarText(void* const hPm, char* text)
594{
595 powermap_data *pData = (powermap_data*)(hPm);
596 memcpy(text, pData->progressBarText, PROGRESSBARTEXT_CHAR_LENGTH*sizeof(char));
597}
598
599int powermap_getMasterOrder(void* const hPm)
600{
601 powermap_data *pData = (powermap_data*)(hPm);
602 return pData->new_masterOrder;
603}
604
605int powermap_getPowermapMode(void* const hPm)
606{
607 powermap_data *pData = (powermap_data*)(hPm);
608 return (int)pData->pmap_mode;
609}
610
611int powermap_getSamplingRate(void* const hPm)
612{
613 powermap_data *pData = (powermap_data*)(hPm);
614 return (int)(pData->fs+0.5f);
615}
616
617float powermap_getCovAvgCoeff(void* const hPm)
618{
619 powermap_data *pData = (powermap_data*)(hPm);
620 return pData->covAvgCoeff;
621}
622
623float powermap_getPowermapEQ(void * const hPm, int bandIdx)
624{
625 powermap_data *pData = (powermap_data*)(hPm);
626 return pData->pmapEQ[bandIdx];
627}
628
629float powermap_getPowermapEQAllBands(void * const hPm)
630{
631 powermap_data *pData = (powermap_data*)(hPm);
632 return pData->pmapEQ[0];
633}
634
636(
637 void* const hPm,
638 float** pX_vector,
639 float** pY_values,
640 int* pNpoints
641)
642{
643 powermap_data *pData = (powermap_data*)(hPm);
644 (*pX_vector) = &(pData->freqVector[0]);
645 (*pY_values) = &(pData->pmapEQ[0]);
646 (*pNpoints) = HYBRID_BANDS;
647}
648
649int powermap_getAnaOrder(void * const hPm, int bandIdx)
650{
651 powermap_data *pData = (powermap_data*)(hPm);
652 return pData->analysisOrderPerBand[bandIdx];
653}
654
655int powermap_getAnaOrderAllBands(void * const hPm)
656{
657 powermap_data *pData = (powermap_data*)(hPm);
658 return pData->analysisOrderPerBand[0];
659}
660
662(
663 void* const hPm,
664 float** pX_vector,
665 int** pY_values,
666 int* pNpoints
667)
668{
669 powermap_data *pData = (powermap_data*)(hPm);
670 (*pX_vector) = &(pData->freqVector[0]);
671 (*pY_values) = &(pData->analysisOrderPerBand[0]);
672 (*pNpoints) = HYBRID_BANDS;
673}
674
676{
677 return HYBRID_BANDS;
678}
679
680int powermap_getNSHrequired(void* const hPm)
681{
682 powermap_data *pData = (powermap_data*)(hPm);
683 return (pData->new_masterOrder+1)*(pData->new_masterOrder+1);
684}
685
686int powermap_getChOrder(void* const hPm)
687{
688 powermap_data *pData = (powermap_data*)(hPm);
689 return (int)pData->chOrdering;
690}
691
692int powermap_getNormType(void* const hPm)
693{
694 powermap_data *pData = (powermap_data*)(hPm);
695 return (int)pData->norm;
696}
697
698int powermap_getNumSources(void* const hPm)
699{
700 powermap_data *pData = (powermap_data*)(hPm);
701 return pData->nSources;
702}
703
704int powermap_getDispFOV(void* const hPm)
705{
706 powermap_data *pData = (powermap_data*)(hPm);
707 return (int)pData->HFOVoption;
708}
709
710int powermap_getAspectRatio(void* const hPm)
711{
712 powermap_data *pData = (powermap_data*)(hPm);
713 return (int)pData->aspectRatioOption;
714}
715
716float powermap_getPowermapAvgCoeff(void* const hPm)
717{
718 powermap_data *pData = (powermap_data*)(hPm);
719 return pData->pmapAvgCoeff;
720}
721
722int powermap_getPmap(void* const hPm, float** grid_dirs, float** pmap, int* nDirs,int* pmapWidth, int* hfov, int* aspectRatio) //TODO: hfov and aspectRatio should be float, if 16:9 etc options are added
723{
724 powermap_data *pData = (powermap_data*)(hPm);
725 powermap_codecPars* pars = pData->pars;
726 if((pData->codecStatus == CODEC_STATUS_INITIALISED) && pData->pmapReady){
727 (*grid_dirs) = pars->interp_dirs_deg;
728 (*pmap) = pData->pmap_grid[pData->dispSlotIdx-1 < 0 ? NUM_DISP_SLOTS-1 : pData->dispSlotIdx-1];
729 (*nDirs) = pars->interp_nDirs;
730 (*pmapWidth) = pData->dispWidth;
731 switch(pData->HFOVoption){
732 default:
733 case HFOV_360:
734 (*hfov) = 360;
735 break;
736 }
737 switch(pData->aspectRatioOption){
738 default:
739 case ASPECT_RATIO_2_1:
740 (*aspectRatio) = 2;
741 break;
742 }
743 }
744 return pData->pmapReady;
745}
746
748{
749 return POWERMAP_FRAME_SIZE + 12*HOP_SIZE;
750}
751
#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
HFOV_OPTIONS
Available horizontal field-of-view (FOV) options.
Definition _common.h:179
@ HFOV_360
360 degrees
Definition _common.h:180
NORM_TYPES
Available Ambisonic normalisation conventions.
Definition _common.h:74
@ NORM_SN3D
Schmidt semi-normalisation (SN3D)
Definition _common.h:76
@ NORM_FUMA
(Legacy) Furse-Malham scaling
Definition _common.h:77
@ NORM_N3D
orthonormalised (N3D)
Definition _common.h:75
CH_ORDER
Available Ambisonic channel ordering conventions.
Definition _common.h:59
@ CH_ACN
Ambisonic Channel Numbering (ACN)
Definition _common.h:60
@ CH_FUMA
(Legacy) Furse-Malham/B-format (WXYZ)
Definition _common.h:61
#define MAX_NUM_SH_SIGNALS
Maximum number of spherical harmonic components/signals supported.
Definition _common.h:239
@ SH_ORDER_FIRST
First-order (4 channels)
Definition _common.h:39
CODEC_STATUS
Current status of the codec.
Definition _common.h:201
@ CODEC_STATUS_NOT_INITIALISED
Codec has not yet been initialised, or the codec configuration has changed.
Definition _common.h:204
@ CODEC_STATUS_INITIALISED
Codec is initialised and ready to process input audio.
Definition _common.h:202
@ CODEC_STATUS_INITIALISING
Codec is currently being initialised, input audio should not be processed.
Definition _common.h:207
ASPECT_RATIO_OPTIONS
Available aspect ratios.
Definition _common.h:188
@ ASPECT_RATIO_2_1
ASPECT_RATIO_2_1 - 2:1.
Definition _common.h:189
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_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
@ 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.
#define NUM_DISP_SLOTS
Number of display slots.
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
void generateMinNormMap(int order, float_complex *Cx, float_complex *Y_grid, int nSources, int nGrid_dirs, int logScaleFlag, float *pmap)
Generates an activity-map based on the sub-space minimum-norm (MinNorm) method.
Definition saf_sh.c:1917
void generateMVDRmap(int order, float_complex *Cx, float_complex *Y_grid, int nGrid_dirs, float regPar, float *pmap, float_complex *w_MVDR_out)
Generates a powermap based on the energy of adaptive Minimum-Variance Distortion-less Response (MVDR)...
Definition saf_sh.c:1699
void generateMUSICmap(int order, float_complex *Cx, float_complex *Y_grid, int nSources, int nGrid_dirs, int logScaleFlag, float *pmap)
Generates an activity-map based on the sub-space multiple-signal classification (MUSIC) method.
Definition saf_sh.c:1869
void generatePWDmap(int order, float_complex *Cx, float_complex *Y_grid, int nGrid_dirs, float *pmap)
Generates a powermap based on the energy of a plane-wave decomposition (PWD) (i.e.
Definition saf_sh.c:1657
void generateCroPaCLCMVmap(int order, float_complex *Cx, float_complex *Y_grid, int nGrid_dirs, float regPar, float lambda, float *pmap)
(EXPERIMENTAL) Generates a powermap utilising the CroPaC LCMV post-filter described in [1]
Definition saf_sh.c:1765
#define SAF_MAX(a, b)
Returns the maximum of the two values.
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.
const float __Eigenmike32_freqRange[6]
Sensor array frequency ranges for each SH order, for the Eigenmike32 (should only be used as a rough ...
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 utility_siminv(const float *a, const int len, int *index)
Single-precision, index of minimum absolute value in a vector, i.e.
void utility_simaxv(const float *a, const int len, int *index)
Single-precision, index of maximum absolute value in a vector, 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 *** 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
int powermap_getNormType(void *const hPm)
Returns the Ambisonic normalisation convention currently being usedto decode with,...
Definition powermap.c:692
void powermap_refreshSettings(void *const hPm)
Sets all intialisation flags to 1; re-initialising all settings/variables as powermap is currently co...
Definition powermap.c:387
void powermap_setChOrder(void *const hPm, int newOrder)
Sets the Ambisonic channel ordering convention to decode with, in order to match the convention emplo...
Definition powermap.c:530
int powermap_getAnaOrder(void *const hPm, int bandIdx)
Returns the input/analysis order for one specific frequency band.
Definition powermap.c:649
int powermap_getNumberOfBands(void)
Returns the number of frequency bands used for the analysis.
Definition powermap.c:675
int powermap_getPowermapMode(void *const hPm)
Returns the powermap/activity-map mode to employed for the analysis see POWERMAP_MODES enum.
Definition powermap.c:605
float powermap_getPowermapAvgCoeff(void *const hPm)
Returns the current activity-map averaging coefficient, 0..1.
Definition powermap.c:716
int powermap_getAnaOrderAllBands(void *const hPm)
Returns the input/analysis order for the first frequency band.
Definition powermap.c:655
void powermap_setNormType(void *const hPm, int newType)
Sets the Ambisonic normalisation convention to decode with, in order to match with the convention emp...
Definition powermap.c:537
float powermap_getProgressBar0_1(void *const hPm)
(Optional) Returns current intialisation/processing progress, between 0..1
Definition powermap.c:587
void powermap_setAspectRatio(void *const hPm, int newOption)
Sets the visualisation display window aspect-ratio (see ASPECT_RATIO_OPTIONS enum)
Definition powermap.c:553
void powermap_setNumSources(void *const hPm, int newValue)
Sets the number of sources present in the input sound scene.
Definition powermap.c:421
void powermap_setPowermapAvgCoeff(void *const hPm, float newValue)
Sets the activity-map averaging coefficient, 0..1.
Definition powermap.c:562
int powermap_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition powermap.c:576
void powermap_setCovAvgCoeff(void *const hPm, float newAvg)
Sets the covariance matrix averaging coefficient, 0..1.
Definition powermap.c:415
int powermap_getChOrder(void *const hPm)
Returns the Ambisonic channel ordering convention currently being used to decode with,...
Definition powermap.c:686
float powermap_getPowermapEQAllBands(void *const hPm)
Returns the weighting coefficient for the first frequency band.
Definition powermap.c:629
int powermap_getNumSources(void *const hPm)
Returns the number of sources present in the input sound scene.
Definition powermap.c:698
void powermap_setSourcePreset(void *const hPm, int newPresetID)
Sets an input preset; the microphone/hyrophone array used to capture the input signals,...
Definition powermap.c:427
void powermap_initCodec(void *const hPm)
Intialises the codec variables, based on current global/user parameters.
Definition powermap.c:160
int powermap_getPmap(void *const hPm, float **grid_dirs, float **pmap, int *nDirs, int *pmapWidth, int *hfov, int *aspectRatio)
Returns the latest computed activity-map if it is ready.
Definition powermap.c:722
void powermap_destroy(void **const phPm)
Destroys an instance of the powermap.
Definition powermap.c:97
void powermap_setMasterOrder(void *const hPm, int newValue)
Sets the maximum input/analysis order (see SH_ORDERS enum)
Definition powermap.c:401
void powermap_init(void *const hPm, float sampleRate)
Initialises an instance of powermap with default settings.
Definition powermap.c:138
void powermap_setAnaOrder(void *const hPm, int newValue, int bandIdx)
Sets the input/analysis order for one specific frequency band index.
Definition powermap.c:500
int powermap_getAspectRatio(void *const hPm)
Returns the current visualisation display window aspect-ratio (see ASPECT_RATIO_OPTIONS enum)
Definition powermap.c:710
void powermap_requestPmapUpdate(void *const hPm)
Informs powermap that it should compute a new activity-map at its own convenience,...
Definition powermap.c:568
void powermap_setPowermapMode(void *const hPm, int newMode)
Sets the powermap/activity-map approach, (see POWERMAP_MODES enum)
Definition powermap.c:392
void powermap_setPowermapEQAllBands(void *const hPm, float newValue)
Sets the weighting coefficient for all frequency bands.
Definition powermap.c:521
void powermap_getProgressBarText(void *const hPm, char *text)
(Optional) Returns current intialisation/processing progress text
Definition powermap.c:593
void powermap_analysis(void *const hPm, const float *const *inputs, int nInputs, int nSamples, int isPlaying)
Analyses the input spherical harmonic signals to generate an activity-map.
Definition powermap.c:189
void powermap_create(void **const phPm)
Creates an instance of the powermap.
Definition powermap.c:36
int powermap_getMasterOrder(void *const hPm)
Returns the current maximum analysis/input order (see SH_ORDERS enum)
Definition powermap.c:599
float powermap_getPowermapEQ(void *const hPm, int bandIdx)
Returns the weighting coefficient for a particular frequency band index, allowing one to "equalise" t...
Definition powermap.c:623
void powermap_setDispFOV(void *const hPm, int newOption)
Sets the visualisation display window horizontal field-of-view (FOV) (see HFOV_OPTIONS enum)
Definition powermap.c:544
int powermap_getDispFOV(void *const hPm)
Returns the current visualisation display window horizontal field-of-view (FOV) (see HFOV_OPTIONS enu...
Definition powermap.c:704
void powermap_getPowermapEQHandle(void *const hPm, float **pX_vector, float **pY_values, int *pNpoints)
Returns the weighting coefficient for all frequency bands.
Definition powermap.c:636
void powermap_setAnaOrderAllBands(void *const hPm, int newValue)
Sets the input/analysis order for all frequency bands.
Definition powermap.c:506
int powermap_getProcessingDelay(void)
Returns the processing delay in samples (may be used for delay compensation features)
Definition powermap.c:747
int powermap_getSamplingRate(void *const hPm)
Returns the current sampling rate, in Hz.
Definition powermap.c:611
void powermap_getAnaOrderHandle(void *const hPm, float **pX_vector, int **pY_values, int *pNpoints)
Returns the input/analysis order for all frequency bands.
Definition powermap.c:662
int powermap_getNSHrequired(void *const hPm)
Returns the number of spherical harmonic signals required by the current analysis order: (current_ord...
Definition powermap.c:680
void powermap_setPowermapEQ(void *const hPm, float newValue, int bandIdx)
Sets the weighting coefficient for a particular frequency band, allowing one to "equalise" the activi...
Definition powermap.c:515
CODEC_STATUS powermap_getCodecStatus(void *const hPm)
Returns current codec status (see CODEC_STATUS enum)
Definition powermap.c:581
float powermap_getCovAvgCoeff(void *const hPm)
Returns the current covariance averaging coefficient value, in Hz.
Definition powermap.c:617
A sound-field visualiser, which utilises spherical harmonic signals as input; note this code is a rem...
POWERMAP_MODES
Available power-map/activity-map options.
Definition powermap.h:58
@ PM_MODE_PWD
Activity-map based on the energy of hyper-cardioid [plane-wave decomposition (PWD)] beamformers.
Definition powermap.h:59
@ PM_MODE_MVDR
Activity-map based on the energy of minimum- variance distortionless response (MVDR) beamformers.
Definition powermap.h:61
@ PM_MODE_MINNORM
Activity-map based on the sub-space method: minimum-norm (Min-Norm)
Definition powermap.h:71
@ PM_MODE_MINNORM_LOG
Same as PM_MODE_MINNORM, but log(out_values)
Definition powermap.h:73
@ PM_MODE_MUSIC_LOG
Same as PM_MODE_MUSIC, but log(out_values)
Definition powermap.h:70
@ PM_MODE_CROPAC_LCMV
Experimental!
Definition powermap.h:64
@ PM_MODE_MUSIC
Activity-map based on the sub-space method: multiple signal classification (MUSIC)
Definition powermap.h:68
void powermap_setCodecStatus(void *const hPm, CODEC_STATUS newStatus)
Sets codec status (see CODEC_STATUS enum)
void powermap_initTFT(void *const hPm)
Initialise the filterbank used by powermap.
void powermap_initAna(void *const hPm)
Intialises the codec variables, based on current global/user parameters.
A sound-field visualiser, which utilises spherical harmonic signals as input; note this code is a rem...
#define MAX_COV_AVG_COEFF
Maximum supported covariance averaging coefficient.
#define POWERMAP_FRAME_SIZE
Framesize, in time-domain samples.
Contains variables for scanning grids, and beamforming.
float_complex * Y_grid_cmplx[MAX_SH_ORDER]
real SH basis (complex datatype); MAX_NUM_SH_SIGNALS x grid_nDirs
float * interp_dirs_deg
2D rectangular window interpolation directions, in degrees; FLAT: interp_nDirs x 2
float * interp_table
Spherical->2D interpolation table; FLAT: interp_nDirs x grid_nDirs.
int grid_nDirs
Number of scanning directions.
float * Y_grid[MAX_SH_ORDER]
real SH basis (real datatype); MAX_NUM_SH_SIGNALS x grid_nDirs
int interp_nDirs
Number of interpolation directions.
Main structure for powermap.
float pmapAvgCoeff
Powermap averaging coefficient, [0..1].
powermap_codecPars * pars
codec parameters
float fs
Host sample rate, in Hz.
CH_ORDER chOrdering
Ambisonic channel order convention (see CH_ORDER)
int dispWidth
Number of pixels on the horizontal in the 2D interpolated powermap image.
float_complex *** SHframeTF
time-frequency domain SH input frame; HYBRID_BANDS x MAX_NUM_SH_SIGNALS x TIME_SLOTS
float freqVector[HYBRID_BANDS]
Frequency vector (filterbank centre frequencies)
float inFIFO[MAX_NUM_SH_SIGNALS][POWERMAP_FRAME_SIZE]
Input FIFO buffer.
POWERMAP_MODES pmap_mode
see POWERMAP_MODES
PROC_STATUS procStatus
see PROC_STATUS
int pmapReady
0: powermap not started yet, 1: powermap is ready for plotting
float progressBar0_1
Current (re)initialisation progress, between [0..1].
float covAvgCoeff
Covariance matrix averaging coefficient, [0..1].
float * prev_pmap
grid_nDirs x 1
float pmapEQ[HYBRID_BANDS]
Equalisation/weights per band.
int new_masterOrder
New maximum/master SH analysis order (current value will be replaced by this after next re-init)
float pmap_grid_minVal
Current minimum value in pmap (used to normalise [0..1])
int recalcPmap
set this to 1 to generate a new powermap
HFOV_OPTIONS HFOVoption
see HFOV_OPTIONS
CODEC_STATUS codecStatus
see CODEC_STATUS
int FIFO_idx
FIFO buffer index.
int masterOrder
Current maximum/master SH analysis order.
float * pmap
grid_nDirs x 1
float ** SHframeTD
time-domain SH input frame; MAX_NUM_SH_SIGNALS x POWERMAP_FRAME_SIZE
ASPECT_RATIO_OPTIONS aspectRatioOption
see ASPECT_RATIO_OPTIONS
int dispSlotIdx
Current display slot.
float_complex Cx[HYBRID_BANDS][MAX_NUM_SH_SIGNALS *MAX_NUM_SH_SIGNALS]
covariance matrices per band
NORM_TYPES norm
Ambisonic normalisation convention (see NORM_TYPES)
float pmap_grid_maxVal
Current maximum value in pmap (used to normalise [0..1])
int nSources
Current number of sources (used for MUSIC)
float * pmap_grid[NUM_DISP_SLOTS]
powermap interpolated to grid; interp_nDirs x 1
int analysisOrderPerBand[HYBRID_BANDS]
SH analysis order per frequency band.
char * progressBarText
Current (re)initialisation step, string.
void * hSTFT
afSTFT handle