39 float roomDimensions[3],
41 float lowestOctaveBand,
62 for(band=1; band<nOctBands; band++)
78 for(band=0; band<sc->
nBands; band++)
103 sc->
rirs[i][j].data = NULL;
104 sc->
rirs[i][j].length = sc->
rirs[i][j].nChannels = 0;
159 free(sc->
rirs[i][j].data);
194 int src_idx, rec_idx, band;
196 saf_assert(maxN<0 || maxTime_ms<0.0f,
"one of these input arguments must be the same or greater than 0, and the other one must be less than 0.");
197 saf_assert(maxN>=0 || maxTime_ms>0.0f,
"one of these input arguments must be the same or greater than 0, and the other one must be less than 0.");
216 for(band=0; band<workspace->
nBands; band++)
221 if(workspace->
d_max != maxTime_ms)
225 if(workspace->
N_max != maxN)
249 workspace->refreshRIRFLAG = 1;
252 sc->applyCrossFadeFLAG[rec_idx][src_idx] = 1;
262 int fractionalDelayFLAG
267 int src_idx, rec_idx;
286 if(wrk->refreshRIRFLAG){
290 wrk->refreshRIRFLAG = 0;
302 int fractionalDelaysFLAG
308 int k, i, n, im, band, ch, rec_idx, src_idx, time_samples, wIdx_n;
311 saf_assert(fractionalDelaysFLAG==0,
"Untested!");
335 if(sc->
recs[i].
ID == receiverID){
352 for(i=0; i<nSamples; i++){
360 memset(sc->
recs[rec_idx].
sigs[ch], 0, nSamples *
sizeof(
float));
377 for(k=sc->applyCrossFadeFLAG[rec_idx][src_idx]; k>=0; k--){
380 for(n=0; n<nSamples; n++){
398 for(band=0; band < sc->
nBands; band++){
400 if(sc->applyCrossFadeFLAG[rec_idx][src_idx]==0)
405 sc->
wIdx[k][rec_idx][src_idx]++;
406 if(sc->applyCrossFadeFLAG[rec_idx][src_idx]==0)
417 if(fractionalDelaysFLAG){
421 time_samples = (int)(echogram_abs_0->
tmp1[im]);
437 echogram_abs_0->
rIdx_frac[i-1][im] = echogram_abs_0->
rIdx[im] - i;
450 time_samples = (int)(echogram_abs_0->
tmp1[im] + 0.5f);
457 for(band=0; band < sc->
nBands; band++){
469 if(fractionalDelaysFLAG){
500 1, echogram_abs->
contrib[ch], 1);
504 if(sc->applyCrossFadeFLAG[rec_idx][src_idx]==0)
509 sc->
wIdx[k][rec_idx][src_idx]++;
510 if(sc->applyCrossFadeFLAG[rec_idx][src_idx]==0)
517 if(sc->applyCrossFadeFLAG[rec_idx][src_idx]){
527 sc->applyCrossFadeFLAG[rec_idx][src_idx] = 0;
544 float new_roomDimensions[3]
548 int rec_idx, src_idx;
551 if( (sc->
room_dims[0]!=new_roomDimensions[0]) ||
552 (sc->
room_dims[1]!=new_roomDimensions[1]) ||
553 (sc->
room_dims[2]!=new_roomDimensions[2]) )
555 sc->
room_dims[0] = new_roomDimensions[0];
556 sc->
room_dims[1] = new_roomDimensions[1];
557 sc->
room_dims[2] = new_roomDimensions[2];
574 int band, i, updateRequired, rec_idx, src_idx;
578 for(band=0; band<sc->
nBands; band++){
580 if(sc->
abs_wall[band][i] != abs_wall[band*6 + i]){
581 sc->
abs_wall[band][i] = abs_wall[band*6 + i];
636 sc->
srcs[obj_idx].
pos.
x = src_xyz[0];
637 sc->
srcs[obj_idx].
pos.
y = src_xyz[1];
638 sc->
srcs[obj_idx].
pos.
z = src_xyz[2];
639 sc->
srcs[obj_idx].
sig = pSrc_sig == NULL ? NULL : *pSrc_sig;
646 return sc->
srcs[obj_idx].
ID;
689 sc->
recs[obj_idx].
pos.
x = rec_xyz[0];
690 sc->
recs[obj_idx].
pos.
y = rec_xyz[1];
691 sc->
recs[obj_idx].
pos.
z = rec_xyz[2];
692 sc->
recs[obj_idx].
sigs = pSH_sigs == NULL ? NULL : *pSH_sigs;
701 return sc->
recs[obj_idx].
ID;
708 float new_position_xyz[3]
715 saf_assert(sourceID >= 0,
"Invalid sourceID");
720 if(sc->
srcs[i].
ID == sourceID){
728 if( (new_position_xyz[0] != sc->
srcs[src_idx].
pos.
x) ||
729 (new_position_xyz[1] != sc->
srcs[src_idx].
pos.
y) ||
730 (new_position_xyz[2] != sc->
srcs[src_idx].
pos.
z))
733 sc->
srcs[src_idx].
pos.
x = new_position_xyz[0];
734 sc->
srcs[src_idx].
pos.
y = new_position_xyz[1];
735 sc->
srcs[src_idx].
pos.
z = new_position_xyz[2];
752 float new_position_xyz[3]
759 saf_assert(receiverID >= 0,
"Invalid receiverID");
764 if(sc->
recs[i].
ID == receiverID){
772 if( (new_position_xyz[0] != sc->
recs[rec_idx].
pos.
x) ||
773 (new_position_xyz[1] != sc->
recs[rec_idx].
pos.
y) ||
774 (new_position_xyz[2] != sc->
recs[rec_idx].
pos.
z))
777 sc->
recs[rec_idx].
pos.
x = new_position_xyz[0];
778 sc->
recs[rec_idx].
pos.
y = new_position_xyz[1];
779 sc->
recs[rec_idx].
pos.
z = new_position_xyz[2];
801 saf_assert(sourceID >= 0,
"Invalid sourceID");
806 if(sc->
srcs[i].
ID == sourceID){
834 saf_assert(receiverID >= 0,
"Invalid receiverID");
839 if(sc->
recs[i].
ID == receiverID){
void ims_shoebox_setRoomDimensions(void *hIms, float new_roomDimensions[3])
Sets new room dimensions.
void ims_shoebox_removeSource(void *hIms, int sourceID)
Removes a specific source from the simulation.
int ims_shoebox_addReceiverSH(void *hIms, int sh_order, float rec_xyz[3], float ***pSH_sigs)
Adds a spherical harmonic (SH) receiver object to the simulator of a given order, and returns a uniqu...
int ims_shoebox_addSource(void *hIms, float src_xyz[3], float **pSrc_sig)
Adds a source object to the simulator, and returns a unique ID corresponding to it.
void ims_shoebox_applyEchogramTD(void *hIms, long receiverID, int nSamples, int fractionalDelaysFLAG)
Applies the currently computed echograms in the time-domain, for all sources, for one specified recei...
void ims_shoebox_updateSource(void *hIms, int sourceID, float new_position_xyz[3])
Updates the position of a specific source in the simulation.
void ims_shoebox_computeEchograms(void *hIms, int maxN, float maxTime_ms)
Computes echograms for all active source/receiver combinations.
void ims_shoebox_updateReceiver(void *hIms, int receiverID, float new_position_xyz[3])
Updates the position of a specific receiver in the simulation.
void ims_shoebox_destroy(void **phIms)
Destroys an instance of ims_shoebox room simulator.
void ims_shoebox_renderRIRs(void *hIms, int fractionalDelayFLAG)
Renders room impulse responses for all active source/receiver combinations.
void ims_shoebox_removeReceiver(void *hIms, int receiverID)
Removes a specific receiver from the simulation.
void ims_shoebox_create(void **phIms, float roomDimensions[3], float *abs_wall, float lowestOctaveBand, int nOctBands, float c_ms, float fs)
Creates an instance of ims_shoebox room simulator.
#define IMS_MAX_NUM_SOURCES
TODO: Arbitrary array receiver option; Directional source option; finish ims_shoebox_renderRIRs() fun...
#define IMS_MAX_NUM_RECEIVERS
Maximum number of receivers supported by an instance of the IMS simulator.
void ims_shoebox_setWallAbsCoeffs(void *hIms, float *abs_wall)
Sets new wall absorption coefficients per wall and per band.
#define NSH2ORDER(nSH)
Converts number of spherical harmonic components to spherical harmonic order i.e: sqrt(nSH)-1.
#define ORDER2NSH(order)
Converts spherical harmonic order to number of spherical harmonic components i.e: (order+1)^2.
void faf_IIRFilterbank_destroy(void **phFaF)
Destroys an instance of the Favrot & Faller filterbank.
#define saf_assert(x, message)
Macro to make an assertion, along with a string explaining its purpose.
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_svmod(const float *a, const float *b, const int len, float *c)
Single-precision, modulus of vector elements, i.e.
void FIRFilterbank(int order, float *fc, int nCutoffFreq, float sampleRate, WINDOWING_FUNCTION_TYPES windowType, int scalingFLAG, float *filterbank)
Computes a bank of FIR filter coefficients required to divide a signal into frequency bands.
void faf_IIRFilterbank_create(void **phFaF, int order, float *fc, int nCutoffFreq, float sampleRate, int maxNumSamples)
Computes a bank of IIR filter coefficients required to divide a signal into frequency bands,...
void lagrangeWeights(int N, float *x, int len_x, float *weights)
Computes Lagrange interpolation weights of order 'N' for value 'x'.
void getOctaveBandCutoffFreqs(float *centreFreqs, int nCentreFreqs, float *cutoffFreqs)
Converts octave band CENTRE frequencies into CUTOFF frequencies.
void utility_ssv2cv_inds(const float *sv, const int *inds, const int len, float *cv)
Single-precision, sparse-vector to compressed vector given known indices i.e.
void faf_IIRFilterbank_apply(void *hFaF, float *inSig, float **outBands, int nSamples)
Applies the Favrot & Faller filterbank.
@ WINDOWING_FUNCTION_HAMMING
Hamming.
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 * realloc1d(void *ptr, size_t dim1_data_size)
1-D realloc (same as realloc, but with error checking)
void *** calloc3d(size_t dim1, size_t dim2, size_t dim3, size_t data_size)
3-D calloc (contiguously allocated, so use free() as usual to deallocate)
#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_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_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...
Internal header for the reverb processing module (SAF_REVERB_MODULE)
@ RECEIVER_SH
Spherical harmonic receiver.
#define IMS_LAGRANGE_ORDER
Order of lagrange interpolation filters.
#define IMS_UNASSIGNED
While a source or receiver ID is yet to be active, it is "IMS_UNASSIGNED".
#define IMS_MAX_NSAMPLES_PER_FRAME
Maximum number of samples that ims should expect to process at a time.
#define IMS_LAGRANGE_LOOKUP_TABLE_SIZE
Lagrange interpolator look-up table size.
#define IMS_EG_CURRENT
Index for the current echogram slot.
#define IMS_CIRC_BUFFER_LENGTH
Circular buffer length.
#define IMS_CIRC_BUFFER_LENGTH_MASK
Circular buffer length, minus 1.
#define IMS_IIR_FILTERBANK_ORDER
IIR filter order (1st or 3rd)
#define IMS_NUM_WALLS_SHOEBOX
Number of wall for a shoebox room.
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)
#define IMS_EG_PREV
Index for the previous echogram slot.
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 * 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.
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.
float * time
Propagation time (in seconds) for each image source; 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.
voidPtr * hPrevEchogram_abs
Previous echograms (hEchogram_abs), one per band, which can be used for cross- fading.
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
int N_max
Maximum reflection order.
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 x
x Cartesian coordinate, in metres
RECEIVER_TYPES type
Receiver type (see RECEIVER_TYPES enum)
int nChannels
Number of channels for receiver.
ims_pos_xyz pos
Receiver position.
int ID
Unique receiver ID.
float ** sigs
Receiver signal pointers (one per channel)
Output format of the rendered room impulse responses (RIR)
float * band_cutofffreqs
Octave band CUTOFF frequencies; (nBands-1) x 1.
long nSources
Current number of sources.
float *** circ_buffer[IMS_EG_NUM_SLOTS]
[IMS_EG_NUM_SLOTS] x (nChannels x nBands x IMS_CIRC_BUFFER_LENGTH)
float c_ms
Speed of sound, in ms^1.
float * interpolator_fIn
framesize x 1
int nBands
Number of frequency bands.
float ** abs_wall
Wall aborption coeffs per wall; nBands x 6.
float *** src_sigs_bands
nSources x nBands x nSamples
float room_dims[3]
Room dimensions, in meters.
float * band_centerfreqs
Octave band CENTRE frequencies; nBands x 1.
float * tmp_frame
framesize x 1
int framesize
Curent framesize in samples.
long nReceivers
Current number of receivers.
ims_rec_obj recs[IMS_MAX_NUM_RECEIVERS]
Receiver positions.
voidPtr ** hCoreWrkSpc
One per source/receiver combination.
ims_src_obj srcs[IMS_MAX_NUM_SOURCES]
Source positions.
float *** rec_sig_tmp[IMS_EG_NUM_SLOTS]
[IMS_EG_NUM_SLOTS] x (nReceivers x nChannels x nSamples)
ims_rir ** rirs
One per source/receiver combination.
unsigned long wIdx[IMS_EG_NUM_SLOTS][IMS_MAX_NUM_RECEIVERS][IMS_MAX_NUM_SOURCES]
current write indices for circular buffers
float ** H_filt
nBands x (IMS_FIR_FILTERBANK_ORDER+1)
float * interpolator_fOut
framesize x 1
voidPtr * hFaFbank
One per source.
ims_pos_xyz pos
Source position.
float * sig
Source signal pointer.