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
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.666f;
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->progressBar0_1 = 0.0f;
76 strcpy(pData->progressBarText,"");
79 pData->dispWidth = 140;
80
81 /* display */
82 pData->pmap = NULL;
83 pData->prev_pmap = NULL;
84 for(i=0; i<NUM_DISP_SLOTS; i++)
85 pData->pmap_grid[i] = NULL;
86 pData->pmapReady = 0;
87 pData->recalcPmap = 1;
88
89 /* set FIFO buffer */
90 pData->fs = 48000.0f;
91 pData->FIFO_idx = 0;
92 memset(pData->inFIFO, 0, MAX_NUM_SH_SIGNALS*POWERMAP_FRAME_SIZE*sizeof(float));
93}
94
96(
97 void ** const phPm
98)
99{
100 powermap_data *pData = (powermap_data*)(*phPm);
101 powermap_codecPars* pars;
102 int i;
103
104 if (pData != NULL) {
105 /* not safe to free memory during intialisation/processing loop */
106 while (pData->codecStatus == CODEC_STATUS_INITIALISING ||
108 SAF_SLEEP(10);
109 }
110
111 pars = pData->pars;
112
113 /* free afSTFT and buffers */
114 afSTFT_destroy(&(pData->hSTFT));
115 free(pData->SHframeTD);
116 free(pData->SHframeTF);
117
118 free(pData->pmap);
119 free(pData->prev_pmap);
120 for(i=0; i<NUM_DISP_SLOTS; i++)
121 free(pData->pmap_grid[i]);
122 free(pars->interp_dirs_deg);
123 for(i=0; i<MAX_SH_ORDER; i++){
124 free(pars->Y_grid[i]);
125 free(pars->Y_grid_cmplx[i]);
126 }
127 free(pars->interp_table);
128 free(pData->pars);
129 free(pData->progressBarText);
130 free(pData);
131 pData = NULL;
132 *phPm = NULL;
133 }
134}
135
137(
138 void * const hPm,
139 float sampleRate
140)
141{
142 powermap_data *pData = (powermap_data*)(hPm);
143 powermap_codecPars* pars = pData->pars;
144
145 pData->fs = sampleRate;
146
147 /* specify frequency vector and determine the number of bands */
148 afSTFT_getCentreFreqs(pData->hSTFT, sampleRate, HYBRID_BANDS, pData->freqVector);
149
150 /* intialise parameters */
151 memset(pData->Cx, 0 , MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS*HYBRID_BANDS*sizeof(float_complex));
152 if(pData->prev_pmap!=NULL)
153 memset(pData->prev_pmap, 0, pars->grid_nDirs*sizeof(float));
154 pData->pmapReady = 0;
155 pData->dispSlotIdx = 0;
156}
157
159(
160 void* const hPm
161)
162{
163 powermap_data *pData = (powermap_data*)(hPm);
164
166 return; /* re-init not required, or already happening */
167 while (pData->procStatus == PROC_STATUS_ONGOING){
168 /* re-init required, but we need to wait for the current processing loop to end */
169 pData->codecStatus = CODEC_STATUS_INITIALISING; /* indicate that we want to init */
170 SAF_SLEEP(10);
171 }
172
173 /* for progress bar */
175 strcpy(pData->progressBarText,"Initialising");
176 pData->progressBar0_1 = 0.0f;
177
178 powermap_initTFT(hPm);
179 powermap_initAna(hPm);
180
181 /* done! */
182 strcpy(pData->progressBarText,"Done!");
183 pData->progressBar0_1 = 1.0f;
185}
186
188(
189 void * const hPm,
190 const float *const * inputs,
191 int nInputs,
192 int nSamples,
193 int isPlaying
194)
195{
196 powermap_data *pData = (powermap_data*)(hPm);
197 powermap_codecPars* pars = pData->pars;
198 int s, i, j, ch, band, nSH_order, order_band, nSH_maxOrder, maxOrder;
199 float C_grp_trace, pmapEQ_band;
200 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
201 float_complex new_Cx[MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS];
202 float_complex C_grp[MAX_NUM_SH_SIGNALS*MAX_NUM_SH_SIGNALS];
203
204 /* local parameters */
205 int analysisOrderPerBand[HYBRID_BANDS];
206 int nSources, masterOrder, nSH;
207 float covAvgCoeff, pmapAvgCoeff;
208 float pmapEQ[HYBRID_BANDS];
209 NORM_TYPES norm;
210 CH_ORDER chOrdering;
211 POWERMAP_MODES pmap_mode;
212 memcpy(analysisOrderPerBand, pData->analysisOrderPerBand, HYBRID_BANDS*sizeof(int));
213 memcpy(pmapEQ, pData->pmapEQ, HYBRID_BANDS*sizeof(float));
214 norm = pData->norm;
215 chOrdering = pData->chOrdering;
216 nSources = pData->nSources;
217 covAvgCoeff = SAF_MIN(pData->covAvgCoeff, MAX_COV_AVG_COEFF);
218 pmapAvgCoeff = pData->pmapAvgCoeff;
219 pmap_mode = pData->pmap_mode;
220 masterOrder = pData->masterOrder;
221 nSH = (masterOrder+1)*(masterOrder+1);
222
223 /* Loop over all samples */
224 for(s=0; s<nSamples; s++){
225 /* Load input signals into inFIFO buffer */
226 for(ch=0; ch<SAF_MIN(nInputs,nSH); ch++)
227 pData->inFIFO[ch][pData->FIFO_idx] = inputs[ch][s];
228 for(; ch<nSH; ch++) /* Zero any channels that were not given */
229 pData->inFIFO[ch][pData->FIFO_idx] = 0.0f;
230
231 /* Increment buffer index */
232 pData->FIFO_idx++;
233
234 /* Process frame if inFIFO is full and codec is ready for it */
235 if (pData->FIFO_idx >= POWERMAP_FRAME_SIZE && (pData->codecStatus == CODEC_STATUS_INITIALISED) && isPlaying ) {
236 pData->FIFO_idx = 0;
238
239 /* Load time-domain data */
240 for(ch=0; ch<nSH; ch++)
241 memcpy(pData->SHframeTD[ch], pData->inFIFO[ch], POWERMAP_FRAME_SIZE*sizeof(float));
242
243 /* account for input channel order */
244 switch(chOrdering){
245 case CH_ACN: /* already ACN */ break; /* Otherwise, convert to ACN... */
247 }
248
249 /* account for input normalisation scheme */
250 switch(norm){
251 case NORM_N3D: /* already in N3D, do nothing */ break; /* Otherwise, convert to N3D... */
254 }
255
256 /* apply the time-frequency transform */
258
259 /* Update covarience matrix per band */
260 for(band=0; band<HYBRID_BANDS; band++){
261 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasConjTrans, nSH, nSH, TIME_SLOTS, &calpha,
262 FLATTEN2D(pData->SHframeTF[band]), TIME_SLOTS,
263 FLATTEN2D(pData->SHframeTF[band]), TIME_SLOTS, &cbeta,
264 new_Cx, nSH);
265
266 /* average over time */
267 cblas_sscal(nSH*nSH*2, covAvgCoeff, (float*)pData->Cx[band], 1);
268 cblas_saxpy(nSH*nSH*2, 1.0f-covAvgCoeff, (float*)new_Cx, 1, (float*)pData->Cx[band], 1);
269 }
270
271 /* update the powermap */
272 if(pData->recalcPmap==1){
273 pData->recalcPmap = 0;
274 pData->pmapReady = 0;
275
276 /* determine maximum analysis order */
277 maxOrder = 1;
278 for(i=0; i<HYBRID_BANDS; i++)
279 maxOrder = SAF_MAX(maxOrder, SAF_MIN(analysisOrderPerBand[i], masterOrder));
280 nSH_maxOrder = (maxOrder+1)*(maxOrder+1);
281
282 /* group covarience matrices */
283 memset(C_grp, 0, nSH_maxOrder*nSH_maxOrder*sizeof(float_complex));
284 for (band=0; band<HYBRID_BANDS; band++){
285 order_band = SAF_MAX(SAF_MIN(pData->analysisOrderPerBand[band], masterOrder),1);
286 nSH_order = (order_band+1)*(order_band+1);
287 pmapEQ_band = SAF_MIN(SAF_MAX(pmapEQ[band], 0.0f), 2.0f);
288 for(i=0; i<nSH_order; i++)
289 for(j=0; j<nSH_order; j++)
290 C_grp[i*nSH_maxOrder+j] = ccaddf(C_grp[i*nSH_maxOrder+j], crmulf(pData->Cx[band][i*nSH+j], 1e3f*pmapEQ_band));
291 }
292
293 /* generate powermap */
294 C_grp_trace = 0.0f;
295 for(i=0; i<nSH_maxOrder; i++)
296 C_grp_trace+=crealf(C_grp[i*nSH_maxOrder+ i]);
297 switch(pmap_mode){
298 default:
299 case PM_MODE_PWD:
300 generatePWDmap(maxOrder, (float_complex*)C_grp, pars->Y_grid_cmplx[maxOrder-1], pars->grid_nDirs, pData->pmap);
301 break;
302
303 case PM_MODE_MVDR:
304 if(C_grp_trace>1e-8f)
305 generateMVDRmap(maxOrder, (float_complex*)C_grp, pars->Y_grid_cmplx[maxOrder-1], pars->grid_nDirs, 8.0f, pData->pmap, NULL);
306 else
307 memset(pData->pmap, 0, pars->grid_nDirs*sizeof(float));
308 break;
309
311 if(C_grp_trace>1e-8f)
312 generateCroPaCLCMVmap(maxOrder, (float_complex*)C_grp, pars->Y_grid_cmplx[maxOrder-1], pars->grid_nDirs, 8.0f, 0.0f, pData->pmap);
313 else
314 memset(pData->pmap, 0, pars->grid_nDirs*sizeof(float));
315 break;
316
317 case PM_MODE_MUSIC:
318 if(C_grp_trace>1e-8f)
319 generateMUSICmap(maxOrder, (float_complex*)C_grp, pars->Y_grid_cmplx[maxOrder-1], nSources, pars->grid_nDirs, 0, pData->pmap);
320 else
321 memset(pData->pmap, 0, pars->grid_nDirs*sizeof(float));
322 break;
323
325 if(C_grp_trace>1e-8f)
326 generateMUSICmap(maxOrder, (float_complex*)C_grp, pars->Y_grid_cmplx[maxOrder-1], nSources, pars->grid_nDirs, 1, pData->pmap);
327 else
328 memset(pData->pmap, 0, pars->grid_nDirs*sizeof(float));
329 break;
330
331 case PM_MODE_MINNORM:
332 if(C_grp_trace>1e-8f)
333 generateMinNormMap(maxOrder, (float_complex*)C_grp, pars->Y_grid_cmplx[maxOrder-1], nSources, pars->grid_nDirs, 0, pData->pmap);
334 else
335 memset(pData->pmap, 0, pars->grid_nDirs*sizeof(float));
336 break;
337
339 if(C_grp_trace>1e-8f)
340 generateMinNormMap(maxOrder, (float_complex*)C_grp, pars->Y_grid_cmplx[maxOrder-1], nSources, pars->grid_nDirs, 1, pData->pmap);
341 else
342 memset(pData->pmap, 0, pars->grid_nDirs*sizeof(float));
343 break;
344 }
345
346 /* average powermap over time */
347 for(i=0; i<pars->grid_nDirs; i++)
348 pData->pmap[i] = (1.0f-pmapAvgCoeff) * (pData->pmap[i] )+ pmapAvgCoeff * (pData->prev_pmap[i]);
349 utility_svvcopy(pData->pmap, pars->grid_nDirs, pData->prev_pmap);
350
351 /* interpolate powermap */
352 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, pars->interp_nDirs, 1, pars->grid_nDirs, 1.0f,
353 pars->interp_table, pars->grid_nDirs,
354 pData->pmap, 1, 0.0f,
355 pData->pmap_grid[pData->dispSlotIdx], 1);
356
357 /* ascertain minimum and maximum values for powermap colour scaling */
358 int ind;
359 utility_siminv(pData->pmap_grid[pData->dispSlotIdx], pars->interp_nDirs, &ind);
360 pData->pmap_grid_minVal = pData->pmap_grid[pData->dispSlotIdx][ind];
361 utility_simaxv(pData->pmap_grid[pData->dispSlotIdx], pars->interp_nDirs, &ind);
362 pData->pmap_grid_maxVal = pData->pmap_grid[pData->dispSlotIdx][ind];
363
364 /* normalise the powermap to 0..1 */
365 for(i=0; i<pars->interp_nDirs; i++)
366 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);
367
368 /* signify that the powermap in current slot is ready for plotting */
369 pData->dispSlotIdx++;
370 if(pData->dispSlotIdx>=NUM_DISP_SLOTS)
371 pData->dispSlotIdx = 0;
372 pData->pmapReady = 1;
373 }
374 }
375 else if(pData->FIFO_idx >= POWERMAP_FRAME_SIZE){
376 /* reset FIFO_idx if codec was not ready */
377 pData->FIFO_idx = 0;
378 }
379 }
380
382}
383
384/* SETS */
385
390
391void powermap_setPowermapMode(void* const hPm, int newMode)
392{
393 powermap_data *pData = (powermap_data*)(hPm);
394 powermap_codecPars* pars = pData->pars;
395 pData->pmap_mode = (POWERMAP_MODES)newMode;
396 if(pData->prev_pmap!=NULL)
397 memset(pData->prev_pmap, 0, pars->grid_nDirs*sizeof(float));
398}
399
400void powermap_setMasterOrder(void* const hPm, int newValue)
401{
402 powermap_data *pData = (powermap_data*)(hPm);
403 if(pData->new_masterOrder != newValue){
404 pData->new_masterOrder = newValue;
406 }
407 /* FUMA only supports 1st order */
408 if(pData->new_masterOrder!=SH_ORDER_FIRST && pData->chOrdering == CH_FUMA)
409 pData->chOrdering = CH_ACN;
410 if(pData->new_masterOrder!=SH_ORDER_FIRST && pData->norm == NORM_FUMA)
411 pData->norm = NORM_SN3D;
412}
413
414void powermap_setCovAvgCoeff(void* const hPm, float newAvg)
415{
416 powermap_data *pData = (powermap_data*)(hPm);
417 pData->covAvgCoeff = SAF_MIN(SAF_MAX(0.0f, newAvg), 0.99999999f);
418}
419
420void powermap_setNumSources(void* const hPm, int newValue)
421{
422 powermap_data *pData = (powermap_data*)(hPm);
423 pData->nSources = newValue;
424}
425
426void powermap_setSourcePreset(void* const hPm, int newPresetID)
427{
428 powermap_data *pData = (powermap_data*)(hPm);
429 int band, rangeIdx, curOrder, reverse;
430
431 rangeIdx = 0;
432 curOrder = 1;
433 reverse = 0;
434 switch(newPresetID){
435 case MIC_PRESET_IDEAL:
436 /* Ideal SH should have maximum order per frequency */
437 for(band=0; band<HYBRID_BANDS; band++)
438 pData->analysisOrderPerBand[band] = pData->new_masterOrder;
439 break;
440
441 /* In the case of real microphone arrays, the analysis order should be frequency dependent
442 * and the frequencies above the spatial-aliasing limit should be EQ's out. */
443 case MIC_PRESET_ZYLIA:
444 for(band=0; band<HYBRID_BANDS; band++){
445 if(rangeIdx<2*(__Zylia_maxOrder-1)){
446 if(pData->freqVector[band]>__Zylia_freqRange[rangeIdx]){
447 if(!reverse)
448 curOrder++;
449 else
450 curOrder--;
451 reverse = (curOrder == __Zylia_maxOrder) || (reverse) ? 1 : 0;
452 rangeIdx++;
453 }
454 }
455 pData->analysisOrderPerBand[band] = SAF_MIN(pData->new_masterOrder,curOrder);
456 if(pData->freqVector[band] > __Zylia_freqRange[(__Zylia_maxOrder-1)*2 - 1])
457 pData->pmapEQ[band] = 0.0f;
458 }
459 break;
460
461 case MIC_PRESET_EIGENMIKE32:
462 for(band=0; band<HYBRID_BANDS; band++){
463 if(rangeIdx<2*(__Eigenmike32_maxOrder-1)){
464 if(pData->freqVector[band]>__Eigenmike32_freqRange[rangeIdx]){
465 if(!reverse)
466 curOrder++;
467 else
468 curOrder--;
469 reverse = (curOrder == __Eigenmike32_maxOrder) || (reverse) ? 1 : 0;
470 rangeIdx++;
471 }
472 }
473 pData->analysisOrderPerBand[band] = SAF_MIN(pData->new_masterOrder,curOrder);
474 if(pData->freqVector[band] > __Eigenmike32_freqRange[(__Eigenmike32_maxOrder-1)*2 - 1])
475 pData->pmapEQ[band] = 0.0f;
476 }
477 break;
478
479 case MIC_PRESET_DTU_MIC:
480 for(band=0; band<HYBRID_BANDS; band++){
481 if(rangeIdx<2*(__DTU_mic_maxOrder-1)){
482 if(pData->freqVector[band]>__DTU_mic_freqRange[rangeIdx]){
483 if(!reverse)
484 curOrder++;
485 else
486 curOrder--;
487 reverse = (curOrder == __DTU_mic_maxOrder) || (reverse) ? 1 : 0;
488 rangeIdx++;
489 }
490 }
491 pData->analysisOrderPerBand[band] = SAF_MIN(pData->new_masterOrder,curOrder);
492 if(pData->freqVector[band] > __DTU_mic_freqRange[(__DTU_mic_maxOrder-1)*2 - 1])
493 pData->pmapEQ[band] = 0.0f;
494 }
495 break;
496 }
497}
498
499void powermap_setAnaOrder(void * const hPm, int newValue, int bandIdx)
500{
501 powermap_data *pData = (powermap_data*)(hPm);
502 pData->analysisOrderPerBand[bandIdx] = SAF_MIN(SAF_MAX(newValue,1), pData->new_masterOrder);
503}
504
505void powermap_setAnaOrderAllBands(void * const hPm, int newValue)
506{
507 powermap_data *pData = (powermap_data*)(hPm);
508 int band;
509
510 for(band=0; band<HYBRID_BANDS; band++)
511 pData->analysisOrderPerBand[band] = SAF_MIN(SAF_MAX(newValue,1), pData->new_masterOrder);
512}
513
514void powermap_setPowermapEQ(void * const hPm, float newValue, int bandIdx)
515{
516 powermap_data *pData = (powermap_data*)(hPm);
517 pData->pmapEQ[bandIdx] = newValue;
518}
519
520void powermap_setPowermapEQAllBands(void * const hPm, float newValue)
521{
522 powermap_data *pData = (powermap_data*)(hPm);
523 int band;
524
525 for(band=0; band<HYBRID_BANDS; band++)
526 pData->pmapEQ[band] = newValue;
527}
528
529void powermap_setChOrder(void* const hPm, int newOrder)
530{
531 powermap_data *pData = (powermap_data*)(hPm);
532 if((CH_ORDER)newOrder != CH_FUMA || pData->new_masterOrder==SH_ORDER_FIRST)/* FUMA only supports 1st order */
533 pData->chOrdering = (CH_ORDER)newOrder;
534}
535
536void powermap_setNormType(void* const hPm, int newType)
537{
538 powermap_data *pData = (powermap_data*)(hPm);
539 if((NORM_TYPES)newType != NORM_FUMA || pData->new_masterOrder==SH_ORDER_FIRST)/* FUMA only supports 1st order */
540 pData->norm = (NORM_TYPES)newType;
541}
542
543void powermap_setDispFOV(void* const hPm, int newOption)
544{
545 powermap_data *pData = (powermap_data*)(hPm);
546 if(pData->HFOVoption != (HFOV_OPTIONS)newOption){
547 pData->HFOVoption = (HFOV_OPTIONS)newOption;
549 }
550}
551
552void powermap_setAspectRatio(void* const hPm, int newOption)
553{
554 powermap_data *pData = (powermap_data*)(hPm);
555 if(pData->aspectRatioOption != (ASPECT_RATIO_OPTIONS)newOption){
556 pData->aspectRatioOption = (ASPECT_RATIO_OPTIONS)newOption;
558 }
559}
560
561void powermap_setPowermapAvgCoeff(void* const hPm, float newValue)
562{
563 powermap_data *pData = (powermap_data*)(hPm);
564 pData->pmapAvgCoeff = SAF_MIN(SAF_MAX(0.0f, newValue), 0.99999999f);
565}
566
567void powermap_requestPmapUpdate(void* const hPm)
568{
569 powermap_data *pData = (powermap_data*)(hPm);
570 pData->recalcPmap = 1;
571}
572
573/* GETS */
574
576{
577 return POWERMAP_FRAME_SIZE;
578}
579
581{
582 powermap_data *pData = (powermap_data*)(hPm);
583 return pData->codecStatus;
584}
585
586float powermap_getProgressBar0_1(void* const hPm)
587{
588 powermap_data *pData = (powermap_data*)(hPm);
589 return pData->progressBar0_1;
590}
591
592void powermap_getProgressBarText(void* const hPm, char* text)
593{
594 powermap_data *pData = (powermap_data*)(hPm);
595 memcpy(text, pData->progressBarText, PROGRESSBARTEXT_CHAR_LENGTH*sizeof(char));
596}
597
598int powermap_getMasterOrder(void* const hPm)
599{
600 powermap_data *pData = (powermap_data*)(hPm);
601 return pData->new_masterOrder;
602}
603
604int powermap_getPowermapMode(void* const hPm)
605{
606 powermap_data *pData = (powermap_data*)(hPm);
607 return (int)pData->pmap_mode;
608}
609
610int powermap_getSamplingRate(void* const hPm)
611{
612 powermap_data *pData = (powermap_data*)(hPm);
613 return (int)(pData->fs+0.5f);
614}
615
616float powermap_getCovAvgCoeff(void* const hPm)
617{
618 powermap_data *pData = (powermap_data*)(hPm);
619 return pData->covAvgCoeff;
620}
621
622float powermap_getPowermapEQ(void * const hPm, int bandIdx)
623{
624 powermap_data *pData = (powermap_data*)(hPm);
625 return pData->pmapEQ[bandIdx];
626}
627
628float powermap_getPowermapEQAllBands(void * const hPm)
629{
630 powermap_data *pData = (powermap_data*)(hPm);
631 return pData->pmapEQ[0];
632}
633
635(
636 void* const hPm,
637 float** pX_vector,
638 float** pY_values,
639 int* pNpoints
640)
641{
642 powermap_data *pData = (powermap_data*)(hPm);
643 (*pX_vector) = &(pData->freqVector[0]);
644 (*pY_values) = &(pData->pmapEQ[0]);
645 (*pNpoints) = HYBRID_BANDS;
646}
647
648int powermap_getAnaOrder(void * const hPm, int bandIdx)
649{
650 powermap_data *pData = (powermap_data*)(hPm);
651 return pData->analysisOrderPerBand[bandIdx];
652}
653
654int powermap_getAnaOrderAllBands(void * const hPm)
655{
656 powermap_data *pData = (powermap_data*)(hPm);
657 return pData->analysisOrderPerBand[0];
658}
659
661(
662 void* const hPm,
663 float** pX_vector,
664 int** pY_values,
665 int* pNpoints
666)
667{
668 powermap_data *pData = (powermap_data*)(hPm);
669 (*pX_vector) = &(pData->freqVector[0]);
670 (*pY_values) = &(pData->analysisOrderPerBand[0]);
671 (*pNpoints) = HYBRID_BANDS;
672}
673
675{
676 return HYBRID_BANDS;
677}
678
679int powermap_getNSHrequired(void* const hPm)
680{
681 powermap_data *pData = (powermap_data*)(hPm);
682 return (pData->new_masterOrder+1)*(pData->new_masterOrder+1);
683}
684
685int powermap_getChOrder(void* const hPm)
686{
687 powermap_data *pData = (powermap_data*)(hPm);
688 return (int)pData->chOrdering;
689}
690
691int powermap_getNormType(void* const hPm)
692{
693 powermap_data *pData = (powermap_data*)(hPm);
694 return (int)pData->norm;
695}
696
697int powermap_getNumSources(void* const hPm)
698{
699 powermap_data *pData = (powermap_data*)(hPm);
700 return pData->nSources;
701}
702
703int powermap_getDispFOV(void* const hPm)
704{
705 powermap_data *pData = (powermap_data*)(hPm);
706 return (int)pData->HFOVoption;
707}
708
709int powermap_getAspectRatio(void* const hPm)
710{
711 powermap_data *pData = (powermap_data*)(hPm);
712 return (int)pData->aspectRatioOption;
713}
714
715float powermap_getPowermapAvgCoeff(void* const hPm)
716{
717 powermap_data *pData = (powermap_data*)(hPm);
718 return pData->pmapAvgCoeff;
719}
720
721int 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
722{
723 powermap_data *pData = (powermap_data*)(hPm);
724 powermap_codecPars* pars = pData->pars;
725 if((pData->codecStatus == CODEC_STATUS_INITIALISED) && pData->pmapReady){
726 (*grid_dirs) = pars->interp_dirs_deg;
727 (*pmap) = pData->pmap_grid[pData->dispSlotIdx-1 < 0 ? NUM_DISP_SLOTS-1 : pData->dispSlotIdx-1];
728 (*nDirs) = pars->interp_nDirs;
729 (*pmapWidth) = pData->dispWidth;
730 switch(pData->HFOVoption){
731 default:
732 case HFOV_360:
733 (*hfov) = 360;
734 break;
735 }
736 switch(pData->aspectRatioOption){
737 default:
738 case ASPECT_RATIO_2_1:
739 (*aspectRatio) = 2;
740 break;
741 }
742 }
743 return pData->pmapReady;
744}
745
750
#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:691
int powermap_getProcessingDelay()
Returns the processing delay in samples (may be used for delay compensation features)
Definition powermap.c:746
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:386
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:529
int powermap_getAnaOrder(void *const hPm, int bandIdx)
Returns the input/analysis order for one specific frequency band.
Definition powermap.c:648
int powermap_getNumberOfBands(void)
Returns the number of frequency bands used for the analysis.
Definition powermap.c:674
int powermap_getPowermapMode(void *const hPm)
Returns the powermap/activity-map mode to employed for the analysis see POWERMAP_MODES enum.
Definition powermap.c:604
float powermap_getPowermapAvgCoeff(void *const hPm)
Returns the current activity-map averaging coefficient, 0..1.
Definition powermap.c:715
int powermap_getAnaOrderAllBands(void *const hPm)
Returns the input/analysis order for the first frequency band.
Definition powermap.c:654
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:536
float powermap_getProgressBar0_1(void *const hPm)
(Optional) Returns current intialisation/processing progress, between 0..1
Definition powermap.c:586
void powermap_setAspectRatio(void *const hPm, int newOption)
Sets the visualisation display window aspect-ratio (see ASPECT_RATIO_OPTIONS enum)
Definition powermap.c:552
void powermap_setNumSources(void *const hPm, int newValue)
Sets the number of sources present in the input sound scene.
Definition powermap.c:420
void powermap_setPowermapAvgCoeff(void *const hPm, float newValue)
Sets the activity-map averaging coefficient, 0..1.
Definition powermap.c:561
int powermap_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition powermap.c:575
void powermap_setCovAvgCoeff(void *const hPm, float newAvg)
Sets the covariance matrix averaging coefficient, 0..1.
Definition powermap.c:414
int powermap_getChOrder(void *const hPm)
Returns the Ambisonic channel ordering convention currently being used to decode with,...
Definition powermap.c:685
float powermap_getPowermapEQAllBands(void *const hPm)
Returns the weighting coefficient for the first frequency band.
Definition powermap.c:628
int powermap_getNumSources(void *const hPm)
Returns the number of sources present in the input sound scene.
Definition powermap.c:697
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:426
void powermap_initCodec(void *const hPm)
Intialises the codec variables, based on current global/user parameters.
Definition powermap.c:159
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:721
void powermap_destroy(void **const phPm)
Destroys an instance of the powermap.
Definition powermap.c:96
void powermap_setMasterOrder(void *const hPm, int newValue)
Sets the maximum input/analysis order (see SH_ORDERS enum)
Definition powermap.c:400
void powermap_init(void *const hPm, float sampleRate)
Initialises an instance of powermap with default settings.
Definition powermap.c:137
void powermap_setAnaOrder(void *const hPm, int newValue, int bandIdx)
Sets the input/analysis order for one specific frequency band index.
Definition powermap.c:499
int powermap_getAspectRatio(void *const hPm)
Returns the current visualisation display window aspect-ratio (see ASPECT_RATIO_OPTIONS enum)
Definition powermap.c:709
void powermap_requestPmapUpdate(void *const hPm)
Informs powermap that it should compute a new activity-map at its own convenience,...
Definition powermap.c:567
void powermap_setPowermapMode(void *const hPm, int newMode)
Sets the powermap/activity-map approach, (see POWERMAP_MODES enum)
Definition powermap.c:391
void powermap_setPowermapEQAllBands(void *const hPm, float newValue)
Sets the weighting coefficient for all frequency bands.
Definition powermap.c:520
void powermap_getProgressBarText(void *const hPm, char *text)
(Optional) Returns current intialisation/processing progress text
Definition powermap.c:592
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:188
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:598
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:622
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:543
int powermap_getDispFOV(void *const hPm)
Returns the current visualisation display window horizontal field-of-view (FOV) (see HFOV_OPTIONS enu...
Definition powermap.c:703
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:635
void powermap_setAnaOrderAllBands(void *const hPm, int newValue)
Sets the input/analysis order for all frequency bands.
Definition powermap.c:505
int powermap_getSamplingRate(void *const hPm)
Returns the current sampling rate, in Hz.
Definition powermap.c:610
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:661
int powermap_getNSHrequired(void *const hPm)
Returns the number of spherical harmonic signals required by the current analysis order: (current_ord...
Definition powermap.c:679
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:514
CODEC_STATUS powermap_getCodecStatus(void *const hPm)
Returns current codec status (see CODEC_STATUS enum)
Definition powermap.c:580
float powermap_getCovAvgCoeff(void *const hPm)
Returns the current covariance averaging coefficient value, in Hz.
Definition powermap.c:616
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! activity-map based on a linearly- contrained minimum-variance (LCMV) formulation of the...
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