SAF
Loading...
Searching...
No Matches
dirass.c
Go to the documentation of this file.
1/*
2 * Copyright 2019 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
37#include "dirass.h"
38#include "dirass_internal.h"
39
41(
42 void ** const phDir
43)
44{
45 dirass_data* pData = (dirass_data*)malloc1d(sizeof(dirass_data));
46 *phDir = (void*)pData;
47 int i;
48
49 /* Default user parameters */
55 pData->pmapAvgCoeff = 0.666f;
56 pData->minFreq_hz = 100.0f;
57 pData->maxFreq_hz = 8e3f;
58 pData->dispWidth = 120;
59 pData->chOrdering = CH_ACN;
60 pData->norm = NORM_SN3D;
61 pData->HFOVoption = HFOV_360;
63
64 /* codec data */
66 dirass_codecPars* pars = pData->pars;
67 pars->interp_dirs_deg = NULL;
68 pars->interp_dirs_rad = NULL;
69 pars->Y_up = NULL;
70 pars->interp_table = NULL;
71 pars->w = NULL;
72 pars->Cw = NULL;
73 pars->Uw = NULL;
74 pars->Cxyz = NULL;
75 pars->ss = NULL;
76 pars->ssxyz = NULL;
77 pars->est_dirs = NULL;
78 pars->est_dirs_idx = NULL;
79 pars->prev_intensity = NULL;
80 pars->prev_energy = NULL;
81
82 /* internal */
83 pData->progressBar0_1 = 0.0f;
85 strcpy(pData->progressBarText,"");
88
89 /* display */
90 pData->pmap = NULL;
91 for(i=0; i<NUM_DISP_SLOTS; i++)
92 pData->pmap_grid[i] = NULL;
93 pData->pmapReady = 0;
94 pData->recalcPmap = 1;
95
96 /* set FIFO buffers */
97 pData->fs = 48000.0f;
98 pData->FIFO_idx = 0;
99 memset(pData->inFIFO, 0, MAX_NUM_INPUT_SH_SIGNALS*DIRASS_FRAME_SIZE*sizeof(float));
100}
101
103(
104 void ** const phDir
105)
106{
107 dirass_data *pData = (dirass_data*)(*phDir);
108 dirass_codecPars* pars;
109 int i;
110
111 if (pData != NULL) {
112 /* not safe to free memory during intialisation/processing loop */
113 while (pData->codecStatus == CODEC_STATUS_INITIALISING ||
115 SAF_SLEEP(10);
116 }
117
118 if(pData->pmap!=NULL)
119 free(pData->pmap);
120 for(i=0; i<NUM_DISP_SLOTS; i++)
121 free(pData->pmap_grid[i]);
122
123 pars = pData->pars;
124 free(pars->interp_dirs_deg);
125 free(pars->interp_dirs_rad);
126 free(pars->Y_up);
127 free(pars->interp_table);
128 free(pars->ss);
129 free(pars->ssxyz);
130 free(pars->Cxyz);
131 free(pars->w);
132 free(pars->Cw);
133 free(pars->Uw);
134 free(pars->est_dirs);
135 free(pars->est_dirs_idx);
136 free(pars->prev_intensity);
137 free(pars->prev_energy);
138
139 free(pData->pars);
140 free(pData->progressBarText);
141 free(pData);
142 pData = NULL;
143 *phDir = NULL;
144 }
145}
146
148(
149 void * const hDir,
150 float sampleRate
151)
152{
153 dirass_data *pData = (dirass_data*)(hDir);
154 dirass_codecPars* pars = pData->pars;
155
156 pData->fs = sampleRate;
157
158 /* intialise parameters */
159 if(pars->prev_intensity!=NULL)
160 memset(pars->prev_intensity, 0, pars->grid_nDirs*3*sizeof(float));
161 if(pars->prev_energy!=NULL)
162 memset(pars->prev_energy, 0, pars->grid_nDirs*sizeof(float));
163 memset(pData->Wz12_hpf, 0, MAX_NUM_INPUT_SH_SIGNALS*2*sizeof(float));
164 memset(pData->Wz12_lpf, 0, MAX_NUM_INPUT_SH_SIGNALS*2*sizeof(float));
165 pData->pmapReady = 0;
166 pData->dispSlotIdx = 0;
167}
168
170(
171 void* const hDir
172)
173{
174 dirass_data *pData = (dirass_data*)(hDir);
175
177 return; /* re-init not required, or already happening */
178 while (pData->procStatus == PROC_STATUS_ONGOING){
179 /* re-init required, but we need to wait for the current processing loop to end */
180 pData->codecStatus = CODEC_STATUS_INITIALISING; /* indicate that we want to init */
181 SAF_SLEEP(10);
182 }
183
184 /* for progress bar */
186 strcpy(pData->progressBarText,"Initialising");
187 pData->progressBar0_1 = 0.0f;
188
189 dirass_initAna(hDir);
190
191 /* done! */
192 strcpy(pData->progressBarText,"Done!");
193 pData->progressBar0_1 = 1.0f;
195}
196
198(
199 void * const hDir,
200 const float *const * inputs,
201 int nInputs,
202 int nSamples,
203 int isPlaying
204)
205{
206 dirass_data *pData = (dirass_data*)(hDir);
207 dirass_codecPars* pars = pData->pars;
208 int s, i, j, k, ch, sec_nSH, secOrder, nSH, up_nSH;
209 float intensity[3];
210
211 /* local copy of user parameters */
212 int inputOrder, DirAssMode, upscaleOrder;
213 float pmapAvgCoeff, minFreq_hz, maxFreq_hz;
214 NORM_TYPES norm;
215 CH_ORDER chOrdering;
216 norm = pData->norm;
217 chOrdering = pData->chOrdering;
218 pmapAvgCoeff = pData->pmapAvgCoeff;
219 DirAssMode = pData->DirAssMode;
220 upscaleOrder = pData->upscaleOrder;
221 minFreq_hz = pData->minFreq_hz;
222 maxFreq_hz = pData->maxFreq_hz;
223 inputOrder = pData->inputOrder;
224 secOrder = inputOrder-1;
225 nSH = (inputOrder+1)*(inputOrder+1);
226 sec_nSH = (secOrder+1)*(secOrder+1);
227 up_nSH = (upscaleOrder+1)*(upscaleOrder+1);
228
229 /* Loop over all samples */
230 for(s=0; s<nSamples; s++){
231 /* Load input signals into inFIFO buffer */
232 for(ch=0; ch<SAF_MIN(nInputs,nSH); ch++)
233 pData->inFIFO[ch][pData->FIFO_idx] = inputs[ch][s];
234 for(; ch<nSH; ch++) /* Zero any channels that were not given */
235 pData->inFIFO[ch][pData->FIFO_idx] = 0.0f;
236
237 /* Increment buffer index */
238 pData->FIFO_idx++;
239
240 /* Process frame if inFIFO is full and codec is ready for it */
241 if (pData->FIFO_idx >= DIRASS_FRAME_SIZE && (pData->codecStatus == CODEC_STATUS_INITIALISED) && isPlaying) {
242 pData->FIFO_idx = 0;
244
245 /* Load time-domain data */
246 for(ch=0; ch<nSH; ch++)
247 memcpy(pData->SHframeTD[ch],pData->inFIFO[ch], DIRASS_FRAME_SIZE*sizeof(float));
248
249 /* account for input channel order */
250 switch(chOrdering){
251 case CH_ACN: /* already ACN */ break; /* Otherwise, convert to ACN... */
253 }
254
255 /* account for input normalisation scheme */
256 switch(norm){
257 case NORM_N3D: /* already in N3D, do nothing */ break; /* Otherwise, convert to N3D... */
260 }
261
262 /* update the dirass powermap */
263 if(pData->recalcPmap==1){
264 pData->recalcPmap = 0;
265 pData->pmapReady = 0;
266
267 /* filter input signals */
268 float b[3], a[3];
269 biQuadCoeffs(BIQUAD_FILTER_HPF, minFreq_hz, pData->fs, 0.7071f, 0.0f, b, a);
270 for(i=0; i<nSH; i++)
271 applyBiQuadFilter(b, a, pData->Wz12_hpf[i], pData->SHframeTD[i], DIRASS_FRAME_SIZE);
272 biQuadCoeffs(BIQUAD_FILTER_LPF, maxFreq_hz, pData->fs, 0.7071f, 0.0f, b, a);
273 for(i=0; i<nSH; i++)
274 applyBiQuadFilter(b, a, pData->Wz12_lpf[i], pData->SHframeTD[i], DIRASS_FRAME_SIZE);
275
276 /* DoA estimation for each spatially-localised sector */
277 if(DirAssMode==REASS_UPSCALE || DirAssMode==REASS_NEAREST){
278 /* Beamform using the sector patterns */
279 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, pars->grid_nDirs, DIRASS_FRAME_SIZE, sec_nSH, 1.0f,
280 pars->Cw, sec_nSH,
281 (const float*)pData->SHframeTD, DIRASS_FRAME_SIZE, 0.0f,
282 pars->ss, DIRASS_FRAME_SIZE);
283
284 for(i=0; i<pars->grid_nDirs; i++){
285 /* beamforming to get velocity patterns */
286 cblas_sgemm(CblasRowMajor, CblasTrans, CblasNoTrans, 3, DIRASS_FRAME_SIZE, nSH, 1.0f,
287 &(pars->Cxyz[i*nSH*3]), 3,
288 (const float*)pData->SHframeTD, DIRASS_FRAME_SIZE, 0.0f,
289 pars->ssxyz, DIRASS_FRAME_SIZE);
290
291 /* take the sum or mean ss.*ssxyz, to get intensity vector */
292 memset(intensity, 0, 3*sizeof(float));
293 for(k=0; k<3; k++){
294 for(j=0; j<DIRASS_FRAME_SIZE; j++)
295 intensity[k] += pars->ssxyz[k*DIRASS_FRAME_SIZE + j] * pars->ss[i*DIRASS_FRAME_SIZE+j];
296 intensity[k] /= (float)DIRASS_FRAME_SIZE;
297
298 /* average over time */
299 intensity[k] = pmapAvgCoeff * (pars->prev_intensity[i*3+k]) + (1.0f-pmapAvgCoeff) * intensity[k];
300 pars->prev_intensity[i*3+k] = intensity[k];
301 }
302
303 /* extract DoA [azi elev] convention */
304 pars->est_dirs[i*2] = atan2f(intensity[1], intensity[0]);
305 pars->est_dirs[i*2+1] = atan2f(intensity[2], sqrtf(powf(intensity[0], 2.0f) + powf(intensity[1], 2.0f)));
306 if(DirAssMode==REASS_UPSCALE)
307 pars->est_dirs[i*2+1] = SAF_PI/2.0f - pars->est_dirs[i*2+1]; /* convert to inclination */
308 }
309 }
310
311 /* Obtain pmap/upscaled pmap in the case of REASS_MODE_OFF and REASS_UPSCALE modes, respectively.
312 * OR find the nearest display grid indices, corresponding to the DoA estimates, for the REASS_NEAREST mode */
313 switch(DirAssMode) {
314 default:
315 case REASS_MODE_OFF:
316 /* Standard beamformer-based pmap */
317 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, pars->grid_nDirs, DIRASS_FRAME_SIZE, nSH, 1.0f,
318 pars->w, nSH,
319 (const float*)pData->SHframeTD, DIRASS_FRAME_SIZE, 0.0f,
320 pars->ss, DIRASS_FRAME_SIZE);
321
322 /* sum energy over the length of the frame to obtain the pmap */
323 memset(pData->pmap, 0, pars->grid_nDirs *sizeof(float));
324 for(i=0; i<pars->grid_nDirs; i++)
325 for(j=0; j<DIRASS_FRAME_SIZE; j++)
326 pData->pmap[i] += (pars->ss[i*DIRASS_FRAME_SIZE+j])*(pars->ss[i*DIRASS_FRAME_SIZE+j]);
327
328 /* average energy over time */
329 for(i=0; i<pars->grid_nDirs; i++){
330 pData->pmap[i] = pmapAvgCoeff * (pars->prev_energy[i]) + (1.0f-pmapAvgCoeff) * (pData->pmap[i]);
331 pars->prev_energy[i] = pData->pmap[i];
332 }
333
334 /* interpolate the pmap */
335 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, pars->interp_nDirs, 1, pars->grid_nDirs, 1.0f,
336 pars->interp_table, pars->grid_nDirs,
337 pData->pmap, 1, 0.0f,
338 pData->pmap_grid[pData->dispSlotIdx], 1);
339 break;
340
341 case REASS_UPSCALE:
342 /* upscale */
343 getSHreal_recur(upscaleOrder, pars->est_dirs, pars->grid_nDirs, pars->Y_up);
344 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, up_nSH, DIRASS_FRAME_SIZE, pars->grid_nDirs, 1.0f,
345 pars->Y_up, pars->grid_nDirs,
346 pars->ss, DIRASS_FRAME_SIZE, 0.0f,
347 (float*)pData->SHframe_upTD, DIRASS_FRAME_SIZE);
348
349 /* Beamform using the new spatially upscaled frame */
350 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, pars->grid_nDirs, DIRASS_FRAME_SIZE, up_nSH, 1.0f,
351 pars->Uw, up_nSH,
352 (float*)pData->SHframe_upTD, DIRASS_FRAME_SIZE, 0.0f,
353 pars->ss, DIRASS_FRAME_SIZE);
354
355 /* sum energy over the length of the frame to obtain the pmap */
356 memset(pData->pmap, 0, pars->grid_nDirs *sizeof(float));
357 for(i=0; i<pars->grid_nDirs; i++)
358 for(j=0; j<DIRASS_FRAME_SIZE; j++)
359 pData->pmap[i] += (pars->ss[i*DIRASS_FRAME_SIZE+j])*(pars->ss[i*DIRASS_FRAME_SIZE+j]);
360
361 /* average energy over time */
362 for(i=0; i<pars->grid_nDirs; i++){
363 pData->pmap[i] = pmapAvgCoeff * (pars->prev_energy[i]) + (1.0f-pmapAvgCoeff) * (pData->pmap[i]);
364 pars->prev_energy[i] = pData->pmap[i];
365 }
366
367 /* interpolate the pmap */
368 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, pars->interp_nDirs, 1, pars->grid_nDirs, 1.0f,
369 pars->interp_table, pars->grid_nDirs,
370 pData->pmap, 1, 0.0f,
371 pData->pmap_grid[pData->dispSlotIdx], 1);
372 break;
373
374 case REASS_NEAREST:
375 /* Assign the sector energies to the nearest display grid point */
376 findClosestGridPoints(pars->interp_dirs_rad, pars->interp_nDirs, pars->est_dirs, pars->grid_nDirs, 0, pars->est_dirs_idx, NULL, NULL);
377 memset(pData->pmap_grid[pData->dispSlotIdx], 0, pars->interp_nDirs * sizeof(float));
378 for(i=0; i< pars->grid_nDirs; i++)
379 for(j=0; j<DIRASS_FRAME_SIZE; j++)
380 pData->pmap[i] = (pars->ss[i*DIRASS_FRAME_SIZE+j])*(pars->ss[i*DIRASS_FRAME_SIZE+j]);
381
382 /* average energy over time, and assign to nearest grid direction */
383 for(i=0; i<pars->grid_nDirs; i++){
384 pData->pmap[i] = pmapAvgCoeff * (pars->prev_energy[i]) + (1.0f-pmapAvgCoeff) * (pData->pmap[i]);
385 pars->prev_energy[i] = pData->pmap[i];
386 pData->pmap_grid[pData->dispSlotIdx][pars->est_dirs_idx[i]] += pData->pmap[i];
387 }
388 break;
389 }
390
391 /* ascertain the minimum and maximum values for pmap colour scaling */
392 int ind;
393 utility_siminv(pData->pmap_grid[pData->dispSlotIdx], pars->interp_nDirs, &ind);
394 pData->pmap_grid_minVal = pData->pmap_grid[pData->dispSlotIdx][ind];
395 utility_simaxv(pData->pmap_grid[pData->dispSlotIdx], pars->interp_nDirs, &ind);
396 pData->pmap_grid_maxVal = pData->pmap_grid[pData->dispSlotIdx][ind];
397
398 /* normalise the pmap to 0..1 */
399 for(i=0; i<pars->interp_nDirs; i++)
400 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);
401
402 /* signify that the pmap in the current slot is ready for plotting */
403 pData->dispSlotIdx++;
404 if(pData->dispSlotIdx>=NUM_DISP_SLOTS)
405 pData->dispSlotIdx = 0;
406 pData->pmapReady = 1;
407 }
408 }
409 else if(pData->FIFO_idx >= DIRASS_FRAME_SIZE){
410 /* reset FIFO_idx index if codec was not ready */
411 pData->FIFO_idx = 0;
412 }
413 }
414
416}
417
418/* SETS */
419
424
425void dirass_setBeamType(void* const hDir, int newType)
426{
427 dirass_data *pData = (dirass_data*)(hDir);
428 if(pData->beamType != (STATIC_BEAM_TYPES)newType){
429 pData->beamType = (STATIC_BEAM_TYPES)newType;
431 }
432}
433
434void dirass_setInputOrder(void* const hDir, int newValue)
435{
436 dirass_data *pData = (dirass_data*)(hDir);
437 if(pData->new_inputOrder != newValue){
438 pData->new_inputOrder = newValue;
440 }
441 /* FUMA only supports 1st order */
442 if(pData->new_inputOrder!=SH_ORDER_FIRST && pData->chOrdering == CH_FUMA)
443 pData->chOrdering = CH_ACN;
444 if(pData->new_inputOrder!=SH_ORDER_FIRST && pData->norm == NORM_FUMA)
445 pData->norm = NORM_SN3D;
446}
447
448void dirass_setDisplayGridOption(void* const hDir, int newState)
449{
450 dirass_data *pData = (dirass_data*)(hDir);
451 if(pData->gridOption != (DIRASS_GRID_OPTIONS)newState){
452 pData->gridOption = (DIRASS_GRID_OPTIONS)newState;
454 }
455}
456
457void dirass_setDispWidth(void* const hDir, int newValue)
458{
459 dirass_data *pData = (dirass_data*)(hDir);
460 if(pData->dispWidth != newValue){
461 pData->dispWidth = newValue;
463 }
464}
465
466void dirass_setUpscaleOrder(void* const hDir, int newValue)
467{
468 dirass_data *pData = (dirass_data*)(hDir);
469 if(pData->new_upscaleOrder != newValue){
470 pData->new_upscaleOrder = newValue;
472 }
473}
474
475void dirass_setDiRAssMode(void* const hDir, int newMode)
476{
477 dirass_data *pData = (dirass_data*)(hDir);
478 dirass_codecPars* pars = pData->pars;
479 if(pData->DirAssMode!=(DIRASS_REASS_MODES)newMode){
480 pData->DirAssMode = (DIRASS_REASS_MODES)newMode;
481 if(pars->prev_intensity!=NULL)
482 memset(pars->prev_intensity, 0, pars->grid_nDirs*3*sizeof(float));
483 memset(pars->prev_energy, 0, pars->grid_nDirs*sizeof(float));
484 }
485}
486
487void dirass_setMinFreq(void* const hDir, float newValue)
488{
489 dirass_data *pData = (dirass_data*)(hDir);
490 pData->minFreq_hz = newValue;
491}
492
493void dirass_setMaxFreq(void* const hDir, float newValue)
494{
495 dirass_data *pData = (dirass_data*)(hDir);
496 pData->maxFreq_hz = newValue;
497}
498
499void dirass_setChOrder(void* const hDir, int newOrder)
500{
501 dirass_data *pData = (dirass_data*)(hDir);
502 if((CH_ORDER)newOrder != CH_FUMA || pData->new_inputOrder==SH_ORDER_FIRST)/* FUMA only supports 1st order */
503 pData->chOrdering = (CH_ORDER)newOrder;
504}
505
506void dirass_setNormType(void* const hDir, int newType)
507{
508 dirass_data *pData = (dirass_data*)(hDir);
509 if((NORM_TYPES)newType != NORM_FUMA || pData->new_inputOrder==SH_ORDER_FIRST)/* FUMA only supports 1st order */
510 pData->norm = (NORM_TYPES)newType;
511}
512
513void dirass_setDispFOV(void* const hDir, int newOption)
514{
515 dirass_data *pData = (dirass_data*)(hDir);
516 if(pData->HFOVoption != (HFOV_OPTIONS)newOption){
517 pData->HFOVoption = (HFOV_OPTIONS)newOption;
519 }
520}
521
522void dirass_setAspectRatio(void* const hDir, int newOption)
523{
524 dirass_data *pData = (dirass_data*)(hDir);
525 if(pData->aspectRatioOption != (ASPECT_RATIO_OPTIONS)newOption){
526 pData->aspectRatioOption = (ASPECT_RATIO_OPTIONS)newOption;
528 }
529}
530
531void dirass_setMapAvgCoeff(void* const hDir, float newValue)
532{
533 dirass_data *pData = (dirass_data*)(hDir);
534 pData->pmapAvgCoeff = SAF_MIN(SAF_MAX(0.0f, newValue), 0.999f);
535}
536
537void dirass_requestPmapUpdate(void* const hDir)
538{
539 dirass_data *pData = (dirass_data*)(hDir);
540 pData->recalcPmap = 1;
541}
542
543
544/* GETS */
545
547{
548 return DIRASS_FRAME_SIZE;
549}
550
552{
553 dirass_data *pData = (dirass_data*)(hDir);
554 return pData->codecStatus;
555}
556
557float dirass_getProgressBar0_1(void* const hDir)
558{
559 dirass_data *pData = (dirass_data*)(hDir);
560 return pData->progressBar0_1;
561}
562
563void dirass_getProgressBarText(void* const hDir, char* text)
564{
565 dirass_data *pData = (dirass_data*)(hDir);
566 memcpy(text, pData->progressBarText, PROGRESSBARTEXT_CHAR_LENGTH*sizeof(char));
567}
568
569int dirass_getInputOrder(void* const hDir)
570{
571 dirass_data *pData = (dirass_data*)(hDir);
572 return pData->new_inputOrder;
573}
574
575int dirass_getBeamType(void* const hDir)
576{
577 dirass_data *pData = (dirass_data*)(hDir);
578 return (int)pData->beamType;
579}
580
581int dirass_getDisplayGridOption(void* const hDir)
582{
583 dirass_data *pData = (dirass_data*)(hDir);
584 return (int)pData->gridOption;
585}
586
587int dirass_getDispWidth(void* const hDir)
588{
589 dirass_data *pData = (dirass_data*)(hDir);
590 return pData->dispWidth;
591}
592
593int dirass_getUpscaleOrder(void* const hDir)
594{
595 dirass_data *pData = (dirass_data*)(hDir);
596 return (int)pData->gridOption;
597}
598
599int dirass_getDiRAssMode(void* const hDir)
600{
601 dirass_data *pData = (dirass_data*)(hDir);
602 return pData->DirAssMode;
603}
604
605float dirass_getMinFreq(void* const hDir)
606{
607 dirass_data *pData = (dirass_data*)(hDir);
608 return pData->minFreq_hz;
609}
610
611float dirass_getMaxFreq(void* const hDir)
612{
613 dirass_data *pData = (dirass_data*)(hDir);
614 return pData->maxFreq_hz;
615}
616
617int dirass_getSamplingRate(void* const hDir)
618{
619 dirass_data *pData = (dirass_data*)(hDir);
620 return (int)(pData->fs+0.5f);
621}
622
623int dirass_getNSHrequired(void* const hDir)
624{
625 dirass_data *pData = (dirass_data*)(hDir);
626 return (pData->inputOrder+1)*(pData->inputOrder+1);
627}
628
629int dirass_getChOrder(void* const hDir)
630{
631 dirass_data *pData = (dirass_data*)(hDir);
632 return (int)pData->chOrdering;
633}
634
635int dirass_getNormType(void* const hDir)
636{
637 dirass_data *pData = (dirass_data*)(hDir);
638 return (int)pData->norm;
639}
640
641int dirass_getDispFOV(void* const hDir)
642{
643 dirass_data *pData = (dirass_data*)(hDir);
644 return (int)pData->HFOVoption;
645}
646
647int dirass_getAspectRatio(void* const hDir)
648{
649 dirass_data *pData = (dirass_data*)(hDir);
650 return (int)pData->aspectRatioOption;
651}
652
653float dirass_getMapAvgCoeff(void* const hDir)
654{
655 dirass_data *pData = (dirass_data*)(hDir);
656 return pData->pmapAvgCoeff;
657}
658
659int dirass_getPmap(void* const hDir, float** grid_dirs, float** pmap, int* nDirs,int* pmapWidth, int* hfov, float* aspectRatio)
660{
661 dirass_data *pData = (dirass_data*)(hDir);
662 dirass_codecPars* pars = pData->pars;
663 if((pData->codecStatus == CODEC_STATUS_INITIALISED) && pData->pmapReady){
664 (*grid_dirs) = pars->interp_dirs_deg;
665 (*pmap) = pData->pmap_grid[pData->dispSlotIdx-1 < 0 ? NUM_DISP_SLOTS-1 : pData->dispSlotIdx-1];
666 (*nDirs) = pars->interp_nDirs;
667 (*pmapWidth) = pData->dispWidth;
668 switch(pData->HFOVoption){
669 default:
670 case HFOV_360: (*hfov) = 360; break;
671 case HFOV_180: (*hfov) = 180; break;
672 case HFOV_90: (*hfov) = 90; break;
673 case HFOV_60: (*hfov) = 60; break;
674 }
675 switch(pData->aspectRatioOption){
676 default:
677 case ASPECT_RATIO_2_1: (*aspectRatio) = 2.0f; break;
678 case ASPECT_RATIO_16_9: (*aspectRatio) = 16.0f/9.0f; break;
679 case ASPECT_RATIO_4_3: (*aspectRatio) = 4.0f/3.0f; break;
680 }
681 }
682 return pData->pmapReady;
683}
684
686{
687 return 2*DIRASS_FRAME_SIZE;
688}
STATIC_BEAM_TYPES
Available static beamforming approaches.
Definition _common.h:168
@ STATIC_BEAM_TYPE_HYPERCARDIOID
hyper-cardioid
Definition _common.h:170
#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_60
60 degrees
Definition _common.h:183
@ HFOV_360
360 degrees
Definition _common.h:180
@ HFOV_180
180 degrees
Definition _common.h:181
@ HFOV_90
90 degrees
Definition _common.h:182
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
@ 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_4_3
ASPECT_RATIO_4_3 - 4:3.
Definition _common.h:191
@ ASPECT_RATIO_16_9
ASPECT_RATIO_16_9 - 16:9.
Definition _common.h:190
@ ASPECT_RATIO_2_1
ASPECT_RATIO_2_1 - 2:1.
Definition _common.h:189
int dirass_getInputOrder(void *const hDir)
Returns the current analysis/input order (see SH_ORDERS enum)
Definition dirass.c:569
int dirass_getDiRAssMode(void *const hDir)
Returns the current analysis directional re-assignment mode (see DIRASS_REASS_MODES enum)
Definition dirass.c:599
void dirass_setInputOrder(void *const hDir, int newValue)
Sets the input/analysis order (see SH_ORDERS enum)
Definition dirass.c:434
void dirass_requestPmapUpdate(void *const hDir)
Informs dirass that it should compute a new activity-map.
Definition dirass.c:537
void dirass_setMinFreq(void *const hDir, float newValue)
Sets the minimum analysis frequency, in Hz.
Definition dirass.c:487
void dirass_create(void **const phDir)
Creates an instance of the dirass.
Definition dirass.c:41
void dirass_init(void *const hDir, float sampleRate)
Initialises an instance of dirass with default settings.
Definition dirass.c:148
void dirass_analysis(void *const hDir, const float *const *inputs, int nInputs, int nSamples, int isPlaying)
Analyses the input spherical harmonic signals to generate an activity-map as in [1,...
Definition dirass.c:198
void dirass_initCodec(void *const hDir)
Intialises the codec variables, based on current global/user parameters.
Definition dirass.c:170
void dirass_destroy(void **const phDir)
Destroys an instance of the dirass.
Definition dirass.c:103
void dirass_setDispWidth(void *const hDir, int newValue)
Sets the output display width in pixels.
Definition dirass.c:457
void dirass_setMaxFreq(void *const hDir, float newValue)
Sets the maximum analysis frequency, in Hz.
Definition dirass.c:493
void dirass_setDiRAssMode(void *const hDir, int newMode)
Sets the analysis directional re-assignment mode (see DIRASS_REASS_MODES enum)
Definition dirass.c:475
void dirass_setAspectRatio(void *const hDir, int newOption)
Sets the visualisation display window aspect-ratio (see ASPECT_RATIO_OPTIONS enum)
Definition dirass.c:522
float dirass_getMinFreq(void *const hDir)
Returns the current minimum analysis frequency, in Hz.
Definition dirass.c:605
int dirass_getNormType(void *const hDir)
Returns the Ambisonic normalisation convention currently being usedto decode with,...
Definition dirass.c:635
void dirass_setUpscaleOrder(void *const hDir, int newValue)
Sets the upscale order, only if DIRASS_REASS_MODES is set to REASS_UPSCALE, (see DIRASS_UPSCALE_ORDER...
Definition dirass.c:466
int dirass_getDisplayGridOption(void *const hDir)
Returns the current display grid option (see DIRASS_GRID_OPTIONS enum)
Definition dirass.c:581
int dirass_getDispWidth(void *const hDir)
Returns the current output display width in pixels.
Definition dirass.c:587
void dirass_setDispFOV(void *const hDir, int newOption)
Sets the visualisation display window horizontal field-of-view (FOV) (see HFOV_OPTIONS enum)
Definition dirass.c:513
int dirass_getDispFOV(void *const hDir)
Returns the current visualisation display window horizontal field-of-view (FOV) (see HFOV_OPTIONS enu...
Definition dirass.c:641
int dirass_getPmap(void *const hDir, float **grid_dirs, float **pmap, int *nDirs, int *pmapWidth, int *hfov, float *aspectRatio)
Returns the latest computed activity-map if it is ready; otherwise it returns 0, and you'll just have...
Definition dirass.c:659
float dirass_getMaxFreq(void *const hDir)
Returns the current maximum analysis frequency, in Hz.
Definition dirass.c:611
int dirass_getSamplingRate(void *const hDir)
Returns the current sampling rate, in Hz.
Definition dirass.c:617
void dirass_setDisplayGridOption(void *const hDir, int newState)
Sets a new display grid option (see DIRASS_GRID_OPTIONS enum)
Definition dirass.c:448
CODEC_STATUS dirass_getCodecStatus(void *const hDir)
Returns current codec status (see CODEC_STATUS enum)
Definition dirass.c:551
int dirass_getUpscaleOrder(void *const hDir)
Returns the current upscale order (see DIRASS_UPSCALE_ORDERS enum)
Definition dirass.c:593
int dirass_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition dirass.c:546
void dirass_setNormType(void *const hDir, int newType)
Sets the Ambisonic normalisation convention to decode with, in order to match with the convention emp...
Definition dirass.c:506
int dirass_getProcessingDelay()
Returns the processing delay in samples (may be used for delay compensation features)
Definition dirass.c:685
int dirass_getChOrder(void *const hDir)
Returns the Ambisonic channel ordering convention currently being used to decode with,...
Definition dirass.c:629
void dirass_setBeamType(void *const hDir, int newType)
Sets the sector beamforming pattern to employ for the analysis (see STATIC_BEAM_TYPES enum).
Definition dirass.c:425
void dirass_getProgressBarText(void *const hDir, char *text)
(Optional) Returns current intialisation/processing progress text
Definition dirass.c:563
int dirass_getAspectRatio(void *const hDir)
Returns the current visualisation display window aspect-ratio (see ASPECT_RATIO_OPTIONS enum)
Definition dirass.c:647
float dirass_getProgressBar0_1(void *const hDir)
(Optional) Returns current intialisation/processing progress, between 0..1
Definition dirass.c:557
void dirass_setMapAvgCoeff(void *const hDir, float newValue)
Sets the activity-map averaging coefficient, 0..1.
Definition dirass.c:531
void dirass_refreshSettings(void *const hDir)
Sets all intialisation flags to 1; re-initialising all settings/variables as dirass is currently conf...
Definition dirass.c:420
void dirass_setChOrder(void *const hDir, int newOrder)
Sets the Ambisonic channel ordering convention to decode with, in order to match the convention emplo...
Definition dirass.c:499
float dirass_getMapAvgCoeff(void *const hDir)
Returns the current activity-map averaging coefficient, 0..1.
Definition dirass.c:653
int dirass_getNSHrequired(void *const hDir)
Returns the number of spherical harmonic signals required by the current analysis order: (current_ord...
Definition dirass.c:623
int dirass_getBeamType(void *const hDir)
Returns the sector beamforming pattern to employed for the analysis (see STATIC_BEAM_TYPES enum)
Definition dirass.c:575
A sound-field visualiser based on the directional re-assignment of beamformer energy based on local D...
DIRASS_REASS_MODES
Available processing modes.
Definition dirass.h:110
@ REASS_NEAREST
Each sector beamformer energy is re-assigned to the nearest interpolation grid point,...
Definition dirass.h:113
@ REASS_MODE_OFF
Re-assignment is disabled.
Definition dirass.h:111
@ REASS_UPSCALE
Each sector beamformer is re-encoded into spherical harmonics of a higher order.
Definition dirass.h:116
DIRASS_GRID_OPTIONS
Available scanning grid options.
Definition dirass.h:86
@ GRID_GEOSPHERE_8
GRID_GEOSPHERE_8 - 642 points.
Definition dirass.h:95
@ UPSCALE_ORDER_TENTH
Tenth-order upscaling.
Definition dirass.h:71
void dirass_setCodecStatus(void *const hDir, CODEC_STATUS newStatus)
Sets codec status (see CODEC_STATUS enum)
void dirass_initAna(void *const hDir)
Intialises the codec variables, based on current global/user parameters.
A sound-field visualiser based on the directional re-assignment of beamformer energy based on local D...
#define MAX_NUM_INPUT_SH_SIGNALS
Maximum number of SH signals for the input.
#define DIRASS_FRAME_SIZE
Framesize, in time-domain samples.
#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 getSHreal_recur(int N, float *dirs_rad, int nDirs, float *Y)
Computes real-valued spherical harmonics [1] for each given direction on the unit sphere.
Definition saf_sh.c:254
#define SAF_PI
pi constant (single precision)
#define SAF_MAX(a, b)
Returns the maximum of the two values.
#define SAF_MIN(a, b)
Returns the minimum of the two values.
void applyBiQuadFilter(float b[3], float a[3], float w_z_12[2], float *signal, int nSamples)
Applies biQuad filter to an input signal using the direct form II difference equation: https://en....
void biQuadCoeffs(BIQUAD_FILTER_TYPES filterType, float fc, float fs, float Q, float gain_dB, float b[3], float a[3])
Calculates 2nd order IIR filter coefficients [1].
void findClosestGridPoints(float *grid_dirs, int nGrid, float *target_dirs, int nTarget, int degFLAG, int *idx_closest, float *dirs_closest, float *angle_diff)
Finds indicies into "grid_dirs" that are the closest to "target dirs".
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.
@ BIQUAD_FILTER_LPF
low-pass filter (DAFx-Zolzer)
@ BIQUAD_FILTER_HPF
high-pass filter (DAFx-Zolzer)
void * malloc1d(size_t dim1_data_size)
1-D malloc (same as malloc, but with error checking)
Definition md_malloc.c:59
Contains variables for scanning grids, and sector beamforming.
float * ss
beamformer sector signals; FLAT: grid_nDirs x DIRASS_FRAME_SIZE
float * interp_table
interpolation table (spherical->rectangular grid); FLAT: interp_nDirs x grid_nDirs
float * interp_dirs_deg
interpolation directions, in degrees; FLAT: interp_nDirs x 2
float * est_dirs
estimated DoA per grid direction; grid_nDirs x 2
float * Cxyz
beamforming weights for velocity patterns; FLAT: nDirs x (order+1)^2 x 3
float * prev_energy
previous energy (for averaging); FLAT: grid_nDirs x 1
int * est_dirs_idx
DoA indices, into the interpolation directions; grid_nDirs x 1.
float * prev_intensity
previous intensity vectors (for averaging); FLAT: grid_nDirs x 3
float * w
beamforming weights; FLAT: nDirs x (order+1)^2
float * Cw
beamforming weights; FLAT: nDirs x (order)^2
int grid_nDirs
number of grid directions
float * Uw
beamforming weights; FLAT: nDirs x (upscaleOrder+1)^2
int interp_nDirs
number of interpolation directions
float * interp_dirs_rad
interpolation directions, in radians; FLAT: interp_nDirs x 2
float * ssxyz
beamformer velocity signals; FLAT: 3 x DIRASS_FRAME_SIZE
float * Y_up
real SH weights for upscaling; FLAT: (upscaleOrder+1)^2 x grid_nDirs
Main structure for dirass.
float pmapAvgCoeff
averaging coefficient for the intensity vector per grid direction
DIRASS_REASS_MODES DirAssMode
see DIRASS_REASS_MODES enum
int inputOrder
Current input/analysis order.
float * pmap
grid_nDirs x 1
float fs
host sampling rate
float Wz12_hpf[MAX_NUM_INPUT_SH_SIGNALS][2]
delayed elements used in the HPF
int upscaleOrder
Current target upscale order.
STATIC_BEAM_TYPES beamType
beamformer type mode
float SHframe_upTD[MAX_NUM_DISPLAY_SH_SIGNALS][DIRASS_FRAME_SIZE]
Upscaled SH signals.
float progressBar0_1
Current (re)initialisation progress, between [0..1].
float pmap_grid_maxVal
maximum value in pmap
float * pmap_grid[NUM_DISP_SLOTS]
dirass interpolated to grid; interp_nDirs x 1
float Wz12_lpf[MAX_NUM_INPUT_SH_SIGNALS][2]
delayed elements used in the LPF
int dispSlotIdx
current display slot index
int new_upscaleOrder
New target upscale order.
float pmap_grid_minVal
minimum value in pmap
int pmapReady
0: image generation not started yet, 1: image is ready for plotting
float SHframeTD[MAX_NUM_INPUT_SH_SIGNALS][DIRASS_FRAME_SIZE]
Input SH signals.
ASPECT_RATIO_OPTIONS aspectRatioOption
aspect ratio option
int new_inputOrder
New input/analysis order.
CODEC_STATUS codecStatus
see CODEC_STATUS
DIRASS_GRID_OPTIONS gridOption
grid option
float minFreq_hz
minimum frequency to include in pmap generation, Hz
int FIFO_idx
FIFO buffer index.
int dispWidth
number of interpolation points on the horizontal
PROC_STATUS procStatus
see PROC_STATUS
float maxFreq_hz
maximum frequency to include in pmap generation, Hz
int recalcPmap
set this to 1 to generate a new image
dirass_codecPars * pars
codec parameters
NORM_TYPES norm
Ambisonic normalisation convention (see NORM_TYPES)
char * progressBarText
Current (re)initialisation step, string.
CH_ORDER chOrdering
Ambisonic channel order convention (see CH_ORDER)
HFOV_OPTIONS HFOVoption
horizontal field-of-view option
float inFIFO[MAX_NUM_INPUT_SH_SIGNALS][DIRASS_FRAME_SIZE]
FIFO buffer.