43 {3.544907701811032f, 0.0f, 0.0f, 0.0f},
44 {0.0f, 0.0f, 0.0f, 2.046653415892977f},
45 {0.0f, 2.046653415892977f, 0.0f, 0.0f},
46 {0.0f, 0.0f, 2.046653415892977f, 0.0f} };
62 double s, norm, scale;
63 double* P, *s_n, *tc, *sqrt_n;
72 P =
calloc1d((n+3)*lenX,
sizeof(
double));
75 sqrt_n =
malloc1d((2*n+1)*
sizeof(
double));
78 for(i=0; i<lenX; i++){
79 s = sqrt(1.0-pow(x[i],2.0)) + 2.23e-20;
80 s_n[i] = pow(-s, (
double)n);
81 tc[i] = -2.0 * x[i]/s;
83 for(i=0; i<2*n+1; i++)
84 sqrt_n[i] = sqrt((
double)i);
87 norm *= 1.0 - 1.0/(2.0*(
double)i);
90 for(i=0; i<lenX; i++){
91 P[(n)*lenX+i] = sqrt(norm)*s_n[i];
92 P[(n-1)*lenX+i] = P[(n)*lenX+i] * tc[i] * (double)n/sqrt_n[2*n];
98 P[(m)*lenX+i] = (P[(m+1)*lenX+i]*tc[i]*((
double)m+1.0) - P[(m+2)*lenX+i] * sqrt_n[n+m+2] * sqrt_n[n-m-1])/(sqrt_n[n+m+1]*sqrt_n[n-m]);
102 memcpy(&(y[i*lenX]), &(P[i*lenX]), lenX*
sizeof(
double));
105 for(i=0; i<lenX; i++)
106 if(sqrt(1.0-pow(x[i],2.0))==0)
107 y[i] = pow(x[i],(
double)n);
112 for(i=n-m+1; i<n+m+1; i++)
114 for(i=0; i<lenX; i++)
115 y[m*lenX+i] *= scale;
118 for(i=1; i<2*n+1; i++)
120 for(i=0; i<lenX; i++)
121 y[n*lenX+i] *= scale;
140 float x2, one_min_x2, dfact_k;
143 for(i=0; i<lenX; i++)
148 for(i=0; i<lenX; i++){
152 Pnm[0*lenX+i] = x[i];
153 Pnm[1*lenX+i] = sqrtf(1.0f-x2);
156 Pnm[0*lenX+i] = (3.0f*x2-1.0f)/2.0f;
157 Pnm[1*lenX+i] = (x[i])*3.0f*sqrtf(1.0f-x2);
158 Pnm[2*lenX+i] = 3.0f*(1.0f-x2);
161 one_min_x2 = 1.0f-x2;
166 for (kk=1; kk<k/2+1; kk++)
167 dfact_k *= 2.0f*(
float)kk;
169 for (kk=1; kk<(k+1)/2+1; kk++)
170 dfact_k *= (2.0f*(
float)kk-1.0f);
172 Pnm[n*lenX+i] = dfact_k * powf(one_min_x2, (
float)n/2.0f);
175 Pnm[(n-1)*lenX+i] = (
float)k * (x[i]) *Pnm_minus1[(n-1)*lenX+i];
177 for (m=0; m<n-1; m++)
179 Pnm[m*lenX+i] = ( ((
float)k * (x[i]) *Pnm_minus1[m*lenX+i]) - ((float)(n+m-1) * Pnm_minus2[m*lenX+i])) / (float)(n-m);
198 int dir, j, n, m, idx_Y;
200 double *p_nm, *cos_incl;
206 Lnm =
malloc1d((2*order+1)*nDirs*
sizeof(
double));
207 norm_real =
malloc1d((2*order+1)*
sizeof(
double));
208 cos_incl =
malloc1d(nDirs*
sizeof(
double));
209 p_nm =
malloc1d((order+1)*nDirs *
sizeof(
double));
210 for (dir = 0; dir<nDirs; dir++)
211 cos_incl[dir] = cos((
double)dirs_rad[dir*2+1]);
214 for(n=0; n<=order; n++){
218 for(dir=0; dir<nDirs; dir++){
221 for(m=-n, j=0; m<=n; m++, j++)
222 Lnm[j*nDirs+dir] = pow(-1.0, (
double)abs(m)) * p_nm[abs(m)*nDirs+dir];
224 Lnm[dir] = p_nm[dir];
228 for(m=-n, j=0; m<=n; m++, j++)
232 for(dir=0; dir<nDirs; dir++){
233 for(m=-n, j=0; m<=n; m++, j++){
235 Y[(j+idx_Y)*nDirs+dir] = (
float)(norm_real[j] * Lnm[j*nDirs+dir] * sqrt(2.0)*sin((
double)(n-j)*(
double)dirs_rad[dir*2]));
237 Y[(j+idx_Y)*nDirs+dir] = (
float)(norm_real[j] * Lnm[j*nDirs+dir]);
239 Y[(j+idx_Y)*nDirs+dir] = (
float)(norm_real[j] * Lnm[j*nDirs+dir] * sqrt(2.0)*cos((
double)(abs(m))*(
double)dirs_rad[dir*2]));
244 idx_Y = idx_Y + (2*n+1);
261 int n, m, i, dir, index_n;
263 float sleg_n[11], sleg_n_1[11], sleg_n_2[11], scos_incl, sfactorials_n[21];
264 float* leg_n, *leg_n_1, *leg_n_2, *cos_incl, *factorials_n;
269 if(N<=10 && nDirs == 1){
274 cos_incl = &scos_incl;
275 factorials_n = sfactorials_n;
278 factorials_n =
malloc1d((2*N+1)*
sizeof(
float));
279 leg_n =
malloc1d((N+1)*nDirs *
sizeof(
float));
280 leg_n_1 =
malloc1d((N+1)*nDirs *
sizeof(
float));
281 leg_n_2 =
malloc1d((N+1)*nDirs *
sizeof(
float));
282 cos_incl =
malloc1d(nDirs *
sizeof(
float));
287 for (i = 0; i < 2*N+1; i++)
291 for (dir = 0; dir<nDirs; dir++)
292 cos_incl[dir] = cosf(dirs_rad[dir*2+1]);
295 for (n = 0; n<N+1; n++) {
297 for (dir = 0; dir<nDirs; dir++)
304 Nn0 = sqrtf(2.0f*(
float)n+1.0f);
305 for (dir = 0; dir<nDirs; dir++){
306 for (m = 0; m<n+1; m++) {
308 Y[(index_n+n)*nDirs+dir] = Nn0/
SQRT4PI * leg_n[m*nDirs+dir];
310 Nnm = Nn0* sqrtf( 2.0f * factorials_n[n-m]/factorials_n[n+m] );
311 Y[(index_n+n-m)*nDirs+dir] = Nnm/
SQRT4PI * leg_n[m*nDirs+dir] * sinf((
float)m * (dirs_rad[dir*2]));
312 Y[(index_n+n+m)*nDirs+dir] = Nnm/
SQRT4PI * leg_n[m*nDirs+dir] * cosf((
float)m * (dirs_rad[dir*2]));
322 if(N>10 || nDirs > 1){
340 int dir, i, n, m, index_n, powm;
347 float* leg_n, *leg_n_1, *leg_n_2, *factorials_n;
352 assert((order_end - order_start) >= 0);
353 Lnm =
malloc1d((2*order_end+1)*nDirs*
sizeof(
double));
354 norm_real =
malloc1d((2*order_end+1)*
sizeof(
double));
355 p_nm =
malloc1d((order_end+1)*nDirs *
sizeof(
double));
356 cos_incl =
malloc1d(nDirs *
sizeof(
double));
357 fcos_incl =
malloc1d(nDirs *
sizeof(
float));
358 factorials_n =
malloc1d((2*order_end+1)*
sizeof(
float));
359 leg_n =
malloc1d((order_end+1)*nDirs *
sizeof(
float));
360 leg_n_1 =
malloc1d((order_end+1)*nDirs *
sizeof(
float));
361 leg_n_2 =
malloc1d((order_end+1)*nDirs *
sizeof(
float));
366 for (i = 0; i < 2*order_end+1; i++)
369 for(n=0; n<=order_end; n++){
371 for(m=0; m<=2*n+1; m++)
372 for(dir=0; dir<nDirs; dir++)
373 Y[(index_n+m)*nDirs+dir] = 0.f;
377 for (dir = 0; dir<nDirs; dir++)
382 for (dir = 0; dir<nDirs; dir++){
383 cos_incl[dir] = cos(dirs_rad[dir*2+1]);
384 fcos_incl[dir] = (float) cos_incl[dir];
387 if (n==order_start || n==order_start+1) {
391 for(dir=0; dir<nDirs; dir++){
395 for(m = 0; m<n+1; m++){
397 leg_n[m*nDirs+dir] = powm * (float)p_nm[abs(m)*nDirs+dir];
401 leg_n[dir] = (float)p_nm[dir];
409 Nn0 = sqrtf(2.0f*(
float)n+1.0f);
410 for (dir = 0; dir<nDirs; dir++){
411 for (m = 0; m<n+1; m++) {
413 Y[(index_n+n)*nDirs+dir] = Nn0/
SQRT4PI * leg_n[m*nDirs+dir];
415 Nnm = Nn0* sqrtf( 2.0f * factorials_n[n-m]/factorials_n[n+m] );
416 Y[(index_n+n-m)*nDirs+dir] = Nnm/
SQRT4PI * leg_n[m*nDirs+dir] * sinf((
float)m * (dirs_rad[dir*2]));
417 Y[(index_n+n+m)*nDirs+dir] = Nnm/
SQRT4PI * leg_n[m*nDirs+dir] * cosf((
float)m * (dirs_rad[dir*2]));
447 int dir, j, n, m, idx_Y;
449 double *Lnm, *cos_incl;
452 Lnm =
malloc1d((order+1)*nDirs*
sizeof(
double));
453 norm_real =
malloc1d((order+1)*
sizeof(
double));
454 cos_incl =
malloc1d(nDirs*
sizeof(
double));
455 for (dir = 0; dir<nDirs; dir++)
456 cos_incl[dir] = cos((
double)dirs_rad[dir*2+1]);
459 for(n=0; n<=order; n++){
468 for(dir=0; dir<nDirs; dir++){
469 for(m=-n, j=0; m<=n; m++, j++){
471 Ynm = crmul(conj(crmul(cexp(cmplx(0.0, (
double)abs(m)*(
double)dirs_rad[dir*2])), norm_real[abs(m)] * Lnm[abs(m)*nDirs+dir])), pow(-1.0, (
double)abs(m)));
472 Y[(j+idx_Y)*nDirs+dir] = cmplxf((
float)creal(Ynm), (float)cimag(Ynm));
475 Ynm = crmul(cexp(cmplx(0.0, (
double)abs(m)*(
double)dirs_rad[dir*2])), norm_real[m] * Lnm[m*nDirs+dir]);
476 Y[(j+idx_Y)*nDirs+dir] = cmplxf((
float)creal(Ynm), (float)cimag(Ynm));
482 idx_Y = idx_Y + (2*n+1);
496 int n, m, q, p, idx, nSH;
499 memset(T_c2r, 0, nSH*nSH*
sizeof(float_complex));
500 T_c2r[0] = cmplxf(1.0f, 0.0f);
505 for(n=1, q = 1; n<=order; n++){
507 for(m=-n, p=0; m<=n; m++, q++, p++){
509 T_c2r[(q)*nSH+(q)] = cmplxf(0.0f, 1.0f/sqrtf(2.0f));
510 T_c2r[(idx-p-1)*nSH+(q)] = cmplxf(1.0f/sqrtf(2.0f), 0.0f);
513 T_c2r[(q)*nSH+(q)] = cmplxf(1.0f, 0.0f);
515 T_c2r[(q)*nSH+(q)] = cmplxf(powf(-1.0f,(
float)m)/sqrtf(2.0f), 0.0f);
516 T_c2r[(idx-p-1)*nSH+(q)] = cmplxf(0.0f, -powf(-1.0f, (
float)abs(m))/sqrtf(2.0f));
528 int n, m, q, p, idx, nSH;
531 memset(T_r2c, 0, nSH*nSH*
sizeof(float_complex));
532 T_r2c[0] = cmplxf(1.0f, 0.0f);
537 for(n=1, q = 1; n<=order; n++){
539 for(m=-n, p=0; m<=n; m++, q++, p++){
541 T_r2c[(q)*nSH+(q)] = cmplxf(0.0f, -1.0f/sqrtf(2.0f));
542 T_r2c[(idx-p-1)*nSH+(q)] = cmplxf(0.0f, powf(-1.0f, (
float)abs(m))/sqrtf(2.0f));
545 T_r2c[(q)*nSH+(q)] = cmplxf(1.0f, 0.0f);
547 T_r2c[(q)*nSH+(q)] = cmplxf(powf(-1.0f,(
float)m)/sqrtf(2.0f), 0.0f);
548 T_r2c[(idx-p-1)*nSH+(q)] = cmplxf(1.0f/sqrtf(2.0f), 0.0f);
563 float_complex* T_c2r, *R_N_c;
564 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
567 T_c2r =
malloc1d(nSH*nSH*
sizeof(float_complex));
568 R_N_c =
malloc1d(nSH*K*
sizeof(float_complex));
570 for(i=0; i<nSH*nSH; i++)
571 T_c2r[i] = conjf(T_c2r[i]);
572 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, K, nSH, &calpha,
576 for(i=0; i<nSH*K; i++)
577 R_N[i] = crealf(R_N_c[i]);
592 int i, j, M, l, m, n, d, bandIdx, denom;
594 float R_1[3][3], _R_lm1[121*121], _R_l[121*121];
604 R_lm1 =
malloc1d(M*M*
sizeof(
float));
607 memset(RotMtx, 0, M*M*
sizeof(
float));
613 R_1[0][0] = Rxyz[1][1];
614 R_1[0][1] = Rxyz[1][2];
615 R_1[0][2] = Rxyz[1][0];
616 R_1[1][0] = Rxyz[2][1];
617 R_1[1][1] = Rxyz[2][2];
618 R_1[1][2] = Rxyz[2][0];
619 R_1[2][0] = Rxyz[0][1];
620 R_1[2][1] = Rxyz[0][2];
621 R_1[2][2] = Rxyz[0][0];
623 R_lm1[(i-1)*M+0] = R_1[i-1][0];
624 R_lm1[(i-1)*M+1] = R_1[i-1][1];
625 R_lm1[(i-1)*M+2] = R_1[i-1][2];
627 RotMtx[i*M+j] = R_1[i-1][j-1];
632 for(l = 2; l<=L; l++){
633 for(i=0; i<2*l+1; i++)
634 memset(R_l + i*M, 0, (2*l+1) *
sizeof(float));
635 for(m=-l; m<=l; m++){
636 for(n=-l; n<=l; n++){
639 denom = abs(n) == l ? (2*l)*(2*l-1) : (l*l-n*n);
640 u = sqrtf( (
float)((l*l-m*m)) / (
float)denom);
641 v = sqrtf( (
float)((1+d)*(l+abs(m)-1)*(l+abs(m))) / (
float)denom) * (float)(1-2*d)*0.5f;
642 w = sqrtf( (
float)((l-abs(m)-1)*(l-abs(m))) / (
float)denom) * (float)(1-d)*(-0.5f);
646 u = u*
getU(M,l,m,n,R_1,R_lm1);
648 v = v*
getV(M,l,m,n,R_1,R_lm1);
650 w = w*
getW(M,l,m,n,R_1,R_lm1);
652 R_l[(m+l)*M+(n+l)] = u+v+w;
656 for(i=0; i<2*l+1; i++)
657 for(j=0; j<2*l+1; j++)
658 RotMtx[(bandIdx + i)*M + (bandIdx + j)] = R_l[i*M+j];
659 for(i=0; i<2*l+1; i++)
660 memcpy(R_lm1+i*M, R_l + i*M, (2*l+1) *
sizeof(float));
677 int i, j, Nxyz, Ns, nC_xyz, nC_s;
678 float x1, x3, z2, y1, y3;
683 nC_xyz = (Nxyz+1)*(Nxyz+1);
684 nC_s = (Ns+1)*(Ns+1);
685 x1 = sqrtf(2.0f*
SAF_PI/3.0f);
687 y1 = y3 = sqrtf(2.0f*
SAF_PI/3.0f);
688 z2 = sqrtf(4.0f*
SAF_PI/3.0f);
689 G_mtx =
malloc1d(nC_s*4*nC_xyz*
sizeof(
float));
692 for (i=0; i<nC_xyz; i++){
693 for (j=0; j<nC_s; j++){
694 A_xyz[i*nC_s*3 + j*3 + 0] = cmplxf(x1*G_mtx[j*4*nC_xyz + 1*nC_xyz + i] + x3*G_mtx[j*4*nC_xyz + 3*nC_xyz + i], 0.0f);
695 A_xyz[i*nC_s*3 + j*3 + 1] = cmplxf(0.0f, y1*G_mtx[j*4*nC_xyz + 1*nC_xyz + i] + y3*G_mtx[j*4*nC_xyz + 3*nC_xyz + i]);
696 A_xyz[i*nC_s*3 + j*3 + 2] = cmplxf(z2*G_mtx[j*4*nC_xyz + 2*nC_xyz + i], 0.0f);
706 float_complex* A_xyz,
713 int i, j, ns, orderVel, nSH;
714 float normSec, azi_sec, elev_sec, Q;
715 float* b_n, *c_nm, *xyz_nm;
718 memcpy(sectorCoeffs,
wxyzCoeffs, 16*
sizeof(
float));
722 orderVel = orderSec+1;
723 nSH = (orderSec+2)*(orderSec+2);
724 b_n =
malloc1d((orderSec+1)*
sizeof(
float));
725 c_nm =
calloc1d((orderVel+1)*(orderVel+1),
sizeof(
float));
726 xyz_nm =
malloc1d((orderVel+1)*(orderVel+1)*3*
sizeof(
float));
730 Q = (float)((orderSec+1) * (orderSec+1));
734 cblas_sgemm(CblasRowMajor, CblasTrans, CblasNoTrans, 1, 1, orderSec+1, 1.0f,
742 Q = 2.0f*(float)orderSec + 1.0f;
745 normSec = Q/(float)nSecDirs;
747 for(ns=0; ns<nSecDirs; ns++){
749 azi_sec = sec_dirs_deg[ns*2] *
SAF_PI/180.0f;
750 elev_sec = sec_dirs_deg[ns*2+1] *
SAF_PI/180.0f;
755 for(j=0; j<nSH; j++){
756 sectorCoeffs[ns*4*nSH + 0*nSH +j] = sqrtf(normSec) * c_nm[j];
758 sectorCoeffs[ns*4*nSH + (i+1)*nSH +j] = sqrtf(normSec) * xyz_nm[j*3+i];
772 float_complex* A_xyz,
779 int i, j, ns, orderVel, nSH;
780 float normSec, azi_sec, elev_sec;
781 float* b_n, *c_nm, *xyz_nm;
784 memcpy(sectorCoeffs,
wxyzCoeffs, 16*
sizeof(
float));
788 orderVel = orderSec+1;
789 nSH = (orderSec+2)*(orderSec+2);
790 b_n =
malloc1d((orderSec+1)*
sizeof(
float));
791 c_nm =
calloc1d((orderVel+1)*(orderVel+1),
sizeof(
float));
792 xyz_nm =
malloc1d((orderVel+1)*(orderVel+1)*3*
sizeof(
float));
798 normSec = (float)(orderSec+1)/(float)nSecDirs;
800 for(ns=0; ns<nSecDirs; ns++){
802 azi_sec = sec_dirs_deg[ns*2] *
SAF_PI/180.0f;
803 elev_sec = sec_dirs_deg[ns*2+1] *
SAF_PI/180.0f;
808 for(j=0; j<nSH; j++){
809 sectorCoeffs[ns*4*nSH + 0*nSH +j] = normSec * c_nm[j];
811 sectorCoeffs[ns*4*nSH + (i+1)*nSH +j] = normSec * xyz_nm[j*3+i];
831 for(n=0; n<N+1; n++) {
832 b_n[n] = sqrtf(4.0f*
SAF_PI*(2.0f*(
float)n+1.0f)) *
847 float dirs_rad[2] = {0.0f, 0.0f};
849 c_n =
malloc1d((N+1)*(N+1)*
sizeof(
float));
852 b_n[n] = c_n[(n+1)*(n+1)-n-1] * 4.0f *
SAF_PI/(powf((
float)N+1.0f, 2.0f));
868 temp_o =
malloc1d( (N+1)*
sizeof(
double));
870 for (n=0; n<=N; n++) {
871 temp_i = cos(2.4068f/((
double)N+1.51));
873 b_n[n] = sqrtf((2.0f*(
float)n+1.0f)/(4.0f*
SAF_PI))*(float)temp_o[0];
874 norm += sqrtf((2.0f*(
float)n+1.0f)/(4.0f*
SAF_PI))*b_n[n];
890 float_complex* A_xyz,
895 float_complex* velCoeffs_c;
898 velCoeffs_c =
malloc1d(nSH*3*
sizeof(float_complex));
911 float_complex* A_xyz,
912 float_complex* velCoeffs
915 int i, j, d3, nSH_l, nSH;
916 float_complex* c_nm, *A_1, *velCoeffs_T;
917 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
921 c_nm =
malloc1d(nSH_l*
sizeof(float_complex));
922 A_1 =
malloc1d(nSH*nSH_l*
sizeof(float_complex));
923 velCoeffs_T =
malloc1d(3*nSH*
sizeof(float_complex));
927 for(d3 = 0; d3<3; d3++){
929 for(j=0; j<nSH_l; j++)
930 A_1[i*nSH_l+j] = A_xyz[i*nSH_l*3 + j*3 + d3];
931 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, 1, nSH_l, &calpha,
934 &velCoeffs_T[d3*nSH], 1);
936 for(d3 = 0; d3<3; d3++)
938 velCoeffs[i*3+d3] = velCoeffs_T[d3*nSH+i];
955 float_complex* c_nm_c;
958 c_nm_c =
malloc1d(nSH*
sizeof(float_complex));
978 phi_theta[0] = phi_0;
979 phi_theta[1] = theta_0;
981 Y_N =
malloc1d(nSH*
sizeof(float_complex));
983 for(n=0, q = 0; n<=order; n++)
984 for(m=-n; m<=n; m++, q++)
985 c_nm[q] = crmulf(conjf(Y_N[q]), sqrtf(4.0f*
SAF_PI/(2.0f*(
float)n+1.0f)) * c_n[n]);
999 int n, i, j, nSH, nSH_n, ind;
1000 float minVal, maxVal;
1001 float *YY_n, *W, *W_Yn, *s;
1006 Y_N = (
float**)
malloc2d(nSH, nDirs,
sizeof(
float));
1007 Y_n = (
float**)
malloc2d(nDirs, nSH,
sizeof(
float));
1008 YY_n =
malloc1d(nSH*nSH*
sizeof(
float));
1013 W =
calloc1d(nDirs*nDirs,
sizeof(
float));
1014 W_Yn =
malloc1d(nDirs*nSH*
sizeof(
float));
1015 for(i=0; i<nDirs; i++)
1016 W[i*nDirs+i] = w[i];
1025 for(n=0; n<=order; n++){
1026 nSH_n = (n+1)*(n+1);
1027 for(i=0; i<nDirs; i++)
1028 for(j=0; j<nSH_n; j++)
1029 Y_n[i][j] = Y_N[j][i];
1031 cblas_sgemm(CblasRowMajor, CblasTrans, CblasNoTrans, nSH_n, nSH_n, nDirs, 1.0f,
1037 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nDirs, nSH_n, nDirs, 1.0f,
1041 cblas_sgemm(CblasRowMajor, CblasTrans, CblasNoTrans, nSH_n, nSH_n, nDirs, 1.0f,
1048 utility_ssvd(NULL, YY_n, nSH_n, nSH_n, NULL, NULL, NULL, s);
1053 cond_N[n] = maxVal/(minVal+2.23e-7f);
1075 float** Y_N, **Y_N_T, **Y_leftinv;
1079 float minVal, maxVal, cond_N;
1088 for(
int n=1; n<100; n++){
1091 Y_N = (
float**)
realloc2d((
void**)Y_N, nSH, nDirs,
sizeof(float));
1092 YY_N = (
float*)
realloc1d(YY_N, nSH*nSH*
sizeof(
float));
1093 s = (
float*)
realloc1d(s, nSH*
sizeof(
float));
1096 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasTrans, nSH, nSH, nDirs, 1.0f,
1102 utility_ssvd(NULL, YY_N, nSH, nSH, NULL, NULL, NULL, s);
1107 cond_N = maxVal/(minVal+2.23e-7f);
1109 if(cond_N > 2 * (n + 1)){
1125 Y_N = (
float**)
malloc2d(nSH, nDirs,
sizeof(
float));
1126 Y_N_T = (
float**)
malloc2d(nDirs, nSH,
sizeof(
float));
1127 Y_leftinv = (
float**)
malloc2d(nSH, nDirs,
sizeof(
float));
1131 for(i=0; i<nDirs; i++)
1132 for(j=0; j<nSH; j++)
1133 Y_N_T[i][j] = Y_N[j][i];
1138 for(
int idx=0; idx<nDirs; idx++){
1139 w[idx] = sqrtf(
FOURPI)*Y_leftinv[0][idx];
1143 if(fabs(sumW -
FOURPI) > 0.001){
1156 void **
const phPWD,
1158 float* grid_dirs_deg,
1165 float** grid_dirs_rad, **grid_svecs_tmp;
1172 h->grid_svecs =
malloc1d(h->nSH * (h->nDirs) *
sizeof(float_complex));
1173 grid_dirs_rad = (
float**)
malloc2d(h->nDirs, 2,
sizeof(
float));
1174 grid_svecs_tmp = (
float**)
malloc2d(h->nSH, h->nDirs,
sizeof(
float));
1175 for(i=0; i<h->nDirs; i++){
1176 grid_dirs_rad[i][0] = grid_dirs_deg[i*2]*
SAF_PI/180.0f;
1177 grid_dirs_rad[i][1] =
SAF_PI/2.0f - grid_dirs_deg[i*2+1]*
SAF_PI/180.0f;
1180 for(i=0; i<h->nSH; i++)
1181 for(j=0; j<h->nDirs; j++)
1182 h->grid_svecs[j*(h->nSH)+i] = cmplxf(grid_svecs_tmp[i][j], 0.0f);
1185 h->grid_dirs_xyz =
malloc1d(h->nDirs * 3 *
sizeof(
float));
1186 unitSph2cart(grid_dirs_deg, h->nDirs, 1, h->grid_dirs_xyz);
1189 h->A_Cx =
malloc1d((h->nSH) *
sizeof(float_complex));
1190 h->pSpec =
malloc1d(h->nDirs*
sizeof(
float));
1191 h->P_minus_peak =
malloc1d(h->nDirs*
sizeof(
float));
1192 h->VM_mask =
malloc1d(h->nDirs*
sizeof(
float));
1193 h->P_tmp =
malloc1d(h->nDirs*
sizeof(
float));
1196 free(grid_dirs_rad);
1197 free(grid_svecs_tmp);
1208 free(h->grid_dirs_xyz);
1209 free(h->grid_svecs);
1212 free(h->P_minus_peak);
1234 float_complex A_Cx_A;
1235 const float_complex calpha = cmplxf(1.0f, 0.0f);
const float_complex cbeta = cmplxf(0.0f, 0.0f);
1238 for (i = 0; i < (h->nDirs); i++){
1239 cblas_cgemv(CblasRowMajor, CblasNoTrans, h->nSH, h->nSH, &calpha,
1241 &(h->grid_svecs[i*(h->nSH)]), 1, &cbeta,
1243 cblas_cdotu_sub(h->nSH, h->A_Cx, 1, &(h->grid_svecs[i*(h->nSH)]), 1, &A_Cx_A);
1244 h->pSpec[i] = crealf(A_Cx_A);
1249 cblas_scopy(h->nDirs, h->pSpec, 1, P_map, 1);
1252 if(peak_inds!=NULL){
1254 scale = kappa/(2.0f*
SAF_PI*expf(kappa)-expf(-kappa));
1255 cblas_scopy(h->nDirs, h->pSpec, 1, h->P_minus_peak, 1);
1258 for(k=0; k<nSrcs; k++){
1260 peak_inds[k] = peak_idx;
1263 VM_mean[0] = h->grid_dirs_xyz[peak_idx*3];
1264 VM_mean[1] = h->grid_dirs_xyz[peak_idx*3+1];
1265 VM_mean[2] = h->grid_dirs_xyz[peak_idx*3+2];
1268 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasTrans, h->nDirs, 1, 3, 1.0f,
1269 h->grid_dirs_xyz, 3,
1270 (
const float*)VM_mean, 3, 0.0f,
1272 cblas_sscal(h->nDirs, kappa, h->VM_mask, 1);
1273 for(i=0; i<h->nDirs; i++)
1274 h->VM_mask[i] = expf(h->VM_mask[i]);
1275 cblas_sscal(h->nDirs, scale, h->VM_mask, 1);
1276 for(i=0; i<h->nDirs; i++)
1277 h->VM_mask[i] = 1.0f/(0.00001f+(h->VM_mask[i]));
1279 cblas_scopy(h->nDirs, h->P_tmp, 1, h->P_minus_peak, 1);
1286 void **
const phMUSIC,
1288 float* grid_dirs_deg,
1295 float** grid_dirs_rad, **grid_svecs_tmp;
1302 h->grid_svecs =
malloc1d(h->nSH * (h->nDirs) *
sizeof(float_complex));
1303 grid_dirs_rad = (
float**)
malloc2d(h->nDirs, 2,
sizeof(
float));
1304 grid_svecs_tmp = (
float**)
malloc2d(h->nSH, h->nDirs,
sizeof(
float));
1305 for(i=0; i<h->nDirs; i++){
1306 grid_dirs_rad[i][0] = grid_dirs_deg[i*2]*
SAF_PI/180.0f;
1307 grid_dirs_rad[i][1] =
SAF_PI/2.0f - grid_dirs_deg[i*2+1]*
SAF_PI/180.0f;
1310 for(i=0; i<h->nSH; i++)
1311 for(j=0; j<h->nDirs; j++)
1312 h->grid_svecs[i*(h->nDirs)+j] = cmplxf(grid_svecs_tmp[i][j], 0.0f);
1315 h->grid_dirs_xyz =
malloc1d(h->nDirs * 3 *
sizeof(
float));
1316 unitSph2cart(grid_dirs_deg, h->nDirs, 1, h->grid_dirs_xyz);
1319 h->VnA =
malloc1d(h->nSH * (h->nDirs) *
sizeof(float_complex));
1320 h->abs_VnA =
malloc1d(h->nSH * (h->nDirs) *
sizeof(
float));
1321 h->pSpec =
malloc1d(h->nDirs*
sizeof(
float));
1322 h->pSpecInv =
malloc1d(h->nDirs*
sizeof(
float));
1323 h->P_minus_peak =
malloc1d(h->nDirs*
sizeof(
float));
1324 h->P_tmp =
malloc1d(h->nDirs*
sizeof(
float));
1325 h->VM_mask =
malloc1d(h->nDirs*
sizeof(
float));
1328 free(grid_dirs_rad);
1329 free(grid_svecs_tmp);
1334 void **
const phMUSIC
1340 free(h->grid_dirs_xyz);
1341 free(h->grid_svecs);
1346 free(h->P_minus_peak);
1365 int i, k, VnD2, peak_idx;
1368 const float_complex calpha = cmplxf(1.0f, 0.0f);
const float_complex cbeta = cmplxf(0.0f, 0.0f);
1370 VnD2 = h->nSH - nSrcs;
1373 cblas_cgemm(CblasRowMajor, CblasTrans, CblasNoTrans, h->nDirs, VnD2, h->nSH, &calpha,
1374 h->grid_svecs, h->nDirs,
1378 for (i = 0; i < (h->nDirs); i++)
1379 h->pSpecInv[i] = cblas_sdot(VnD2, &(h->abs_VnA[i*VnD2]), 1, &(h->abs_VnA[i*VnD2]), 1);
1385 cblas_scopy(h->nDirs, h->pSpec, 1, P_music, 1);
1388 if(peak_inds!=NULL){
1390 scale = kappa/(2.0f*
SAF_PI*expf(kappa)-expf(-kappa));
1391 cblas_scopy(h->nDirs, h->pSpec, 1, h->P_minus_peak, 1);
1394 for(k=0; k<nSrcs; k++){
1396 peak_inds[k] = peak_idx;
1399 VM_mean[0] = h->grid_dirs_xyz[peak_idx*3];
1400 VM_mean[1] = h->grid_dirs_xyz[peak_idx*3+1];
1401 VM_mean[2] = h->grid_dirs_xyz[peak_idx*3+2];
1404 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasTrans, h->nDirs, 1, 3, 1.0f,
1405 h->grid_dirs_xyz, 3,
1406 (
const float*)VM_mean, 3, 0.0f,
1408 cblas_sscal(h->nDirs, kappa, h->VM_mask, 1);
1409 for(i=0; i<h->nDirs; i++)
1410 h->VM_mask[i] = expf(h->VM_mask[i]);
1411 cblas_sscal(h->nDirs, scale, h->VM_mask, 1);
1412 for(i=0; i<h->nDirs; i++)
1413 h->VM_mask[i] = 1.0f/(0.00001f+(h->VM_mask[i]));
1415 cblas_scopy(h->nDirs, h->P_tmp, 1, h->P_minus_peak, 1);
1422 void **
const phESPRIT,
1431 h->NN = order*order;
1436 h->rWVnimu[i] =
malloc1d((order*order) * (order*order) *
sizeof(
double));
1437 h->WVnimu[i] =
malloc1d((order*order) * (order*order) *
sizeof(double_complex));
1439 h->nIdx[0] = h->nIdx[1] = h->nIdx[4] = h->nIdx[5] = h->nIdx[10] = h->nIdx[11] = (order*order);
1440 h->nIdx[2] = h->nIdx[3] = h->nIdx[6] = h->nIdx[7] = h->nIdx[8] = h->nIdx[9] = ((order-1)*(order-1));
1441 for(i=0; i<12; i++){
1443 h->idx_from_Ynm2Ynimu[i] = NULL;
1445 h->idx_from_Ynm2Ynimu[i] =
calloc1d(h->nIdx[i],
sizeof(
int));
1447 getWnimu(order, 1, 1,-1, h->rWVnimu[0]);
1448 getWnimu(order,-1, 0, 0, h->rWVnimu[1]);
1449 getWnimu(order,-1, 1,-1, h->rWVnimu[2]);
1450 getWnimu(order, 1, 0, 0, h->rWVnimu[3]);
1451 getVnimu(order, 0, 0, h->rWVnimu[4]);
1452 getVnimu(order, 1, 0, h->rWVnimu[5]);
1454 for(j=0; j<(order*order) * (order*order); j++)
1455 h->WVnimu[i][j] = cmplx(h->rWVnimu[i][j], 0.0);
1457 muni2q(order, 1,-1, h->idx_from_Ynm2Ynimu[0], h->idx_from_Ynm2Ynimu[1]);
1458 muni2q(order,-1,-1, h->idx_from_Ynm2Ynimu[2], h->idx_from_Ynm2Ynimu[3]);
1459 muni2q(order, 1, 1, h->idx_from_Ynm2Ynimu[4], h->idx_from_Ynm2Ynimu[5]);
1460 muni2q(order,-1, 1, h->idx_from_Ynm2Ynimu[6], h->idx_from_Ynm2Ynimu[7]);
1461 muni2q(order,-1, 0, h->idx_from_Ynm2Ynimu[8], h->idx_from_Ynm2Ynimu[9]);
1462 muni2q(order, 1, 0, h->idx_from_Ynm2Ynimu[10], h->idx_from_Ynm2Ynimu[11]);
1468 h->Us_1m1 =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1469 h->Us_m1m1 =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1470 h->Us_11 =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1471 h->Us_m11 =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1472 h->Us_m10 =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1473 h->Us_10 =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1474 h->Us_00 =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1475 h->WVnimu0_Us1m1 =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1476 h->WVnimu1_Usm1m1 =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1477 h->WVnimu2_Us11 =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1478 h->WVnimu3_Usm11 =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1479 h->WVnimu4_Usm10 =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1480 h->WVnimu5_Us10 =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1481 h->LambdaXYp =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1482 h->LambdaXYm =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1483 h->LambdaZ =
malloc1d((h->NN) * (h->maxK) *
sizeof(double_complex));
1484 h->pinvUs =
malloc1d((h->maxK) * (h->NN) *
sizeof(double_complex));
1485 h->PsiXYp =
malloc1d((h->maxK) * (h->maxK) *
sizeof(double_complex));
1486 h->PsiXYm =
malloc1d((h->maxK) * (h->maxK) *
sizeof(double_complex));
1487 h->PsiZ =
malloc1d((h->maxK) * (h->maxK) *
sizeof(double_complex));
1488 h->tmp_KK =
malloc1d((h->maxK) * (h->maxK) *
sizeof(double_complex));
1489 h->V =
malloc1d((h->maxK) * (h->maxK) *
sizeof(double_complex));
1490 h->PhiXYp =
malloc1d((h->maxK) * (h->maxK) *
sizeof(double_complex));
1491 h->PhiXYm =
malloc1d((h->maxK) * (h->maxK) *
sizeof(double_complex));
1492 h->PhiZ =
malloc1d((h->maxK) * (h->maxK) *
sizeof(double_complex));
1497 void **
const phESPRIT
1505 free(h->rWVnimu[i]);
1509 free(h->idx_from_Ynm2Ynimu[i]);
1520 free(h->WVnimu0_Us1m1);
1521 free(h->WVnimu1_Usm1m1);
1522 free(h->WVnimu2_Us11);
1523 free(h->WVnimu3_Usm11);
1524 free(h->WVnimu4_Usm10);
1525 free(h->WVnimu5_Us10);
1547 void *
const hESPRIT,
1555 const double_complex i2_ = cmplx(0.0, 2.0);
1556 const double_complex calpha = cmplx(1.0, 0.0);
const double_complex cbeta = cmplx(0.0, 0.0);
1560 memset(h->Us_1m1, 0, (h->NN) * K *
sizeof(double_complex));
1561 memset(h->Us_m1m1, 0, (h->NN) * K *
sizeof(double_complex));
1562 memset(h->Us_11, 0, (h->NN) * K *
sizeof(double_complex));
1563 memset(h->Us_m11, 0, (h->NN) * K *
sizeof(double_complex));
1564 memset(h->Us_m10, 0, (h->NN) * K *
sizeof(double_complex));
1565 memset(h->Us_10, 0, (h->NN) * K *
sizeof(double_complex));
1566 memset(h->Us_00, 0, (h->NN) * K *
sizeof(double_complex));
1567 for (i = 0; i < K; i++) {
1568 for (j = 0; j < h->nIdx[0]; j++)
1569 h->Us_1m1[h->idx_from_Ynm2Ynimu[0][j] * K + i] = cmplx(crealf(Us[h->idx_from_Ynm2Ynimu[1][j] * K + i]), cimagf(Us[h->idx_from_Ynm2Ynimu[1][j] * K + i]));
1570 for (j = 0; j < h->nIdx[2]; j++)
1571 h->Us_m1m1[h->idx_from_Ynm2Ynimu[2][j] * K + i] = cmplx(crealf(Us[h->idx_from_Ynm2Ynimu[3][j] * K + i]), cimagf(Us[h->idx_from_Ynm2Ynimu[3][j] * K + i]));
1572 for (j = 0; j < h->nIdx[4]; j++)
1573 h->Us_11[h->idx_from_Ynm2Ynimu[4][j] * K + i] = cmplx(crealf(Us[h->idx_from_Ynm2Ynimu[5][j] * K + i]), cimagf(Us[h->idx_from_Ynm2Ynimu[5][j] * K + i]));
1574 for (j = 0; j < h->nIdx[6]; j++)
1575 h->Us_m11[h->idx_from_Ynm2Ynimu[6][j] * K + i] = cmplx(crealf(Us[h->idx_from_Ynm2Ynimu[7][j] * K + i]), cimagf(Us[h->idx_from_Ynm2Ynimu[7][j] * K + i]));
1576 for (j = 0; j < h->nIdx[8]; j++)
1577 h->Us_m10[h->idx_from_Ynm2Ynimu[8][j] * K + i] = cmplx(crealf(Us[h->idx_from_Ynm2Ynimu[9][j] * K + i]), cimagf(Us[h->idx_from_Ynm2Ynimu[9][j] * K + i]));
1578 for (j = 0; j < h->nIdx[10]; j++)
1579 h->Us_10[h->idx_from_Ynm2Ynimu[10][j] * K + i] = cmplx(crealf(Us[h->idx_from_Ynm2Ynimu[11][j] * K + i]), cimagf(Us[h->idx_from_Ynm2Ynimu[11][j] * K + i]));
1580 for (j = 0; j < (h->NN); j++)
1581 h->Us_00[j*K + i] = cmplx(crealf(Us[j*K + i]), cimagf(Us[j*K + i]));
1585 cblas_zgemm(CblasRowMajor, CblasTrans, CblasNoTrans, (h->NN), K, (h->NN), &calpha,
1586 h->WVnimu[0], (h->NN),
1587 h->Us_1m1, K, &cbeta,
1588 h->WVnimu0_Us1m1, K);
1589 cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, (h->NN), K, (h->NN), &calpha,
1590 h->WVnimu[1], (h->NN),
1591 h->Us_m1m1, K, &cbeta,
1592 h->WVnimu1_Usm1m1, K);
1593 cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, (h->NN), K, (h->NN), &calpha,
1594 h->WVnimu[2], (h->NN),
1595 h->Us_11, K, &cbeta,
1596 h->WVnimu2_Us11, K);
1597 cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, (h->NN), K, (h->NN), &calpha,
1598 h->WVnimu[3], (h->NN),
1599 h->Us_m11, K, &cbeta,
1600 h->WVnimu3_Usm11, K);
1601 cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, (h->NN), K, (h->NN), &calpha,
1602 h->WVnimu[4], (h->NN),
1603 h->Us_m10, K, &cbeta,
1604 h->WVnimu4_Usm10, K);
1605 cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, (h->NN), K, (h->NN), &calpha,
1606 h->WVnimu[5], (h->NN),
1607 h->Us_10, K, &cbeta,
1608 h->WVnimu5_Us10, K);
1609 utility_zvvsub(h->WVnimu0_Us1m1, h->WVnimu1_Usm1m1, h->NN*K, h->LambdaXYp);
1610 cblas_dscal(2*h->NN*K, -1.0, (
double*)h->WVnimu2_Us11, 1);
1611 utility_zvvadd(h->WVnimu2_Us11, h->WVnimu3_Usm11, h->NN*K, h->LambdaXYm);
1612 utility_zvvadd(h->WVnimu4_Usm10, h->WVnimu5_Us10, h->NN*K, h->LambdaZ);
1616 cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, K, K, (h->NN), &calpha,
1618 h->LambdaXYp, K, &cbeta,
1620 cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, K, K, (h->NN), &calpha,
1622 h->LambdaXYm, K, &cbeta,
1624 cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, K, K, (h->NN), &calpha,
1626 h->LambdaZ, K, &cbeta,
1630 utility_zeigmp(h->hZeigmp, h->PsiXYp, h->PsiZ, K, NULL, h->V, NULL);
1631 cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, K, K, K, &calpha,
1636 cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, K, K, K, &calpha,
1641 cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, K, K, K, &calpha,
1649 phiX = (creal(h->PhiXYp[i*K+i])+creal(h->PhiXYm[i*K+i]))/2.0;
1650 phiY = creal(ccdiv(ccsub(h->PhiXYp[i*K+i], h->PhiXYm[i*K+i]), i2_));
1651 src_dirs_rad[i*2] = (float)atan2(phiY, phiX);
1652 src_dirs_rad[i*2+1] = (float)
SAF_MIN(atan2(creal(h->PhiZ[i*K+i]), sqrt(phiX*phiX+phiY*phiY)),
SAF_PI/2.0f);
1660 float_complex* Y_grid,
1666 float_complex* Cx_Y, *Y_Cx_Y, *Cx_Y_s, *Y_grid_s;
1667 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
1670 Cx_Y =
malloc1d(nSH * nGrid_dirs *
sizeof(float_complex));
1671 Y_Cx_Y =
malloc1d(nGrid_dirs*
sizeof(float_complex));
1672 Cx_Y_s =
malloc1d(nSH*
sizeof(float_complex));
1673 Y_grid_s =
malloc1d(nSH*
sizeof(float_complex));
1676 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, nGrid_dirs, nSH, &calpha,
1678 Y_grid, nGrid_dirs, &cbeta,
1680 for(i=0; i<nGrid_dirs; i++){
1681 for(j=0; j<nSH; j++){
1682 Cx_Y_s[j] = Cx_Y[j*nGrid_dirs+i];
1683 Y_grid_s[j] = Y_grid[j*nGrid_dirs+i];
1689 for(i=0; i<nGrid_dirs; i++)
1690 pmap[i] = crealf(Y_Cx_Y[i]);
1702 float_complex* Y_grid,
1706 float_complex* w_MVDR_out
1711 float_complex *Cx_d, *invCx_Ygrid, *w_MVDR, *invCx_Ygrid_s, *Y_grid_s;
1712 float_complex denum;
1715 w_MVDR =
malloc1d(nSH * nGrid_dirs*
sizeof(float_complex));
1716 Cx_d =
malloc1d(nSH*nSH*
sizeof(float_complex));
1717 invCx_Ygrid =
malloc1d(nSH*nGrid_dirs*
sizeof(float_complex));
1718 invCx_Ygrid_s =
malloc1d(nSH*
sizeof(float_complex));
1719 Y_grid_s =
malloc1d(nSH*
sizeof(float_complex));
1723 for(i=0; i<nSH; i++)
1724 Cx_trace += crealf(Cx[i*nSH+i]);
1725 Cx_trace /= (float)nSH;
1726 memcpy(Cx_d, Cx, nSH*nSH*
sizeof(float_complex));
1727 for(i=0; i<nSH; i++)
1728 Cx_d[i*nSH+i] = craddf(Cx_d[i*nSH+i], regPar*Cx_trace);
1731 utility_cslslv(NULL, Cx_d, nSH, Y_grid, nGrid_dirs, invCx_Ygrid);
1732 for(i=0; i<nGrid_dirs; i++){
1734 for(j=0; j<nSH; j++){
1735 invCx_Ygrid_s[j] = conjf(invCx_Ygrid[j*nGrid_dirs+i]);
1736 Y_grid_s[j] = Y_grid[j*nGrid_dirs+i];
1742 for(j=0; j<nSH; j++)
1743 w_MVDR[j*nGrid_dirs +i] = ccdivf(invCx_Ygrid[j*nGrid_dirs +i], denum);
1750 if (w_MVDR_out!=NULL)
1751 memcpy(w_MVDR_out, w_MVDR, nSH * nGrid_dirs*
sizeof(float_complex));
1756 free(invCx_Ygrid_s);
1768 float_complex* Y_grid,
1776 float Cx_trace, S, G;
1778 float_complex* Cx_d, *A, *invCxd_A, *invCxd_A_tmp, *w_LCMV_s, *w_CroPaC, *wo, *Cx_Y, *Cx_Y_s;
1780 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
1781 float_complex A_invCxd_A[2][2];
1782 float_complex Y_wo_xspec;
1784 b[0] = cmplxf(1.0f, 0.0f);
1785 b[1] = cmplxf(0.0f, 0.0f);
1787 Cx_Y =
malloc1d(nSH * nGrid_dirs *
sizeof(float_complex));
1788 Cx_d =
malloc1d(nSH*nSH*
sizeof(float_complex));
1789 A =
malloc1d(nSH*2*
sizeof(float_complex));
1790 invCxd_A =
malloc1d(nSH*2*
sizeof(float_complex));
1791 invCxd_A_tmp =
malloc1d(nSH*2*
sizeof(float_complex));
1792 w_LCMV_s =
malloc1d(2*nGrid_dirs*
sizeof(float_complex));
1793 w_CroPaC =
malloc1d(nSH*nGrid_dirs*
sizeof(float_complex));
1794 wo =
malloc1d(nSH*
sizeof(float_complex));
1795 mvdr_map =
malloc1d(nGrid_dirs*
sizeof(
float));
1796 Cx_Y_s =
malloc1d(nSH*
sizeof(float_complex));
1799 generateMVDRmap(order, Cx, Y_grid, nGrid_dirs, regPar, mvdr_map, w_CroPaC);
1802 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, nGrid_dirs, nSH, &calpha,
1804 Y_grid, nGrid_dirs, &cbeta,
1809 for(i=0; i<nSH; i++)
1810 Cx_trace += crealf(Cx[i*nSH+i]);
1811 Cx_trace /= (float)nSH;
1812 memcpy(Cx_d, Cx, nSH*nSH*
sizeof(float_complex));
1813 for(i=0; i<nSH; i++)
1814 Cx_d[i*nSH+i] = craddf(Cx_d[i*nSH+i], regPar*Cx_trace);
1817 for(i=0; i<nGrid_dirs; i++){
1818 for(j=0; j<nSH; j++){
1819 A[j*2] = Y_grid[j*nGrid_dirs+i];
1820 A[j*2+1] = ccmulf(A[j*2], Cx[j*nSH+j]);
1825 for(j=0; j<nSH*2; j++)
1826 invCxd_A_tmp[j] = conjf(invCxd_A[j]);
1827 cblas_cgemm(CblasRowMajor, CblasConjTrans, CblasNoTrans, 2, 2, nSH, &calpha,
1829 invCxd_A_tmp, 2, &cbeta,
1831 for(j=0; j<nSH; j++)
1833 invCxd_A_tmp[k*nSH+j] = invCxd_A[j*2+k];
1834 utility_cglslv(NULL, (float_complex*)A_invCxd_A, 2, invCxd_A_tmp, nSH, w_LCMV_s);
1835 cblas_cgemm(CblasRowMajor, CblasTrans, CblasNoTrans, nSH, 1, 2, &calpha,
1841 for(j=0; j<nSH; j++)
1842 Cx_Y_s[j] = Cx_Y[j*nGrid_dirs+i];
1846 S =
SAF_MIN(cabsf(Y_wo_xspec), mvdr_map[i]);
1847 G = sqrtf(S/(mvdr_map[i]+2.23e-10f));
1849 for(j=0; j<nSH; j++)
1850 w_CroPaC[j*nGrid_dirs + i] = crmulf(w_CroPaC[j*nGrid_dirs + i], G);
1872 float_complex* Y_grid,
1880 float_complex* V, *Vn, *Vn_Y;
1881 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
1885 nSources =
SAF_MIN(nSources, nSH/2);
1886 V =
malloc1d(nSH*nSH*
sizeof(float_complex));
1887 Vn =
malloc1d(nSH*(nSH-nSources)*
sizeof(float_complex));
1888 Vn_Y =
malloc1d((nSH-nSources)*nGrid_dirs*
sizeof(float_complex));
1895 for (i = 0; i < nSH; i++)
1896 for (j = 0; j < nSH - nSources; j++)
1897 Vn[i*(nSH - nSources) + j] = V[i*nSH + j + nSources];
1900 cblas_cgemm(CblasRowMajor, CblasTrans, CblasNoTrans, nSH-nSources, nGrid_dirs, nSH, &calpha,
1902 Y_grid, nGrid_dirs, &cbeta,
1904 for(i=0; i<nGrid_dirs; i++){
1905 tmp = cmplxf(0.0f,0.0f);
1906 for(j=0; j<nSH-nSources; j++)
1907 tmp = ccaddf(tmp, ccmulf(conjf(Vn_Y[j*nGrid_dirs+i]),Vn_Y[j*nGrid_dirs+i]));
1908 pmap[i] = logScaleFlag ? logf(1.0f/(crealf(tmp)+2.23e-10f)) : 1.0f/(crealf(tmp)+2.23e-10f);
1920 float_complex* Y_grid,
1928 float_complex* V, *Vn, *Vn1, *Un, *Un_Y;
1929 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
1930 float_complex Vn1_Vn1H;
1933 nSources =
SAF_MIN(nSources, nSH/2);
1934 V =
malloc1d(nSH*nSH*
sizeof(float_complex));
1935 Vn =
malloc1d(nSH*(nSH-nSources)*
sizeof(float_complex));
1936 Vn1 =
malloc1d((nSH-nSources)*
sizeof(float_complex));
1937 Un =
malloc1d(nSH*
sizeof(float_complex));
1938 Un_Y =
malloc1d(nGrid_dirs*
sizeof(float_complex));
1944 for(i=0; i<nSH; i++)
1945 for(j=0; j<nSH-nSources; j++)
1946 Vn[i*(nSH-nSources)+j] = V[i*nSH + j + nSources];
1947 for(j=0; j<nSH-nSources; j++)
1948 Vn1[j] = V[j + nSources];
1952 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasConjTrans, nSH, 1, nSH-nSources, &calpha,
1954 Vn1, nSH-nSources, &cbeta,
1956 for(i=0; i<nSH; i++)
1957 Un[i] = ccdivf(Un[i], craddf(Vn1_Vn1H, 2.23e-9f));
1958 cblas_cgemm(CblasRowMajor, CblasConjTrans, CblasNoTrans, 1, nGrid_dirs, nSH, &calpha,
1960 Y_grid, nGrid_dirs, &cbeta,
1962 for(i=0; i<nGrid_dirs; i++)
1963 pmap[i] = logScaleFlag ? logf(1.0f/(powf(cabsf(Un_Y[i]),2.0f) + 2.23e-9f)) : 1.0f/(powf(cabsf(Un_Y[i]),2.0f) + 2.23e-9f);
1981 float amp_thresh_dB,
1982 float_complex* H_array,
1983 float* grid_dirs_deg,
1988 float_complex* H_sht
1991 int i, kk, nSH, order_grid, nSH_grid;
1993 float* grid_dirs_rad, *Ytmp;
1994 float_complex* W, *Y_grid, *HW, *YW;
1995 float_complex *YWH_H, *HWH_H, *inv_HWH_H;
1996 float_complex* HWY_T, *YWY_T, *inv_YWY_T, *Q, *QQ_H, *inv_QQ_H;
1998 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
2001 saf_assert(order<=sqrt(nMics)-1,
"Order exceeds maximum possible for this number of sensors.");
2004 W =
calloc1d(nGrid*nGrid,
sizeof(float_complex));
2005 for(i=0; i<nGrid; i++)
2006 W[i*nGrid+i] = w_grid==NULL ? calpha : cmplxf(w_grid[i], 0.0f);
2010 HWY_T = YWY_T = inv_YWY_T = Q = QQ_H = inv_QQ_H = NULL;
2011 YW = YWH_H = HW = HWH_H = inv_HWH_H = NULL;
2019 YWH_H =
malloc1d(nSH*nMics*
sizeof(float_complex));
2020 HWH_H =
malloc1d(nMics*nMics*
sizeof(float_complex));
2021 inv_HWH_H =
malloc1d(nMics*nMics*
sizeof(float_complex));
2025 order_grid = (int)(sqrtf((
float)nGrid)/2.0f-1.0f);
2029 HWY_T =
malloc1d(nMics*nSH_grid*
sizeof(float_complex));
2030 YWY_T =
malloc1d(nSH_grid*nSH_grid*
sizeof(float_complex));
2031 inv_YWY_T =
malloc1d(nSH_grid*nSH_grid*
sizeof(float_complex));
2032 Q =
malloc1d(nMics*nSH_grid*
sizeof(float_complex));
2033 QQ_H =
malloc1d(nMics*nMics*
sizeof(float_complex));
2034 inv_QQ_H =
malloc1d(nMics*nMics*
sizeof(float_complex));
2037 HW =
malloc1d(nMics*nGrid*
sizeof(float_complex));
2038 YW =
malloc1d(nSH_grid*nGrid*
sizeof(float_complex));
2041 grid_dirs_rad =
malloc1d(nGrid*2*
sizeof(
float));
2042 for(i=0; i<nGrid; i++){
2043 grid_dirs_rad[i*2+0] =
SAF_PI/180.0f * grid_dirs_deg[i*2+0];
2044 grid_dirs_rad[i*2+1] =
SAF_PI/2.0f -
SAF_PI/180.0f * grid_dirs_deg[i*2+1];
2046 Ytmp =
malloc1d(nSH_grid*nGrid*
sizeof(
float));
2047 getSHreal(order_grid, grid_dirs_rad, nGrid, Ytmp);
2048 cblas_sscal(nSH_grid*nGrid,
SQRT4PI, Ytmp, 1);
2049 Y_grid =
calloc1d(nSH_grid*nGrid,
sizeof(float_complex));
2050 cblas_scopy(nSH_grid*nGrid, Ytmp, 1, (
float*)Y_grid, 2);
2053 alpha = powf(10.0f, amp_thresh_dB/20.0f);
2054 beta = 1.0f/(2.0f*alpha);
2058 for (kk=0; kk<nBins; kk++){
2062 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH_grid, nGrid, nGrid, &calpha,
2066 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasConjTrans, nSH_grid, nMics, nGrid, &calpha,
2068 &H_array[kk*nMics*nGrid], nGrid, &cbeta,
2070 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nMics, nGrid, nGrid, &calpha,
2071 &H_array[kk*nMics*nGrid], nGrid,
2074 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasConjTrans, nMics, nMics, nGrid, &calpha,
2076 &H_array[kk*nMics*nGrid], nGrid, &cbeta,
2080 for(i=0; i<nMics; i++)
2081 HWH_H[i*nMics+i] = craddf(HWH_H[i*nMics+i], beta*beta);
2083 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, nMics, nMics, &calpha,
2085 inv_HWH_H, nMics, &cbeta,
2086 &H_sht[kk*nSH*nMics], nMics);
2090 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nMics, nGrid, nGrid, &calpha,
2091 &H_array[kk*nMics*nGrid], nGrid,
2094 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasConjTrans, nMics, nSH_grid, nGrid, &calpha,
2096 Y_grid, nGrid, &cbeta,
2098 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH_grid, nGrid, nGrid, &calpha,
2102 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasConjTrans, nSH_grid, nSH_grid, nGrid, &calpha,
2104 Y_grid, nGrid, &cbeta,
2107 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nMics, nSH_grid, nSH_grid, &calpha,
2109 inv_YWY_T, nSH_grid, &cbeta,
2113 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasConjTrans, nMics, nMics, nSH_grid, &calpha,
2115 Q, nSH_grid, &cbeta,
2117 for(i=0; i<nMics; i++)
2118 QQ_H[i*nMics+i] = craddf(QQ_H[i*nMics+i], beta*beta);
2120 cblas_cgemm(CblasRowMajor, CblasConjTrans, CblasNoTrans, nSH , nMics, nMics, &calpha,
2122 inv_QQ_H, nMics, &cbeta,
2123 &H_sht[kk*nSH*nMics], nMics);
2130 free(grid_dirs_rad);
2158 float amp_thresh_dB,
2159 float_complex* H_array,
2160 float* grid_dirs_deg,
2168 int i, j, k, nBins, nSH;
2169 float_complex* H_sht, *H_sht_bins;
2175 H_sht =
malloc1d(nBins*nSH*nMics*
sizeof(float_complex));
2176 arraySHTmatrices(method, order, amp_thresh_dB, H_array, grid_dirs_deg, nBins, nMics, nGrid, w_grid, H_sht);
2179 H_sht_bins =
malloc1d(nBins*
sizeof(float_complex));
2181 for(i=0; i<nSH; i++){
2182 for(j=0; j<nMics; j++){
2183 for(k=0; k<nBins; k++)
2184 H_sht_bins[k] = H_sht[k*nSH*nMics + i*nMics + j];
2197 float_complex* H_sht,
2200 float alias_freq_hz,
2204 float_complex* H_sht_eq
2207 int i, kk, idxf_alias, nSH;
2208 float_complex* HD, *HDH_H, *EQ;
2210 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
2214 HD =
malloc1d(nSH*nMics*
sizeof(float_complex));
2215 HDH_H =
malloc1d(nSH*nSH*
sizeof(float_complex));
2216 L_diff_fal =
malloc1d(nSH*
sizeof(
float));
2217 EQ =
calloc1d(nSH*nSH,
sizeof(float_complex));
2221 while(freqVector[idxf_alias]<alias_freq_hz)
2223 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, nMics, nMics, &calpha,
2224 &H_sht[idxf_alias*nSH*nMics], nMics,
2225 &DCM[idxf_alias*nMics*nMics], nMics, &cbeta,
2227 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasConjTrans, nSH, nSH, nMics, &calpha,
2229 &H_sht[idxf_alias*nSH*nMics], nMics, &cbeta,
2231 for(i=0; i<nSH; i++)
2232 L_diff_fal[i] = crealf(HDH_H[i*nSH+i]);
2235 for(kk=0; kk<nBins; kk++){
2237 cblas_ccopy(nSH*nMics, &H_sht[kk*nSH*nMics], 1, &H_sht_eq[kk*nSH*nMics], 1);
2240 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, nMics, nMics, &calpha,
2241 &H_sht[kk*nSH*nMics], nMics,
2242 &DCM[kk*nMics*nMics], nMics, &cbeta,
2244 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasConjTrans, nSH, nSH, nMics, &calpha,
2246 &H_sht[kk*nSH*nMics], nMics, &cbeta,
2250 for(i=0; i<nSH; i++)
2251 EQ[i*nSH+i] = cmplxf(sqrtf(L_diff_fal[i]/crealf(HDH_H[i*nSH+i])), 0.0f);
2252 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, nMics, nSH, &calpha,
2254 &H_sht[kk*nSH*nMics], nMics, &cbeta,
2255 &H_sht_eq[kk*nSH*nMics], nMics);
2276 double*
Jn, *Jnprime;
2277 double_complex* Hn2, *Hn2prime;
2279 memset(b_N, 0, nBands*(order+1)*
sizeof(double_complex));
2284 Jn =
malloc1d(nBands*(order+1)*
sizeof(
double));
2288 for(n=0; n<order+1; n++)
2289 for(i=0; i<nBands; i++)
2290 b_N[i*(order+1)+n] = crmul(cpow(cmplx(0.0,1.0), cmplx((
double)n,0.0)),
Jn[i*(order+1)+n]);
2297 Jn =
malloc1d(nBands*(order+1)*
sizeof(
double));
2298 Jnprime =
malloc1d(nBands*(order+1)*
sizeof(
double));
2299 Hn2 =
malloc1d(nBands*(order+1)*
sizeof(double_complex));
2300 Hn2prime =
malloc1d(nBands*(order+1)*
sizeof(double_complex));
2305 for(i=0; i<nBands; i++){
2306 for(n=0; n<order+1; n++){
2307 if(n==0 && kr[i]<=1e-20)
2308 b_N[i*(order+1)+n] = cmplx(1.0, 0.0);
2309 else if(kr[i] <= 1e-20)
2310 b_N[i*(order+1)+n] = cmplx(0.0, 0.0);
2312 b_N[i*(order+1)+n] = ccmul(cpow(cmplx(0.0,1.0), cmplx((
double)n,0.0)), ( ccsub(cmplx(
Jn[i*(order+1)+n], 0.0),
2313 ccmul(ccdiv(cmplx(Jnprime[i*(order+1)+n],0.0), Hn2prime[i*(order+1)+n]), Hn2[i*(order+1)+n]))));
2338 return c*(float)maxN/(2.0f*
SAF_PI*r);
2356 double_complex* b_N;
2358 maxG = powf(10.0f, maxG_db/10.0f);
2360 for (n=1; n<maxN+1; n++){
2361 b_N =
malloc1d((n+1) *
sizeof(double_complex));
2363 kR_lim = powf(maxG*(
float)Nsensors* powf((
float)cabs(b_N[n])/(4.0f*
SAF_PI), 2.0f), (-10.0f*log10f(2.0f)/(6.0f*n)));
2364 f_lim[n-1] = kR_lim*c/(2.0f*
SAF_PI*r);
2379 int i, n, maxN, maxN_tmp;
2380 double* jn, *jnprime;
2381 double_complex* hn2, *hn2prime;
2383 memset(b_N, 0, nBands*(order+1)*
sizeof(double_complex));
2388 jn =
malloc1d(nBands*(order+1)*
sizeof(
double));
2392 for(n=0; n<maxN+1; n++)
2393 for(i=0; i<nBands; i++)
2394 b_N[i*(order+1)+n] = crmul(crmul(cpow(cmplx(0.0,1.0), cmplx((
double)n,0.0)), 4.0*
SAF_PId), jn[i*(order+1)+n]);
2401 jn =
malloc1d(nBands*(order+1)*
sizeof(
double));
2402 jnprime =
malloc1d(nBands*(order+1)*
sizeof(
double));
2406 for(n=0; n<maxN+1; n++)
2407 for(i=0; i<nBands; i++)
2408 b_N[i*(order+1)+n] = ccmul(crmul(cpow(cmplx(0.0,1.0), cmplx((
double)n,0.0)), 4.0*
SAF_PId), ccsub(cmplx(dirCoeff*jn[i*(order+1)+n], 0.0),
2409 cmplx(0.0, (1.0-dirCoeff)*jnprime[i*(order+1)+n])) );
2421 jn =
malloc1d(nBands*(order+1)*
sizeof(
double));
2422 jnprime =
malloc1d(nBands*(order+1)*
sizeof(
double));
2423 hn2 =
malloc1d(nBands*(order+1)*
sizeof(double_complex));
2424 hn2prime =
malloc1d(nBands*(order+1)*
sizeof(double_complex));
2427 maxN =
SAF_MIN(maxN_tmp, maxN);
2429 maxN =
SAF_MIN(maxN_tmp, maxN);
2432 for(i=0; i<nBands; i++){
2433 for(n=0; n<maxN+1; n++){
2434 if(n==0 && kr[i]<=1e-20)
2435 b_N[i*(order+1)+n] = cmplx(4.0*
SAF_PId, 0.0);
2436 else if(kr[i] <= 1e-20)
2437 b_N[i*(order+1)+n] = cmplx(0.0, 0.0);
2439 b_N[i*(order+1)+n] = ccmul(crmul(cpow(cmplx(0.0,1.0), cmplx((
double)n,0.0)), 4.0*
SAF_PId), ( ccsub(cmplx(jn[i*(order+1)+n], 0.0),
2440 ccmul(ccdiv(cmplx(jnprime[i*(order+1)+n],0.0), hn2prime[i*(order+1)+n]), hn2[i*(order+1)+n]))));
2462 int i, n, maxN, maxN_tmp;
2463 double* jn, *jnprime;
2464 double_complex* hn2, *hn2prime;
2467 jn =
malloc1d(nBands*(order+1)*
sizeof(
double));
2468 jnprime =
malloc1d(nBands*(order+1)*
sizeof(
double));
2469 hn2 =
malloc1d(nBands*(order+1)*
sizeof(double_complex));
2470 hn2prime =
malloc1d(nBands*(order+1)*
sizeof(double_complex));
2473 maxN =
SAF_MIN(maxN_tmp, maxN);
2475 maxN =
SAF_MIN(maxN_tmp, maxN);
2477 maxN =
SAF_MIN(maxN_tmp, maxN);
2479 maxN =
SAF_MIN(maxN_tmp, maxN);
2483 for(i=0; i<nBands; i++){
2484 for(n=0; n<maxN+1; n++){
2485 if(n==0 && kr[i]<=1e-20)
2486 b_N[i*(order+1)+n] = cmplx(4.0*
SAF_PId, 0.0);
2487 else if(kr[i] <= 1e-20)
2488 b_N[i*(order+1)+n] = cmplx(0.0, 0.0);
2490 b_N[i*(order+1)+n] = ccmul(crmul(cpow(cmplx(0.0,1.0), cmplx((
double)n,0.0)), 4.0*
SAF_PId), ( ccsub(cmplx(jn[i*(order+1)+n], 0.0),
2491 ccmul(ccdiv(cmplx(jnprime[i*(order+1)+n],0.0), hn2prime[i*(order+1)+n]), hn2[i*(order+1)+n]))));
2512 int i, n, maxN, maxN_tmp;
2513 double* jn_kr, *jnprime_kr, *jnprime_kR;
2514 double_complex* hn2_kr, *hn2prime_kr, *hn2prime_kR;
2517 jn_kr =
malloc1d(nBands*(order+1)*
sizeof(
double));
2518 jnprime_kr =
malloc1d(nBands*(order+1)*
sizeof(
double));
2519 jnprime_kR =
malloc1d(nBands*(order+1)*
sizeof(
double));
2520 hn2_kr =
malloc1d(nBands*(order+1)*
sizeof(double_complex));
2521 hn2prime_kr =
malloc1d(nBands*(order+1)*
sizeof(double_complex));
2522 hn2prime_kR =
malloc1d(nBands*(order+1)*
sizeof(double_complex));
2524 bessel_jn_ALL(order, kr, nBands, &maxN_tmp, jn_kr, jnprime_kr);
2525 maxN =
SAF_MIN(maxN_tmp, maxN);
2526 bessel_jn_ALL(order, kR, nBands, &maxN_tmp, NULL, jnprime_kR);
2527 maxN =
SAF_MIN(maxN_tmp, maxN);
2528 hankel_hn2_ALL(order, kr, nBands, &maxN_tmp, hn2_kr, hn2prime_kr);
2529 maxN =
SAF_MIN(maxN_tmp, maxN);
2531 maxN =
SAF_MIN(maxN_tmp, maxN);
2537 for(i=0; i<nBands; i++){
2538 for(n=0; n<maxN+1; n++){
2539 if(n==0 && kr[i]<=1e-20)
2540 b_N[i*(order+1)+n] = cmplx(4.0*
SAF_PId, 0.0);
2541 else if(kr[i] <= 1e-20)
2542 b_N[i*(order+1)+n] = cmplx(0.0, 0.0);
2549 b_N[i*(order+1)+n] = cmplx(dirCoeff * jn_kr[i*(order+1)+n], -(1.0-dirCoeff)* jnprime_kr[i*(order+1)+n]);
2550 b_N[i*(order+1)+n] = ccsub(b_N[i*(order+1)+n], ccmul(ccdiv(cmplx(jnprime_kR[i*(order+1)+n], 0.0), hn2prime_kR[i*(order+1)+n]),
2551 (ccsub(crmul(hn2_kr[i*(order+1)+n], dirCoeff), ccmul(cmplx(0.0f,1.0-dirCoeff), hn2prime_kr[i*(order+1)+n])))));
2552 b_N[i*(order+1)+n] = crmul(ccmul(cpow(cmplx(0.0,1.0), cmplx((
double)n,0.0)), b_N[i*(order+1)+n]), 4.0*
SAF_PId/dirCoeff);
2572 float* sensor_dirs_rad,
2583 float* sensor_dirs_xyz, *ppm, *ppm_z1, *ppm_z2;
2585 double_complex* b_N;
2588 sensor_dirs_xyz =
malloc1d(N_sensors*3*
sizeof(
float));
2589 for(i=0; i<N_sensors; i++){
2590 sensor_dirs_xyz[i*3] = cosf(sensor_dirs_rad[i*2+1]) * cosf(sensor_dirs_rad[i*2]);
2591 sensor_dirs_xyz[i*3+1] = cosf(sensor_dirs_rad[i*2+1]) * sinf(sensor_dirs_rad[i*2]);
2592 sensor_dirs_xyz[i*3+2] = sinf(sensor_dirs_rad[i*2+1]);
2596 b_N =
malloc1d(nBands * (order+1) *
sizeof(double_complex));
2597 b_N2 =
malloc1d(nBands * (order+1) *
sizeof(
double));
2608 for(i=0; i<nBands * (order+1); i++)
2609 b_N2[i] = pow(cabs(ccdiv(b_N[i], cmplx(4.0*
SAF_PId, 0.0))), 2.0);
2612 ppm =
malloc1d((order+1)*
sizeof(
float));
2613 ppm_z1 =
malloc1d((order+1)*
sizeof(
float));
2614 ppm_z2 =
malloc1d((order+1)*
sizeof(
float));
2615 Pn =
malloc1d((order+1)*
sizeof(
double));
2616 for(i=0; i<N_sensors; i++){
2617 for(j=i; j<N_sensors; j++){
2620 cosangle += sensor_dirs_xyz[j*3+k] * sensor_dirs_xyz[i*3+k];
2621 cosangle = cosangle>1.0f ? 1.0f : (cosangle<-1.0f ? -1.0f : cosangle);
2622 for(n=0; n<order+1; n++){
2624 Pn[n] = (2.0*(double)n+1.0) * 4.0f*
SAF_PI * (double)ppm[0];
2625 memcpy(ppm_z2, ppm_z1, (order+1)*
sizeof(
float));
2626 memcpy(ppm_z1, ppm, (order+1)*
sizeof(
float));
2628 cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nBands, 1, order+1, 1.0,
2631 &M_diffcoh[j*N_sensors*nBands + i*nBands], 1);
2633 memcpy(&M_diffcoh[i*N_sensors*nBands + j*nBands], &M_diffcoh[j*N_sensors*nBands + i*nBands], nBands*
sizeof(
double));
2639 free(sensor_dirs_xyz);
2648 float_complex* H_array,
2653 float_complex* M_diffcoh
2657 float_complex* W, *HW;
2658 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
2661 W =
calloc1d(nGrid*nGrid,
sizeof(float_complex));
2662 for(i=0; i<nGrid; i++)
2663 W[i*nGrid+i] = w_grid==NULL ? calpha : cmplxf(w_grid[i], 0.0f);
2666 HW =
malloc1d(nCH*nGrid*
sizeof(float_complex));
2667 for (kk=0; kk<nBins; kk++){
2668 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nCH, nGrid, nGrid, &calpha,
2669 &H_array[kk*nCH*nGrid], nGrid,
2672 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasConjTrans, nCH, nCH, nGrid, &calpha,
2674 &H_array[kk*nCH*nGrid], nGrid, &cbeta,
2675 &M_diffcoh[kk*nCH*nCH], nCH);
2696 W =
calloc1d(nGrid*nGrid,
sizeof(
float));
2697 for(i=0; i<nGrid; i++)
2698 W[i*nGrid+i] = w_grid==NULL ? 1.0f : w_grid[i];
2701 HW =
malloc1d(nCH*nGrid*
sizeof(float_complex));
2702 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nCH, nGrid, nGrid, 1.0f,
2706 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasTrans, nCH, nCH, nGrid, 1.0f,
2708 H_array, nGrid, 0.0f,
2721 float* sensor_dirs_rad,
2723 float* src_dirs_deg,
2726 float_complex* H_array
2731 double_complex* b_N, *C, *b_NC;
2732 const double_complex calpha = cmplx(1.0, 0.0), cbeta = cmplx(0.0, 0.0);
2735 b_N =
malloc1d(nBands * (order+1) *
sizeof(double_complex));
2739 C =
malloc1d((order+1)*N_sensors*
sizeof(double_complex));
2740 b_NC =
malloc1d(nBands*N_sensors*
sizeof(double_complex));
2741 for(i=0; i<N_srcs; i++){
2742 for(j=0; j<N_sensors; j++){
2743 angle = sensor_dirs_rad[i*2] - src_dirs_deg[i*2]*
SAF_PId/180.0;
2744 for(n=0; n<order+1; n++){
2747 C[n*N_sensors+j] = cmplx(1.0, 0.0);
2749 C[n*N_sensors+j] = cmplx(2.0*cos((
double)n*angle), 0.0);
2752 cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nBands, N_sensors, order+1, &calpha,
2754 C, N_sensors, &cbeta,
2758 for(band=0; band<nBands; band++)
2759 for(j=0; j<N_sensors; j++)
2760 H_array[band*N_sensors*N_srcs + j*N_srcs + i] = cmplxf((
float)creal(b_NC[band*N_sensors+j]), (
float)cimag(b_NC[band*N_sensors+j]));
2774 float* sensor_dirs_rad,
2776 float* src_dirs_deg,
2780 float_complex* H_array
2787 float* U_sensors, *U_srcs;
2788 double_complex* b_N, *P, *b_NP;
2789 const double_complex calpha = cmplx(1.0, 0.0), cbeta = cmplx(0.0, 0.0);
2792 b_N =
malloc1d(nBands * (order+1) *
sizeof(double_complex));
2808 U_sensors =
malloc1d(N_sensors*3*
sizeof(
float));
2809 U_srcs =
malloc1d(N_srcs*3*
sizeof(
float));
2810 unitSph2cart(sensor_dirs_rad, N_sensors, 0, U_sensors);
2814 ppm =
malloc1d((order+1)*
sizeof(
double));
2815 P =
malloc1d((order+1)*N_sensors*
sizeof(double_complex));
2816 b_NP =
malloc1d(nBands*N_sensors*
sizeof(double_complex));
2817 for(i=0; i<N_srcs; i++){
2818 for(j=0; j<N_sensors; j++){
2819 utility_svvdot((
const float*)&U_sensors[j*3], (
const float*)&U_srcs[i*3], 3, &cosangle);
2820 for(n=0; n<order+1; n++){
2822 dcosangle = (double)cosangle;
2824 P[n*N_sensors+j] = cmplx((2.0*(
double)n+1.0)/(4.0*
SAF_PId) * ppm[0], 0.0);
2827 cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nBands, N_sensors, order+1, &calpha,
2829 P, N_sensors, &cbeta,
2833 for(band=0; band<nBands; band++)
2834 for(j=0; j<N_sensors; j++)
2835 H_array[band*N_sensors*N_srcs + j*N_srcs + i] = cmplxf((
float)creal(b_NP[band*N_sensors+j]), (
float)cimag(b_NP[band*N_sensors+j]));
2849 float_complex* M_array2SH,
2852 float_complex* H_array,
2854 float_complex* Y_grid,
2862 int band, i, n, m, nSH, q;
2863 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
2864 float w_uni_grid, lSH_n, lSH_nm;
2865 float_complex cSH_n, cSH_nm, yre_yre_dot, yre_yid_dot;
2866 float_complex *y_recon_kk, *y_recon_nm, *w_y_recon_nm, *y_ideal_nm, *MH_M, *EigV;
2869 w_uni_grid = 1.0f/(float)nDirs;
2870 y_recon_kk =
malloc1d(nSH*nDirs*
sizeof(float_complex));
2871 y_recon_nm =
malloc1d(nDirs*
sizeof(float_complex));
2872 w_y_recon_nm =
malloc1d(nDirs*
sizeof(float_complex));
2873 y_ideal_nm =
malloc1d(nDirs*
sizeof(float_complex));
2874 MH_M =
malloc1d(nSensors*nSensors*
sizeof(float_complex));
2875 EigV =
malloc1d(nSensors*nSensors*
sizeof(float_complex));
2876 for(band=0; band<nBands; band++){
2877 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, nDirs, nSensors, &calpha,
2878 &M_array2SH[band*nSH*nSensors], nSensors,
2879 &H_array[band*nSensors*nDirs], nDirs, &cbeta,
2881 for(n=0; n<order+1; n++){
2882 cSH_n = cmplxf(0.0f, 0.0f);
2884 for(m=-n; m<=n; m++){
2886 for(i=0; i<nDirs; i++){
2887 y_recon_nm[i] = y_recon_kk[q*nDirs+i];
2888 w_y_recon_nm[i] = crmulf(y_recon_nm[i], w_uni_grid);
2889 y_ideal_nm[i] = Y_grid[q*nDirs+i];
2893 cSH_nm = ccdivf(yre_yid_dot, ccaddf(csqrtf(yre_yre_dot), cmplxf(2.23e-9f, 0.0f)));
2894 cSH_n = ccaddf(cSH_n, cSH_nm);
2895 lSH_nm = crealf(yre_yre_dot);
2898 cSH[band*(order+1)+n] =
SAF_MAX(
SAF_MIN(cabsf(cSH_n)/(2.0f*(
float)n+1.0f),1.0f),0.0f);
2899 lSH[band*(order+1)+n] = 10.0f*log10f(lSH_n/(2.0f*(
float)n+1.0f)+2.23e-9f);
2905 for(band=0; band<nBands; band++){
2906 cblas_cgemm(CblasRowMajor, CblasConjTrans, CblasNoTrans, nSensors, nSensors, nSH, &calpha,
2907 &M_array2SH[band*nSH*nSensors], nSensors,
2908 &M_array2SH[band*nSH*nSensors], nSensors, &cbeta,
2910 utility_ceig(NULL, MH_M, nSensors, 1, NULL, NULL, EigV);
2911 WNG[band] = 10.0f*log10f(crealf(EigV[0])+2.23e-9f);
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.
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)...
void arraySHTmatricesDiffEQ(float_complex *H_sht, float_complex *DCM, float *freqVector, float alias_freq_hz, int nBins, int order, int nMics, float_complex *H_sht_eq)
Diffuse-field equalisation of SHT matrices above the spatial aliasing frequency.
void sphMUSIC_destroy(void **const phMUSIC)
Destroys an instance of the spherical harmonic domain MUSIC implementation.
void unnorm_legendreP(int n, double *x, int lenX, double *y)
Calculates unnormalised Legendre polynomials up to order N, for all values in vector x [1].
void rotateAxisCoeffsComplex(int order, float *c_n, float theta_0, float phi_0, float_complex *c_nm)
Generates spherical coefficients for a rotated axisymmetric pattern (COMPLEX)
#define ORDER2NSH(order)
Converts spherical harmonic order to number of spherical harmonic components i.e: (order+1)^2.
void sphPWD_create(void **const phPWD, int order, float *grid_dirs_deg, int nDirs)
Creates an instance of a spherical harmonic domain implementation of the steer-response power (SRP) a...
void cylModalCoeffs(int order, double *kr, int nBands, ARRAY_CONSTRUCTION_TYPES arrayType, double_complex *b_N)
Calculates the modal coefficients for open/rigid cylindrical arrays.
void evaluateSHTfilters(int order, float_complex *M_array2SH, int nSensors, int nBands, float_complex *H_array, int nDirs, float_complex *Y_grid, float *cSH, float *lSH)
Generates some objective measures, which evaluate the performance of spatial encoding filters.
void sphMUSIC_compute(void *const hMUSIC, float_complex *Vn, int nSrcs, float *P_music, int *peak_inds)
Computes a pseudo-spectrum based on the MUSIC algorithm in the spherical harmonic domain; optionally ...
void sphESPRIT_create(void **const phESPRIT, int order)
Creates an instance of the spherical harmonic domain ESPRIT-based direction of arrival estimator.
float computeSectorCoeffsEP(int orderSec, float_complex *A_xyz, SECTOR_PATTERNS pattern, float *sec_dirs_deg, int nSecDirs, float *sectorCoeffs)
Computes beamforming matrices (sector coefficients) which, when applied to input SH signals,...
void unnorm_legendreP_recur(int n, float *x, int lenX, float *Pnm_minus1, float *Pnm_minus2, float *Pnm)
Calculates unnormalised Legendre polynomials up to order N, for all values in vector x.
int calculateGridWeights(float *dirs_rad, int nDirs, int order, float *w)
Computes approximation of quadrature/integration weights for a given grid.
void diffCohMtxMeas(float_complex *H_array, int nBins, int nCH, int nGrid, float *w_grid, float_complex *M_diffcoh)
Calculates the diffuse coherence matrices for an arbitrary array.
void getSHcomplex(int order, float *dirs_rad, int nDirs, float_complex *Y)
Computes complex-valued spherical harmonics [1] for each given direction on the unit sphere.
void beamWeightsVelocityPatternsReal(int order, float *b_n, float azi_rad, float elev_rad, float_complex *A_xyz, float *velCoeffs)
Generates beamforming coefficients for velocity patterns (REAL)
void sphMUSIC_create(void **const phMUSIC, int order, float *grid_dirs_deg, int nDirs)
Creates an instance of the spherical harmonic domain MUSIC implementation, which may be used for comp...
void beamWeightsVelocityPatternsComplex(int order, float *b_n, float azi_rad, float elev_rad, float_complex *A_xyz, float_complex *velCoeffs)
Generates beamforming coefficients for velocity patterns (COMPLEX)
void sphESPRIT_estimateDirs(void *const hESPRIT, float_complex *Us, int K, float *src_dirs_rad)
Estimates the direction-of-arrival (DoA) based on the ESPRIT-based estimator, in the spherical harmon...
void sphModalCoeffs(int order, double *kr, int nBands, ARRAY_CONSTRUCTION_TYPES arrayType, double dirCoeff, double_complex *b_N)
Calculates the modal coefficients for open/rigid spherical arrays.
void beamWeightsCardioid2Spherical(int N, float *b_n)
Generates spherical coefficients for generating cardioid beampatterns.
void beamWeightsMaxEV(int N, float *b_n)
Generates beamweights in the SHD for maximum energy-vector beampatterns.
void sphPWD_destroy(void **const phPWD)
Destroys an instance of the spherical harmonic domain PWD implementation.
void rotateAxisCoeffsReal(int order, float *c_n, float theta_0, float phi_0, float *c_nm)
Generates spherical coefficients for a rotated axisymmetric pattern (REAL)
float sphArrayAliasLim(float r, float c, int maxN)
Returns a simple estimate of the spatial aliasing limit (the kR = maxN rule)
void complex2realSHMtx(int order, float_complex *T_c2r)
Computes a complex to real spherical harmonic transform matrix.
void sphPWD_compute(void *const hPWD, float_complex *Cx, int nSrcs, float *P_map, int *peak_inds)
Computes a power-map based on determining the energy of hyper-cardioid beamformers; optionally,...
void diffCohMtxMeasReal(float *H_array, int nCH, int nGrid, float *w_grid, float *M_diffcoh)
Calculates the diffuse coherence matrices for an array that uses a broad-band real-valued basis.
void sphArrayNoiseThreshold(int maxN, int Nsensors, float r, float c, ARRAY_CONSTRUCTION_TYPES arrayType, double dirCoeff, float maxG_db, float *f_lim)
Computes the frequencies (per order), at which the noise of a SHT of a SMA exceeds a specified maximu...
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.
void beamWeightsHypercardioid2Spherical(int N, float *b_n)
Generates beamweights in the SHD for hypercardioid beampatterns.
void complex2realCoeffs(int order, float_complex *C_N, int K, float *R_N)
Converts SH coefficients from the complex to real basis.
ARRAY_CONSTRUCTION_TYPES
Microphone/Hydrophone array construction types.
void simulateCylArray(int order, double *kr, int nBands, float *sensor_dirs_rad, int N_sensors, float *src_dirs_deg, int N_srcs, ARRAY_CONSTRUCTION_TYPES arrayType, float_complex *H_array)
Simulates a cylindrical microphone array, returning the transfer functions for each (plane wave) sour...
void arraySHTmatrices(ARRAY_SHT_OPTIONS method, int order, float amp_thresh_dB, float_complex *H_array, float *grid_dirs_deg, int nBins, int nMics, int nGrid, float *w_grid, float_complex *H_sht)
Computes matrices required to transform array signals into spherical harmonic signals (frequency-doma...
void sphESPRIT_destroy(void **const phESPRIT)
Destroys an instance of the spherical harmonic domain ESPRIT-based direction of arrival estimator.
SECTOR_PATTERNS
Sector pattern designs for directionally-constraining sound-fields [1].
void simulateSphArray(int order, double *kr, double *kR, int nBands, float *sensor_dirs_rad, int N_sensors, float *src_dirs_deg, int N_srcs, ARRAY_CONSTRUCTION_TYPES arrayType, double dirCoeff, float_complex *H_array)
Simulates a spherical microphone array, returning the transfer functions for each (plane wave) source...
void getSHrotMtxReal(float Rxyz[3][3], float *RotMtx, int L)
Generates a real-valued spherical harmonic rotation matrix [1] based on a 3x3 rotation matrix (see qu...
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.
void arraySHTfilters(ARRAY_SHT_OPTIONS method, int order, float amp_thresh_dB, float_complex *H_array, float *grid_dirs_deg, int nFFT, int nMics, int nGrid, float *w_grid, float *h_sht)
Computes filters required to transform array signals into spherical harmonic signals (time-domain)
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.
void computeVelCoeffsMtx(int sectorOrder, float_complex *A_xyz)
Computes the matrices which generate the coefficients of a beampattern of order (sectorOrder+1) that ...
float computeSectorCoeffsAP(int orderSec, float_complex *A_xyz, SECTOR_PATTERNS pattern, float *sec_dirs_deg, int nSecDirs, float *sectorCoeffs)
Computes beamforming matrices (sector coefficients) which, when applied to input SH signals,...
void getSHreal(int order, float *dirs_rad, int nDirs, float *Y)
Computes real-valued spherical harmonics [1] for each given direction on the unit sphere.
void sphDiffCohMtxTheory(int order, float *sensor_dirs_rad, int N_sensors, ARRAY_CONSTRUCTION_TYPES arrayType, double dirCoeff, double *kr, int nBands, double *M_diffcoh)
Calculates the theoretical diffuse coherence matrix for a spherical array.
void sphScattererModalCoeffs(int order, double *kr, double *kR, int nBands, double_complex *b_N)
Calculates the modal coefficients for a rigid spherical scatterer with omni-directional sensors.
void checkCondNumberSHTReal(int order, float *dirs_rad, int nDirs, float *w, float *cond_N)
Computes the condition numbers for a least-squares SHT.
void real2complexSHMtx(int order, float_complex *T_r2c)
Computes a real to complex spherical harmonic transform matrix.
void sphScattererDirModalCoeffs(int order, double *kr, double *kR, int nBands, double dirCoeff, double_complex *b_N)
Calculates the modal coefficients for a rigid spherical scatterer with directional sensors.
ARRAY_SHT_OPTIONS
Microphone array to spherical harmonic domain conversion options.
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]
@ ARRAY_CONSTRUCTION_RIGID_DIRECTIONAL
Rigid baffle, directional sensors.
@ ARRAY_CONSTRUCTION_RIGID
Rigid baffle, omni-directional sensors.
@ ARRAY_CONSTRUCTION_OPEN_DIRECTIONAL
Open array, directional sensors.
@ ARRAY_CONSTRUCTION_OPEN
Open array, omni-directional sensors.
@ SECTOR_PATTERN_PWD
Plane-wave decomposition/Hyper-cardioid.
@ SECTOR_PATTERN_MAXRE
Spatially tapered hyper-cardioid, such that it has maximum energy concentrated in the look- direction...
@ SECTOR_PATTERN_CARDIOID
Cardioid pattern.
@ ARRAY_SHT_DEFAULT
The default SHT filters are ARRAY_SHT_REG_LS.
@ ARRAY_SHT_REG_LS
Regularised least-squares (LS)
@ ARRAY_SHT_REG_LSHD
Regularised least-squares (LS) in the SH domain (similar as in [1])
#define saf_print_error(message)
Macro to print a error message along with the filename and line number.
void bessel_jn_ALL(int N, double *z, int nZ, int *maxN, double *j_n, double *dj_n)
Computes the spherical Bessel function of the first kind (jn) and their derivatives (djn) for ALL ord...
void utility_zvvsub(const double_complex *a, const double_complex *b, const int len, double_complex *c)
Double-precision, complex, vector-vector subtraction, i.e.
#define saf_assert(x, message)
Macro to make an assertion, along with a string explaining its purpose.
#define SAF_PI
pi constant (single precision)
void hankel_hn2_ALL(int N, double *z, int nZ, int *maxN, double_complex *h_n2, double_complex *dh_n2)
Computes the spherical Hankel function of the second kind (hn2) and their derivatives (dhn2) for ALL ...
void utility_cglslv(void *const hWork, const float_complex *A, const int dim, float_complex *B, int nCol, float_complex *X)
General linear solver: single precision complex, i.e.
void utility_svvmul(const float *a, const float *b, const int len, float *c)
Single-precision, element-wise vector-vector multiplication i.e.
void utility_cinv(void *const hWork, float_complex *A, float_complex *B, const int N)
Matrix inversion: double precision complex, i.e.
#define SAF_MAX(a, b)
Returns the maximum of the two values.
#define SAF_PId
pi constant (double precision)
void utility_ssvd(void *const hWork, const float *A, const int dim1, const int dim2, float *U, float *S, float *V, float *sing)
Singular value decomposition: single precision, i.e.
#define FOURPI
4pi (single precision)
void utility_zeigmp(void *const hWork, const double_complex *A, const double_complex *B, const int dim, double_complex *VL, double_complex *VR, double_complex *D)
Computes eigenvalues of a matrix pair using the QZ method, double precision complex,...
void utility_cinv_destroy(void **const phWork)
De-allocate the working struct used by utility_cinv()
void utility_ceig(void *const hWork, const float_complex *A, const int dim, float_complex *VL, float_complex *VR, float_complex *D, float_complex *eig)
Eigenvalue decomposition of a NON-SYMMETRIC matrix: single precision complex, i.e.
void bessel_Jn_ALL(int N, double *z, int nZ, double *J_n, double *dJ_n)
Computes the (cylindrical) Bessel function of the first kind (Jn) and their derivatives (dJn) for ALL...
void utility_zglslv(void *const hWork, const double_complex *A, const int dim, double_complex *B, int nCol, double_complex *X)
General linear solver: double precision complex, i.e.
void utility_svvcopy(const float *a, const int len, float *c)
Single-precision, vector-vector copy, i.e.
void saf_rfft_create(void **const phFFT, int N)
Creates an instance of saf_rfft; real<->half-complex (conjugate-symmetric) FFT.
void utility_spinv(void *const hWork, const float *inM, const int dim1, const int dim2, float *outM)
General matrix pseudo-inverse (the svd way): single precision, i.e.
void utility_zglslv_destroy(void **const phWork)
De-allocate the working struct used by utility_zglslv()
void utility_cseig(void *const hWork, const float_complex *A, const int dim, int sortDecFLAG, float_complex *V, float_complex *D, float *eig)
Eigenvalue decomposition of a SYMMETRIC/HERMITION matrix: single precision complex,...
#define SAF_MIN(a, b)
Returns the minimum of the two values.
void utility_cvabs(const float_complex *a, const int len, float *c)
Single-precision, complex, absolute values of vector elements, i.e.
void utility_cvvdot(const float_complex *a, const float_complex *b, const int len, CONJ_FLAG flag, float_complex *c)
Single-precision, complex, vector-vector dot product, i.e.
void utility_cinv_create(void **const phWork, int maxN)
(Optional) Pre-allocate the working struct used by utility_cinv()
long double factorial(int n)
Factorial, accurate up to n<=25.
void utility_zpinv(void *const hWork, const double_complex *inM, const int dim1, const int dim2, double_complex *outM)
General matrix pseudo-inverse (the svd way): double precision complex, i.e.
void saf_rfft_backward(void *const hFFT, float_complex *inputFD, float *outputTD)
Performs the backward-FFT operation; use for complex (conjugate symmetric) to real transformations.
void saf_rfft_destroy(void **const phFFT)
Destroys an instance of saf_rfft.
void utility_zpinv_create(void **const phWork, int maxDim1, int maxDim2)
(Optional) Pre-allocate the working struct used by utility_zpinv()
void unitSph2cart(float *dirs, int nDirs, int anglesInDegreesFLAG, float *dirs_xyz)
Converts spherical coordinates to Cartesian coordinates of unit length.
#define saf_print_warning(message)
Macro to print a warning message along with the filename and line number.
void utility_zeigmp_destroy(void **const phWork)
De-allocate the working struct used by utility_zeigmp()
void hankel_Hn2_ALL(int N, double *z, int nZ, double_complex *H_n2, double_complex *dH_n2)
Computes the (cylindrical) Hankel function of the second kind (Hn2) and their derivatives (dHn2) for ...
void utility_zvvadd(const double_complex *a, const double_complex *b, const int len, double_complex *c)
Double-precision, complex, vector-vector addition, i.e.
void utility_svrecip(const float *a, const int len, float *c)
Single-precision, vector-reciprocal/inversion, i.e.
void utility_svvdot(const float *a, const float *b, const int len, float *c)
Single-precision, vector-vector dot product, i.e.
#define SQRT4PI
sqrt(4pi) (single precision)
void utility_zglslv_create(void **const phWork, int maxDim, int maxNCol)
(Optional) Pre-allocate the working struct used by utility_zglslv()
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_zeigmp_create(void **const phWork, int maxDim)
(Optional) Pre-allocate the working struct used by utility_zeigmp()
void utility_simaxv(const float *a, const int len, int *index)
Single-precision, index of maximum absolute value in a vector, i.e.
void utility_zpinv_destroy(void **const phWork)
De-allocate the working struct used by utility_zpinv()
void utility_cslslv(void *const hWork, const float_complex *A, const int dim, float_complex *B, int nCol, float_complex *X)
Linear solver for HERMITIAN positive-definate 'A': single precision complex, i.e.
@ NO_CONJ
Do not take the conjugate.
@ CONJ
Take the conjugate.
void ** malloc2d(size_t dim1, size_t dim2, size_t data_size)
2-D malloc (contiguously allocated, so use free() as usual to deallocate)
void ** realloc2d(void **ptr, size_t dim1, size_t dim2, size_t data_size)
2-D realloc which does NOT retain previous data order
void * malloc1d(size_t dim1_data_size)
1-D malloc (same as malloc, but with error checking)
void * calloc1d(size_t dim1, size_t data_size)
1-D calloc (same as calloc, but with error checking)
void * realloc1d(void *ptr, size_t dim1_data_size)
1-D realloc (same as realloc, but with error checking)
#define FLATTEN2D(A)
Use this macro when passing a 2-D dynamic multi-dimensional array to memset, memcpy or any other func...
const float wxyzCoeffs[4][4]
First-order ACN/N3D to FuMa [without sqrt(4pi) term] conversion matrix.
Main header for the Spherical Harmonic Transform and Spherical Array Processing module (SAF_SH_MODULE...
void getVnimu(int order, int ni, int mu, double *Vnimu)
Helper function for sphESPRIT_create()
float getV(int M, int l, int m, int n, float R_1[3][3], float *R_lm1)
Helper function for getSHrotMtxReal()
void gaunt_mtx(int N1, int N2, int N, float *A)
Constructs a matrix of Guant coefficients.
float getU(int M, int l, int m, int n, float R_1[3][3], float *R_lm1)
Helper function for getSHrotMtxReal()
float getW(int M, int l, int m, int n, float R_1[3][3], float *R_lm1)
Helper function for getSHrotMtxReal()
void getWnimu(int order, int mm, int ni, int mu, double *Wnimu)
Helper function for sphESPRIT_create()
void muni2q(int order, int ni, int mu, int *idx_nimu, int *idx_nm)
Helper function for sphESPRIT_create()
Internal header for the Spherical Harmonic Transform and Spherical Array Processing module (SAF_SH_MO...
static double Jn(int n, double z)
Wrapper for the cylindrical Bessel function of the first kind.
Internal data structure for sphESPRIT.
Internal data structure for sphMUSIC.
Internal data structure for sphPWD.