46 saf_assert(include_rt_vars==0 || include_rt_vars==1,
"include_rt_vars is a bool");
84 ec->
value = (
float**)
realloc2d((
void**)ec->
value, nChannels, numImageSources,
sizeof(float));
101 for(i=0; i<numImageSources; i++)
115 int nChannels, numImageSources;
117 saf_assert(hEchoX!=NULL && hEchoY!=NULL,
"Echograms must be allocated first");
132 cblas_scopy(numImageSources, ecX->
time, 1, ecY->
time, 1);
188 wrk->numImageSources = 0;
189 memset(wrk->
room, 0, 3*
sizeof(
int));
197 wrk->validIDs = NULL;
198 wrk->II = wrk->JJ = wrk->KK = NULL;
199 wrk->iII = wrk->iJJ = wrk->iKK = NULL;
200 wrk->s_x = wrk->s_y = wrk->s_z = wrk->s_d = NULL;
201 wrk->s_t = wrk->s_att = NULL;
210 for(band=0; band<nBands; band++){
216 wrk->refreshRIRFLAG = 1;
217 wrk->rir_len_samples = 0;
218 wrk->rir_len_seconds = 0.0f;
219 wrk->rir_bands = (
float***)
malloc1d(nBands*
sizeof(
float**));
220 for(band=0; band < nBands; band++)
221 wrk->rir_bands[band] = NULL;
252 for(band=0; band< wrk->
nBands; band++){
260 for(band=0; band < wrk->
nBands; band++)
261 free(wrk->rir_bands[band]);
286 d_max = maxTime_s*c_ms;
289 src_orig.
x = src.
x - room[0]/2.0f;
290 src_orig.
y = room[1]/2.0f - src.
y;
291 src_orig.
z = src.
z - room[2]/2.0f;
292 rec_orig.
x = rec.
x - room[0]/2.0f;
293 rec_orig.
y = room[1]/2.0f - rec.
y;
294 rec_orig.
z = rec.
z - room[2]/2.0f;
297 if( (wrk->
d_max != d_max) ||
298 (wrk->
room[0] != room[0]) || (wrk->
room[1] != room[1]) || (wrk->
room[2] != room[2]) )
300 wrk->Nx = (int)(d_max/room[0] + 1.0f);
301 wrk->Ny = (int)(d_max/room[1] + 1.0f);
302 wrk->Nz = (int)(d_max/room[2] + 1.0f);
303 wrk->lengthVec = (2*(wrk->Nx)+1) * (2*(wrk->Ny)+1) * (2*(wrk->Nz)+1);
306 wrk->II =
realloc1d(wrk->II, wrk->lengthVec*
sizeof(
float));
307 wrk->JJ =
realloc1d(wrk->JJ, wrk->lengthVec*
sizeof(
float));
308 wrk->KK =
realloc1d(wrk->KK, wrk->lengthVec*
sizeof(
float));
309 ii = -(wrk->Nx); jj = -(wrk->Ny); kk = -(wrk->Nz);
310 for(imsrc = 0; imsrc<wrk->lengthVec; imsrc++){
311 wrk->II[imsrc] = (float)ii;
312 wrk->JJ[imsrc] = (float)jj;
313 wrk->KK[imsrc] = (float)kk;
329 wrk->validIDs =
realloc1d(wrk->validIDs, wrk->lengthVec*
sizeof(
int));
330 wrk->s_x =
realloc1d(wrk->s_x, wrk->lengthVec*
sizeof(
float));
331 wrk->s_y =
realloc1d(wrk->s_y, wrk->lengthVec*
sizeof(
float));
332 wrk->s_z =
realloc1d(wrk->s_z, wrk->lengthVec*
sizeof(
float));
333 wrk->s_d =
realloc1d(wrk->s_d, wrk->lengthVec*
sizeof(
float));
334 wrk->s_t =
realloc1d(wrk->s_t, wrk->lengthVec*
sizeof(
float));
335 wrk->s_att =
realloc1d(wrk->s_att, wrk->lengthVec*
sizeof(
float));
339 if( (wrk->
d_max != d_max) ||
340 (wrk->
rec.
x != rec_orig.
x) || (wrk->
rec.
y != rec_orig.
y) || (wrk->
rec.
z != rec_orig.
z) ||
341 (wrk->
src.
x != src_orig.
x) || (wrk->
src.
y != src_orig.
y) || (wrk->
src.
z != src_orig.
z) ||
342 (wrk->
room[0] != room[0]) || (wrk->
room[1] != room[1]) || (wrk->
room[2] != room[2]))
345 wrk->
room[0] = room[0];
346 wrk->
room[1] = room[1];
347 wrk->
room[2] = room[2];
352 for(imsrc = 0; imsrc<wrk->lengthVec; imsrc++){
353 wrk->s_x[imsrc] = wrk->II[imsrc]*room[0] + powf(-1.0f, wrk->II[imsrc])*src_orig.
x - rec_orig.
x;
354 wrk->s_y[imsrc] = wrk->JJ[imsrc]*room[1] + powf(-1.0f, wrk->JJ[imsrc])*src_orig.
y - rec_orig.
y;
355 wrk->s_z[imsrc] = wrk->KK[imsrc]*room[2] + powf(-1.0f, wrk->KK[imsrc])*src_orig.
z - rec_orig.
z;
356 wrk->s_d[imsrc] = sqrtf(powf(wrk->s_x[imsrc], 2.0f) + powf(wrk->s_y[imsrc], 2.0f) + powf(wrk->s_z[imsrc], 2.0f));
360 for(imsrc = 0, wrk->numImageSources = 0; imsrc<wrk->lengthVec; imsrc++){
361 if(wrk->s_d[imsrc]<d_max){
362 wrk->validIDs[imsrc] = 1;
363 wrk->numImageSources++;
366 wrk->validIDs[imsrc] = 0;
373 for(imsrc = 0, vIdx = 0; imsrc<wrk->lengthVec; imsrc++){
374 if(wrk->validIDs[imsrc]){
375 echogram->
time[vIdx] = wrk->s_d[imsrc]/c_ms;
379 echogram->
value[0][vIdx] = wrk->s_d[imsrc]<=1 ? 1.0f : 1.0f / wrk->s_d[imsrc];
382 echogram->
order[vIdx][0] = (int)(wrk->II[imsrc] + (wrk->II[imsrc]>0 ? 0.1f : -0.1f));
383 echogram->
order[vIdx][1] = (int)(wrk->JJ[imsrc] + (wrk->JJ[imsrc]>0 ? 0.1f : -0.1f));
384 echogram->
order[vIdx][2] = (int)(wrk->KK[imsrc] + (wrk->KK[imsrc]>0 ? 0.1f : -0.1f));
387 echogram->
coords[vIdx].
x = wrk->s_x[imsrc];
388 echogram->
coords[vIdx].
y = wrk->s_y[imsrc];
389 echogram->
coords[vIdx].
z = wrk->s_z[imsrc];
416 src_orig.
x = src.
x - room[0]/2.0f;
417 src_orig.
y = room[1]/2.0f - src.
y;
418 src_orig.
z = src.
z - room[2]/2.0f;
419 rec_orig.
x = rec.
x - room[0]/2.0f;
420 rec_orig.
y = room[1]/2.0f - rec.
y;
421 rec_orig.
z = rec.
z - room[2]/2.0f;
424 if( (wrk->
N_max != maxN) )
426 wrk->lengthVec = (2*(maxN)+1) * (2*(maxN)+1) * (2*(maxN)+1);
429 wrk->iII =
realloc1d(wrk->iII, wrk->lengthVec*
sizeof(
int));
430 wrk->iJJ =
realloc1d(wrk->iJJ, wrk->lengthVec*
sizeof(
int));
431 wrk->iKK =
realloc1d(wrk->iKK, wrk->lengthVec*
sizeof(
int));
432 wrk->s_ord =
realloc1d(wrk->s_ord, wrk->lengthVec*
sizeof(
int));
433 ii = -maxN; jj = -maxN; kk = -maxN;
434 for(imsrc = 0; imsrc<wrk->lengthVec; imsrc++){
435 wrk->iII[imsrc] = ii;
436 wrk->iJJ[imsrc] = jj;
437 wrk->iKK[imsrc] = kk;
438 wrk->s_ord[imsrc] = abs(wrk->iII[imsrc]) + abs(wrk->iJJ[imsrc]) + abs(wrk->iKK[imsrc]);
454 wrk->II =
realloc1d(wrk->II, wrk->lengthVec*
sizeof(
float));
455 wrk->JJ =
realloc1d(wrk->JJ, wrk->lengthVec*
sizeof(
float));
456 wrk->KK =
realloc1d(wrk->KK, wrk->lengthVec*
sizeof(
float));
457 for(imsrc = 0, wrk->numImageSources = 0; imsrc<wrk->lengthVec; imsrc++){
458 if(wrk->s_ord[imsrc]<=maxN){
459 wrk->II[wrk->numImageSources] = (float)wrk->iII[imsrc];
460 wrk->JJ[wrk->numImageSources] = (float)wrk->iJJ[imsrc];
461 wrk->KK[wrk->numImageSources] = (float)wrk->iKK[imsrc];
462 wrk->numImageSources++;
467 wrk->s_x =
realloc1d(wrk->s_x, wrk->numImageSources*
sizeof(
float));
468 wrk->s_y =
realloc1d(wrk->s_y, wrk->numImageSources*
sizeof(
float));
469 wrk->s_z =
realloc1d(wrk->s_z, wrk->numImageSources*
sizeof(
float));
470 wrk->s_d =
realloc1d(wrk->s_d, wrk->numImageSources*
sizeof(
float));
471 wrk->s_t =
realloc1d(wrk->s_t, wrk->numImageSources*
sizeof(
float));
472 wrk->s_att =
realloc1d(wrk->s_att, wrk->numImageSources*
sizeof(
float));
476 if( (wrk->
N_max != maxN) ||
477 (wrk->
rec.
x != rec_orig.
x) || (wrk->
rec.
y != rec_orig.
y) || (wrk->
rec.
z != rec_orig.
z) ||
478 (wrk->
src.
x != src_orig.
x) || (wrk->
src.
y != src_orig.
y) || (wrk->
src.
z != src_orig.
z) ||
479 (wrk->
room[0] != room[0]) || (wrk->
room[1] != room[1]) || (wrk->
room[2] != room[2]))
482 wrk->
room[0] = room[0];
483 wrk->
room[1] = room[1];
484 wrk->
room[2] = room[2];
489 for(imsrc = 0; imsrc<wrk->numImageSources; imsrc++){
490 wrk->s_x[imsrc] = wrk->II[imsrc]*room[0] + powf(-1.0f, wrk->II[imsrc])*src_orig.
x - rec_orig.
x;
491 wrk->s_y[imsrc] = wrk->JJ[imsrc]*room[1] + powf(-1.0f, wrk->JJ[imsrc])*src_orig.
y - rec_orig.
y;
492 wrk->s_z[imsrc] = wrk->KK[imsrc]*room[2] + powf(-1.0f, wrk->KK[imsrc])*src_orig.
z - rec_orig.
z;
493 wrk->s_d[imsrc] = sqrtf(powf(wrk->s_x[imsrc], 2.0f) + powf(wrk->s_y[imsrc], 2.0f) + powf(wrk->s_z[imsrc], 2.0f));
500 for(imsrc = 0; imsrc<wrk->numImageSources; imsrc++){
501 echogram->
time[imsrc] = wrk->s_d[imsrc]/c_ms;
505 echogram->
value[0][imsrc] = wrk->s_d[imsrc]<=1 ? 1.0f : 1.0f / wrk->s_d[imsrc];
508 echogram->
order[imsrc][0] = (int)(wrk->II[imsrc] + (wrk->II[imsrc]>0 ? 0.1f : -0.1f));
509 echogram->
order[imsrc][1] = (int)(wrk->JJ[imsrc] + (wrk->JJ[imsrc]>0 ? 0.1f : -0.1f));
510 echogram->
order[imsrc][2] = (int)(wrk->KK[imsrc] + (wrk->KK[imsrc]>0 ? 0.1f : -0.1f));
513 echogram->
coords[imsrc].
x = wrk->s_x[imsrc];
514 echogram->
coords[imsrc].
y = wrk->s_y[imsrc];
515 echogram->
coords[imsrc].
z = wrk->s_z[imsrc];
533 float aziElev_rad[2];
561 sh_gains =
malloc1d(nSH*
sizeof(
float));
565 aziElev_rad[1] =
SAF_PI/2.0f-aziElev_rad[1];
585 float r_x[2], r_y[2], r_z[2];
586 float abs_x, abs_y, abs_z, s_abs_tot;
588 for(band=0; band < wrk->
nBands; band++){
598 r_x[0] = sqrtf(1.0f - abs_wall[band][0]);
599 r_x[1] = sqrtf(1.0f - abs_wall[band][1]);
600 r_y[0] = sqrtf(1.0f - abs_wall[band][2]);
601 r_y[1] = sqrtf(1.0f - abs_wall[band][3]);
602 r_z[0] = sqrtf(1.0f - abs_wall[band][4]);
603 r_z[1] = sqrtf(1.0f - abs_wall[band][5]);
609 if((echogram_abs->
order[i][0]%2)==0)
610 abs_x = powf(r_x[0], (
float)abs(echogram_abs->
order[i][0])/2.0f) * powf(r_x[1], (
float)abs(echogram_abs->
order[i][0])/2.0f);
611 else if (echogram_abs->
order[i][0]>0)
612 abs_x = powf(r_x[0], ceilf((
float)echogram_abs->
order[i][0]/2.0f)) * powf(r_x[1], floorf((
float)echogram_abs->
order[i][0]/2.0f));
614 abs_x = powf(r_x[0], floorf((
float)abs(echogram_abs->
order[i][0])/2.0f)) * powf(r_x[1], ceilf((
float)abs(echogram_abs->
order[i][0])/2.0f));
617 if((echogram_abs->
order[i][1]%2)==0)
618 abs_y = powf(r_y[0], (
float)abs(echogram_abs->
order[i][1])/2.0f) * powf(r_y[1], (
float)abs(echogram_abs->
order[i][1])/2.0f);
619 else if (echogram_abs->
order[i][1]>0)
620 abs_y = powf(r_y[0], ceilf((
float)echogram_abs->
order[i][1]/2.0f)) * powf(r_y[1], floorf((
float)echogram_abs->
order[i][1]/2.0f));
622 abs_y = powf(r_y[0], floorf((
float)abs(echogram_abs->
order[i][1])/2.0f)) * powf(r_y[1], ceilf((
float)abs(echogram_abs->
order[i][1])/2.0f));
625 if((echogram_abs->
order[i][2]%2)==0)
626 abs_z = powf(r_z[0], (
float)abs(echogram_abs->
order[i][2])/2.0f) * powf(r_z[1], (
float)abs(echogram_abs->
order[i][2])/2.0f);
627 else if (echogram_abs->
order[i][2]>0)
628 abs_z = powf(r_z[0], ceilf((
float)echogram_abs->
order[i][2]/2.0f)) * powf(r_z[1], floorf((
float)echogram_abs->
order[i][2]/2.0f));
630 abs_z = powf(r_z[0], floorf((
float)abs(echogram_abs->
order[i][2])/2.0f)) * powf(r_z[1], ceilf((
float)abs(echogram_abs->
order[i][2])/2.0f));
633 s_abs_tot = abs_x * abs_y * abs_z;
634 for(ch=0; ch<echogram_abs->
nChannels; ch++)
635 echogram_abs->
value[ch][i] *= s_abs_tot;
643 int fractionalDelayFLAG,
652 int i, j, refl_idx, band, rir_len_samples;
653 float endtime, rir_len_seconds;
656 for(band=0; band<wrk->
nBands; band++){
661 rir_len_samples = (int)(endtime * fs + 1.0f) + 1;
662 rir_len_seconds = (float)rir_len_samples/fs;
665 if(fractionalDelayFLAG){
671 wrk->rir_bands[band] = (
float**)
realloc2d((
void**)wrk->rir_bands[band], echogram_abs->
nChannels, rir_len_samples,
sizeof(float));
672 wrk->rir_len_samples = rir_len_samples;
673 wrk->rir_len_seconds = rir_len_seconds;
674 memset(
FLATTEN2D(wrk->rir_bands[band]), 0, (echogram_abs->
nChannels)*rir_len_samples*
sizeof(
float));
678 refl_idx = (int)(echogram_abs->
time[i]*fs+0.5f);
680 wrk->rir_bands[band][j][refl_idx] += echogram_abs->
value[j][i];
689 if( (echogram_abs->
nChannels!=rir->nChannels) || (wrk->rir_len_samples !=rir->length) ){
690 rir->data =
realloc1d(rir->data, echogram_abs->
nChannels * (wrk->rir_len_samples) *
sizeof(
float));
691 rir->length = wrk->rir_len_samples;
692 rir->nChannels = echogram_abs->
nChannels;
694 memset(rir->data, 0, echogram_abs->
nChannels * (wrk->rir_len_samples) *
sizeof(
float));
697 for(band=0; band<wrk->
nBands; band++){
706 cblas_saxpy(wrk->rir_len_samples, 1.0f, wrk->rir_bands[band][i], 1, &(rir->data[i*(wrk->rir_len_samples)]), 1);
#define ORDER2NSH(order)
Converts spherical harmonic order to number of spherical harmonic components i.e: (order+1)^2.
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.
#define saf_print_error(message)
Macro to print a error message along with the filename and line number.
#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 sortf(float *in_vec, float *out_vec, int *new_idices, int len, int descendFLAG)
Sort a vector of floating-point values into ascending/decending order (optionally returning the new i...
void fftconv(float *x, float *h, int x_len, int h_len, int nCH, float *y)
FFT-based convolution of signal 'x' with filter 'h'.
void unitCart2sph(float *dirs_xyz, int nDirs, int anglesInDegreesFLAG, float *dirs)
Converts Cartesian coordinates of unit length to spherical coordinates.
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 * 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...
Main header for the reverb processing module (SAF_REVERB_MODULE)
void ims_shoebox_coreWorkspaceCreate(void **phWork, int nBands)
Creates an instance of the core workspace.
void ims_shoebox_coreInitT(void *hWork, float room[3], ims_pos_xyz src, ims_pos_xyz rec, float maxTime_s, float c_ms)
Calculates an echogram of a rectangular space using the image source method, for a specific source/re...
void ims_shoebox_coreWorkspaceDestroy(void **phWork)
Destroys an instance of the core workspace.
void ims_shoebox_coreRecModuleSH(void *hWork, int sh_order)
Imposes spherical harmonic directivies onto the echogram computed with ims_shoebox_coreInit() for a s...
void ims_shoebox_echogramResize(void *hEcho, int numImageSources, int nChannels)
Resizes an echogram container.
void ims_shoebox_coreAbsorptionModule(void *hWork, float **abs_wall)
Applies boundary absoption per frequency band, onto the echogram computed with ims_shoebox_coreRecMod...
void ims_shoebox_renderRIR(void *hWork, int fractionalDelayFLAG, float fs, float **H_filt, ims_rir *rir)
Renders a room impulse response for a specific source/reciever combination.
void ims_shoebox_echogramCreate(void **phEcho, int include_rt_vars)
Creates an instance of an echogram container.
void ims_shoebox_echogramCopy(void *hEchoX, void *hEchoY)
Copies echogram data from container 'X' into container 'Y' (also resizing 'Y' as needed)
void ims_shoebox_coreInitN(void *hWork, float room[3], ims_pos_xyz src, ims_pos_xyz rec, int maxN, float c_ms)
Calculates an echogram of a rectangular space using the image source method, for a specific source/re...
void ims_shoebox_echogramDestroy(void **phEcho)
Destroys an instance of an echogram container.
Internal header for the reverb processing module (SAF_REVERB_MODULE)
#define IMS_LAGRANGE_ORDER
Order of lagrange interpolation filters.
void * voidPtr
Void pointer (just to improve code readability when working with arrays of handles)
#define IMS_FIR_FILTERBANK_ORDER
FIR filter order (must be even)
float ** value
Echogram magnitudes per image source and channel; nChannels x numImageSources.
float ** contrib
Total contribution (i.e.
int numImageSources
Number of image sources in current echogram.
int ** order
Reflection order for each image and dimension; numImageSources x 3.
int * rIdx_frac[IMS_LAGRANGE_ORDER]
Current circular buffer read indices for fractional buffers; IMS_LAGRANGE_ORDER x numImageSources.
int * rIdx
Current circular buffer read indices; numImageSources x 1.
ims_pos_xyz * coords
Reflection coordinates (Cartesian); numImageSources x 3.
int nChannels
Number of channels.
float ** h_frac
Current fractional delay coeffs; (IMS_LAGRANGE_ORDER+1) x numImageSources x.
float ** cb_vals
Current circular buffer values (per channel & image source); nChannels x numImageSources.
int include_rt_vars
0: the below vars are disabled, 1: enabled
float * time
Propagation time (in seconds) for each image source; numImageSources x 1.
int * sortedIdx
Indices that sort the echogram based on propagation time in ascending order; numImageSources x 1.
float * tmp1
1st temporary vector; numImageSources x 1
float * ones_dummy
Just a vector of ones, for the cblas_sdot sum hack, and fmodf; numImageSources x 1.
float * tmp2
2nd temporary vector; numImageSources x 1
Helper structure, comprising variables used when computing echograms and rendering RIRs.
float room[3]
Room dimensions, in meters.
void * hEchogram_rec
Echogram with the receiver directivities applied (multi-channel)
voidPtr * hPrevEchogram_abs
Previous echograms (hEchogram_abs), one per band, which can be used for cross- fading.
ims_pos_xyz rec
Receiver position.
voidPtr * hEchogram_abs
Echograms with the receiver directivities and also wall absorption applied (multi- channel); one echo...
int refreshEchogramFLAG
1: Refresh needed, 0: refresh not needed
void * hEchogram
Pressure echogram (single-channel)
int N_max
Maximum reflection order.
ims_pos_xyz src
Source position.
int nBands
Number of bands.
float d_max
Maximum distance, in meters.
Union struct for Cartesian coordinates (access as .x,.y,.z, or .v[3])
float y
y Cartesian coordinate, in metres
float z
z Cartesian coordinate, in metres
float v[3]
x,y,z Cartesian coordinates, in metres
float x
x Cartesian coordinate, in metres
Output format of the rendered room impulse responses (RIR)