SAF
Loading...
Searching...
No Matches
ambi_roomsim.c
Go to the documentation of this file.
1/*
2 * Copyright 2020 Leo McCormack
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
25
26#include "ambi_roomsim.h"
28
30(
31 void ** const phAmbi
32)
33{
35 *phAmbi = (void*)pData;
36
37 /* default user parameters */
38 pData->enableReflections = 1;
39 pData->sh_order = 3;
40 pData->refl_order = 3;
43 memcpy(pData->abs_wall, ambi_roomsim_default_abs_wall, 6*sizeof(float));
44 memcpy(pData->room_dims, ambi_roomsim_default_room_dims, 3*sizeof(float));
45 pData->chOrdering = CH_ACN;
46 pData->norm = NORM_SN3D;
49
50 /* Internal */
51 pData->fs = 48000.0f;
52 pData->hIms = NULL;
53 pData->new_sh_order = pData->sh_order;
54 pData->new_nSources = pData->nSources;
55 pData->new_nReceivers = pData->nReceivers;
56
57 pData->src_sigs = (float**)malloc2d(MAX_NUM_CHANNELS, AMBI_ROOMSIM_FRAME_SIZE, sizeof(float));
59
60 pData->reinit_room = 1;
61}
62
64(
65 void ** const phAmbi
66)
67{
68 ambi_roomsim_data *pData = (ambi_roomsim_data*)(*phAmbi);
69
70 if (pData != NULL) {
71 ims_shoebox_destroy(&(pData->hIms));
72 free(pData->src_sigs);
73 free(pData->rec_sh_outsigs);
74 free(pData);
75 pData = NULL;
76 *phAmbi = NULL;
77 }
78}
79
81(
82 void * const hAmbi,
83 int sampleRate
84)
85{
86 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
87 pData->fs = (float)sampleRate;
88}
89
91(
92 void * const hAmbi,
93 const float *const * inputs,
94 float* const* const outputs,
95 int nInputs,
96 int nOutputs,
97 int nSamples
98)
99{
100 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
101 int i, j, rec, ch, nSources, nReceivers, nSH, order;
102 float maxTime_s;
103 CH_ORDER chOrdering;
104 NORM_TYPES norm;
105
106 /* (ims_shoebox is actually much more flexible than this. So consider this as a minimal example, which will also make things easier when designing a GUI) */
107
108 /* Reinitialise room if needed */
109 if(pData->reinit_room){
110 ims_shoebox_destroy(&(pData->hIms));
111 ims_shoebox_create(&(pData->hIms), (float*)pData->room_dims, (float*)pData->abs_wall, 250.0f, 1, 343.0f, pData->fs);
112 for(i=0; i<pData->new_nSources; i++) /* re-add source objects... */
113 pData->sourceIDs[i] = ims_shoebox_addSource(pData->hIms, (float*)pData->src_pos[i], &(pData->src_sigs[i]));
114 for(i=0; i<pData->new_nReceivers; i++) /* re-add receiver objects... */
115 pData->receiverIDs[i] = ims_shoebox_addReceiverSH(pData->hIms, pData->new_sh_order, (float*)pData->rec_pos[i], &(pData->rec_sh_outsigs[i]));
116 pData->nSources = pData->new_nSources;
117 pData->nReceivers = pData->new_nReceivers;
118 pData->sh_order = pData->new_sh_order;
119 pData->reinit_room = 0;
120 }
121
122 /* Add/remove source objects */
123 if(pData->new_nSources!=pData->nSources){
124 if(pData->new_nSources>pData->nSources)
125 for(i=pData->nSources; i<pData->new_nSources; i++)
126 pData->sourceIDs[i] = ims_shoebox_addSource(pData->hIms, (float*)pData->src_pos[i], &(pData->src_sigs[i]));
127 else
128 for(i=pData->new_nSources; i<pData->nSources; i++)
129 ims_shoebox_removeSource(pData->hIms, pData->sourceIDs[i]);
130 pData->nSources = pData->new_nSources;
131 }
132
133 /* Add/remove receiver objects */
134 if(pData->new_nReceivers!=pData->nReceivers){
135 if(pData->new_nReceivers>pData->nReceivers)
136 for(i=pData->nReceivers; i<pData->new_nReceivers; i++)
137 pData->receiverIDs[i] = ims_shoebox_addReceiverSH(pData->hIms, pData->sh_order, (float*)pData->rec_pos[i], &(pData->rec_sh_outsigs[i]));
138 else
139 for(i=pData->new_nReceivers; i<pData->nReceivers; i++)
141 pData->nReceivers = pData->new_nReceivers;
142 }
143
144 /* local copies of user parameters */
145 chOrdering = pData->chOrdering;
146 norm = pData->norm;
147 order = SAF_MIN(pData->sh_order, MAX_SH_ORDER);
148 nSH = ORDER2NSH(order);
149 nSources = pData->nSources;
150 nReceivers = pData->nReceivers;
151 maxTime_s = -0.05f; /* 50ms */
152
153 /* Process frame */
154 if (nSamples == AMBI_ROOMSIM_FRAME_SIZE) {
155 /* Load time-domain data */
156 for(i=0; i < SAF_MIN(nSources,nInputs); i++)
157 memcpy(pData->src_sigs[i], inputs[i], AMBI_ROOMSIM_FRAME_SIZE * sizeof(float));
158 for(; i < nInputs; i++)
159 memset(pData->src_sigs[i], 0, AMBI_ROOMSIM_FRAME_SIZE * sizeof(float));
160
161 /* Update source/receiver positions, room dims/coeffs and re-compute echgrams
162 * (note, if nothing has changed since last frame then these calls will be bypassed internally) */
163 for(i=0; i<nSources; i++)
164 ims_shoebox_updateSource(pData->hIms, pData->sourceIDs[i], pData->src_pos[i]);
165 for(i=0; i<nReceivers; i++)
166 ims_shoebox_updateReceiver(pData->hIms, pData->receiverIDs[i], pData->rec_pos[i]);
168 ims_shoebox_setWallAbsCoeffs(pData->hIms, (_Atomic_FLOAT32*)pData->abs_wall);
169 ims_shoebox_computeEchograms(pData->hIms, pData->enableReflections ? pData->refl_order : 0, maxTime_s);
170
171 /* Render audio for each receiver */
172 for(i=0; i<nReceivers; i++)
173 ims_shoebox_applyEchogramTD(pData->hIms, pData->receiverIDs[i], nSamples, 0);
174
175 /* Handle output */
176 for(rec=0, i=0; rec<nReceivers; rec++){
177 /* account for output channel order */
178 switch(chOrdering){
179 case CH_ACN: break;
181 }
182
183 /* account for normalisation scheme */
184 switch(norm){
185 case NORM_N3D: break;
188 }
189
190 /* Append this receiver's output channels to the master output buffer */
191 for(j=0; (j<SAF_MIN(nSH, MAX_NUM_SH_SIGNALS) && i<SAF_MIN(nOutputs, MAX_NUM_CHANNELS)); j++, i++)
192 memcpy(outputs[i], pData->rec_sh_outsigs[rec][j], AMBI_ROOMSIM_FRAME_SIZE * sizeof(float));
193 }
194 for(; i < nOutputs; i++)
195 memset(outputs[i], 0, AMBI_ROOMSIM_FRAME_SIZE * sizeof(float));
196 }
197 else{
198 for (ch=0; ch < nOutputs; ch++)
199 memset(outputs[ch],0, nSamples*sizeof(float));
200 }
201}
202
203/* Set Functions */
204
205void ambi_roomsim_refreshParams(void* const hAmbi)
206{
207 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
208 pData->reinit_room = 1;
209}
210
211void ambi_roomsim_setEnableIMSflag(void* const hAmbi, int newValue)
212{
213 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
214 pData->enableReflections = newValue;
215}
216
217void ambi_roomsim_setMaxReflectionOrder(void* const hAmbi, int newValue)
218{
219 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
220 pData->refl_order = newValue;
221}
222
223void ambi_roomsim_setOutputOrder(void* const hAmbi, int newOrder)
224{
225 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
226 if(newOrder != pData->new_sh_order){
227 pData->new_sh_order = newOrder;
228 /* FUMA only supports 1st order */
229 if(pData->new_sh_order!=SH_ORDER_FIRST && pData->chOrdering == CH_FUMA)
230 pData->chOrdering = CH_ACN;
231 if(pData->new_sh_order!=SH_ORDER_FIRST && pData->norm == NORM_FUMA)
232 pData->norm = NORM_SN3D;
233
234 pData->reinit_room = 1;
235 }
236}
237
238void ambi_roomsim_setNumSources(void* const hAmbi, int new_nSources)
239{
240 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
241 pData->new_nSources = SAF_CLAMP(new_nSources, 1, ROOM_SIM_MAX_NUM_SOURCES);
242}
243
244void ambi_roomsim_setSourceX(void* const hAmbi, int index, float newValue)
245{
246 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
247 saf_assert(index<=ROOM_SIM_MAX_NUM_SOURCES, "Index exceeds the maximum number of sources permitted");
248 pData->src_pos[index][0] = newValue;
249}
250
251void ambi_roomsim_setSourceY(void* const hAmbi, int index, float newValue)
252{
253 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
254 saf_assert(index<=ROOM_SIM_MAX_NUM_SOURCES, "Index exceeds the maximum number of sources permitted");
255 pData->src_pos[index][1] = newValue;
256}
257
258void ambi_roomsim_setSourceZ(void* const hAmbi, int index, float newValue)
259{
260 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
261 saf_assert(index<=ROOM_SIM_MAX_NUM_SOURCES, "Index exceeds the maximum number of sources permitted");
262 pData->src_pos[index][2] = newValue;
263}
264
265void ambi_roomsim_setNumReceivers(void* const hAmbi, int new_nReceivers)
266{
267 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
268 pData->new_nReceivers = SAF_CLAMP(new_nReceivers, 1, ROOM_SIM_MAX_NUM_RECEIVERS);
269}
270
271void ambi_roomsim_setReceiverX(void* const hAmbi, int index, float newValue)
272{
273 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
274 saf_assert(index<=ROOM_SIM_MAX_NUM_RECEIVERS, "Index exceeds the maximum number of receivers permitted");
275 pData->rec_pos[index][0] = newValue;
276}
277
278void ambi_roomsim_setReceiverY(void* const hAmbi, int index, float newValue)
279{
280 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
281 saf_assert(index<=ROOM_SIM_MAX_NUM_RECEIVERS, "Index exceeds the maximum number of receivers permitted");
282 pData->rec_pos[index][1] = newValue;
283}
284
285void ambi_roomsim_setReceiverZ(void* const hAmbi, int index, float newValue)
286{
287 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
288 saf_assert(index<=ROOM_SIM_MAX_NUM_RECEIVERS, "Index exceeds the maximum number of receivers permitted");
289 pData->rec_pos[index][2] = newValue;
290}
291
292void ambi_roomsim_setRoomDimX(void* const hAmbi, float newValue)
293{
294 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
295 if(newValue!=pData->room_dims[0]){
296 pData->room_dims[0] = newValue;
297 }
298}
299
300void ambi_roomsim_setRoomDimY(void* const hAmbi, float newValue)
301{
302 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
303 if(newValue!=pData->room_dims[1]){
304 pData->room_dims[1] = newValue;
305 }
306}
307
308void ambi_roomsim_setRoomDimZ(void* const hAmbi, float newValue)
309{
310 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
311 if(newValue!=pData->room_dims[2]){
312 pData->room_dims[2] = newValue;
313 }
314}
315
316void ambi_roomsim_setWallAbsCoeff(void* const hAmbi, int xyz_idx, int posNeg_idx, float new_value)
317{
318 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
319 saf_assert(xyz_idx<3, "xyz_idx indicates each spatial axis, so cannot exceed 3");
320 saf_assert(posNeg_idx==0 || posNeg_idx==1, "posNeg_idx is a bool");
321 if(new_value!=pData->abs_wall[2*xyz_idx+posNeg_idx]){
322 pData->abs_wall[2*xyz_idx+posNeg_idx] = new_value;
323 }
324}
325
326void ambi_roomsim_setChOrder(void* const hAmbi, int newOrder)
327{
328 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
329 if((CH_ORDER)newOrder != CH_FUMA || pData->new_sh_order==SH_ORDER_FIRST)/* FUMA only supports 1st order */
330 pData->chOrdering = (CH_ORDER)newOrder;
331}
332
333void ambi_roomsim_setNormType(void* const hAmbi, int newType)
334{
335 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
336 if((NORM_TYPES)newType != NORM_FUMA || pData->new_sh_order==SH_ORDER_FIRST)/* FUMA only supports 1st order */
337 pData->norm = (NORM_TYPES)newType;
338}
339
340
341/* Get Functions */
342
347
348int ambi_roomsim_getEnableIMSflag(void* const hAmbi)
349{
350 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
351 return pData->enableReflections;
352}
353
355{
356 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
357 return pData->refl_order;
358}
359
360int ambi_roomsim_getOutputOrder(void* const hAmbi)
361{
362 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
363 return pData->new_sh_order;
364}
365
366int ambi_roomsim_getNumSources(void* const hAmbi)
367{
368 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
369 return pData->new_nSources;
370}
371
376
377int ambi_roomsim_getNSHrequired(void* const hAmbi)
378{
379 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
380 return (pData->new_sh_order+1)*(pData->new_sh_order+1);
381}
382
383float ambi_roomsim_getSourceX(void* const hAmbi, int index)
384{
385 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
386 saf_assert(index<=ROOM_SIM_MAX_NUM_SOURCES, "Index exceeds the maximum number of sources permitted");
387 return pData->src_pos[index][0];
388}
389
390float ambi_roomsim_getSourceY(void* const hAmbi, int index)
391{
392 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
393 saf_assert(index<=ROOM_SIM_MAX_NUM_SOURCES, "Index exceeds the maximum number of sources permitted");
394 return pData->src_pos[index][1];
395}
396
397float ambi_roomsim_getSourceZ(void* const hAmbi, int index)
398{
399 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
400 saf_assert(index<=ROOM_SIM_MAX_NUM_SOURCES, "Index exceeds the maximum number of sources permitted");
401 return pData->src_pos[index][2];
402}
403
404int ambi_roomsim_getNumReceivers(void* const hAmbi)
405{
406 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
407 return pData->new_nReceivers;
408}
409
414
415float ambi_roomsim_getReceiverX(void* const hAmbi, int index)
416{
417 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
418 saf_assert(index<=ROOM_SIM_MAX_NUM_RECEIVERS, "Index exceeds the maximum number of receivers permitted");
419 return pData->rec_pos[index][0];
420}
421
422float ambi_roomsim_getReceiverY(void* const hAmbi, int index)
423{
424 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
425 saf_assert(index<=ROOM_SIM_MAX_NUM_RECEIVERS, "Index exceeds the maximum number of receivers permitted");
426 return pData->rec_pos[index][1];
427}
428
429float ambi_roomsim_getReceiverZ(void* const hAmbi, int index)
430{
431 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
432 saf_assert(index<=ROOM_SIM_MAX_NUM_RECEIVERS, "Index exceeds the maximum number of receivers permitted");
433 return pData->rec_pos[index][2];
434}
435
436float ambi_roomsim_getRoomDimX(void* const hAmbi)
437{
438 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
439 return pData->room_dims[0];
440}
441
442float ambi_roomsim_getRoomDimY(void* const hAmbi)
443{
444 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
445 return pData->room_dims[1];
446}
447
448float ambi_roomsim_getRoomDimZ(void* const hAmbi)
449{
450 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
451 return pData->room_dims[2];
452}
453
454float ambi_roomsim_getWallAbsCoeff(void* const hAmbi, int xyz_idx, int posNeg_idx)
455{
456 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
457 return pData->abs_wall[2*xyz_idx+posNeg_idx];
458}
459
460int ambi_roomsim_getChOrder(void* const hAmbi)
461{
462 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
463 return (int)pData->chOrdering;
464}
465
466int ambi_roomsim_getNormType(void* const hAmbi)
467{
468 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
469 return (int)pData->norm;
470}
471
#define MAX_SH_ORDER
Maximum supported Ambisonic order.
Definition _common.h:56
#define MAX_NUM_CHANNELS
Maximum number of input/output channels supported.
Definition _common.h:258
NORM_TYPES
Available Ambisonic normalisation conventions.
Definition _common.h:78
@ NORM_SN3D
Schmidt semi-normalisation (SN3D)
Definition _common.h:80
@ NORM_FUMA
(Legacy) Furse-Malham scaling
Definition _common.h:81
@ NORM_N3D
orthonormalised (N3D)
Definition _common.h:79
CH_ORDER
Available Ambisonic channel ordering conventions.
Definition _common.h:63
@ CH_ACN
Ambisonic Channel Numbering (ACN)
Definition _common.h:64
@ CH_FUMA
(Legacy) Furse-Malham/B-format (WXYZ)
Definition _common.h:65
#define MAX_NUM_SH_SIGNALS
Maximum number of spherical harmonic components/signals supported.
Definition _common.h:267
@ SH_ORDER_FIRST
First-order (4 channels)
Definition _common.h:43
void ambi_roomsim_setRoomDimY(void *const hAmbi, float newValue)
Sets the room length along the y dimension.
void ambi_roomsim_setOutputOrder(void *const hAmbi, int newOrder)
Sets the encoding order (see SH_ORDERS enum)
float ambi_roomsim_getSourceZ(void *const hAmbi, int index)
Returns the 'z' coordinate for a specific source index.
void ambi_roomsim_setReceiverZ(void *const hAmbi, int index, float newValue)
Sets the 'z' coordinate for a specific receiver index.
int ambi_roomsim_getEnableIMSflag(void *const hAmbi)
Returns whether to include image sources (1) or not (0)
int ambi_roomsim_getMaxNumReceivers(void)
Returns the maximum number of receivers.
int ambi_roomsim_getNSHrequired(void *const hAmbi)
Returns the number of spherical harmonic signals required by the current decoding order: (current_ord...
void ambi_roomsim_process(void *const hAmbi, const float *const *inputs, float *const *const outputs, int nInputs, int nOutputs, int nSamples)
Processes audio.
void ambi_roomsim_setNumSources(void *const hAmbi, int new_nSources)
Sets the number of input signals/sources to encode.
float ambi_roomsim_getWallAbsCoeff(void *const hAmbi, int xyz_idx, int posNeg_idx)
Returns wall absorption coefficients.
float ambi_roomsim_getReceiverZ(void *const hAmbi, int index)
Returns the 'z' coordinate for a specific receiver index.
float ambi_roomsim_getRoomDimZ(void *const hAmbi)
Returns the room length along the z dimension.
void ambi_roomsim_setReceiverX(void *const hAmbi, int index, float newValue)
Sets the 'x' coordinate for a specific receiver index.
float ambi_roomsim_getRoomDimY(void *const hAmbi)
Returns the room length along the y dimension.
void ambi_roomsim_setRoomDimZ(void *const hAmbi, float newValue)
Sets the room length along the z dimension.
void ambi_roomsim_create(void **const phAmbi)
Creates an instance of ambi_roomsim.
int ambi_roomsim_getNumReceivers(void *const hAmbi)
Returns the number of SH receivers.
float ambi_roomsim_getSourceY(void *const hAmbi, int index)
Returns the 'y' coordinate for a specific source index.
void ambi_roomsim_setNormType(void *const hAmbi, int newType)
Sets the Ambisonic normalisation convention to encode with (see NORM_TYPES enum)
void ambi_roomsim_destroy(void **const phAmbi)
Destroys an instance of ambi_roomsim.
void ambi_roomsim_setSourceX(void *const hAmbi, int index, float newValue)
Sets the 'x' coordinate for a specific source index.
void ambi_roomsim_init(void *const hAmbi, int sampleRate)
Initialises an instance of ambi_roomsim with default settings.
float ambi_roomsim_getReceiverX(void *const hAmbi, int index)
Returns the 'x' coordinate for a specific receiver index.
int ambi_roomsim_getNumSources(void *const hAmbi)
Returns the number of input signals/sources to encode.
void ambi_roomsim_setEnableIMSflag(void *const hAmbi, int newValue)
Sets whether to include image sources (1) or not (0)
void ambi_roomsim_setChOrder(void *const hAmbi, int newOrder)
Sets the Ambisonic channel ordering convention to encode with (see CH_ORDER enum)
void ambi_roomsim_setRoomDimX(void *const hAmbi, float newValue)
Sets the room length along the x dimension.
void ambi_roomsim_refreshParams(void *const hAmbi)
Sets all intialisation flags to 1; re-initialising all settings/variables as ambi_roomsim is currentl...
void ambi_roomsim_setSourceZ(void *const hAmbi, int index, float newValue)
Sets the 'z' coordinate for a specific source index.
int ambi_roomsim_getProcessingDelay(void)
Returns the processing delay in samples (may be used for delay compensation features)
int ambi_roomsim_getOutputOrder(void *const hAmbi)
Returns the decoding order (see SH_ORDERS enum)
float ambi_roomsim_getSourceX(void *const hAmbi, int index)
Returns the 'x' coordinate for a specific source index.
int ambi_roomsim_getChOrder(void *const hAmbi)
Returns the Ambisonic channel ordering convention currently being used to encode with (see CH_ORDER e...
float ambi_roomsim_getRoomDimX(void *const hAmbi)
Returns the room length along the x dimension.
void ambi_roomsim_setNumReceivers(void *const hAmbi, int new_nReceivers)
Sets the number of input SH receivers.
void ambi_roomsim_setReceiverY(void *const hAmbi, int index, float newValue)
Sets the 'y' coordinate for a specific receiver index.
int ambi_roomsim_getMaxReflectionOrder(void *const hAmbi)
Returns the maximum reflection order.
void ambi_roomsim_setWallAbsCoeff(void *const hAmbi, int xyz_idx, int posNeg_idx, float new_value)
Sets wall absorption coefficients.
int ambi_roomsim_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
void ambi_roomsim_setSourceY(void *const hAmbi, int index, float newValue)
Sets the 'y' coordinate for a specific source index.
int ambi_roomsim_getMaxNumSources(void)
Returns the maximum number of input signals/sources that can be encoded.
int ambi_roomsim_getNormType(void *const hAmbi)
Returns the Ambisonic normalisation convention currently being used to encode with (see NORM_TYPES en...
void ambi_roomsim_setMaxReflectionOrder(void *const hAmbi, int newValue)
Sets the maximum reflection order.
float ambi_roomsim_getReceiverY(void *const hAmbi, int index)
Returns the 'y' coordinate for a specific receiver index.
A simple shoebox room Ambisonic encoder.
const float ambi_roomsim_default_room_dims[3]
Default room dimensions.
const float ambi_roomsim_defaultReceiverPositions[ROOM_SIM_MAX_NUM_RECEIVERS][3]
Default receiver positions.
#define ROOM_SIM_MAX_NUM_RECEIVERS
Maximum supported number of receivers for the room sim example.
const int ambi_roomsim_defaultNumReceivers
Default number of receivers in the simulation.
const int ambi_roomsim_defaultNumSources
Default number of sources in the simulation.
const float ambi_roomsim_defaultSourcePositions[ROOM_SIM_MAX_NUM_SOURCES][3]
Default source positions.
const float ambi_roomsim_default_abs_wall[6]
Default wall absorption coefficients.
#define ROOM_SIM_MAX_NUM_SOURCES
Maximum supported number of sources for the room sim example.
A simple shoebox room Ambisonic encoder.
#define AMBI_ROOMSIM_FRAME_SIZE
Framesize, in time-domain samples.
void convertHOAChannelConvention(float *insig, int order, int signalLength, HOA_CH_ORDER inConvention, HOA_CH_ORDER outConvention)
Converts an Ambisonic signal from one channel ordering convention to another.
Definition saf_hoa.c:41
void convertHOANormConvention(float *insig, int order, int signalLength, HOA_NORM inConvention, HOA_NORM outConvention)
Converts an Ambisonic signal from one normalisation convention to another.
Definition saf_hoa.c:73
@ HOA_CH_ORDER_FUMA
Furse-Malham (FuMa) convention, often used by older recordings.
Definition saf_hoa.h:187
@ HOA_CH_ORDER_ACN
Ambisonic Channel numbering (ACN) convention, which is employed by all spherical harmonic related fun...
Definition saf_hoa.h:184
@ HOA_NORM_FUMA
Furse-Malham (FuMa) convention.
Definition saf_hoa.h:208
@ HOA_NORM_SN3D
Schmidt semi-normalisation (SN3D) convention, as used by the AmbiX standard.
Definition saf_hoa.h:206
@ HOA_NORM_N3D
Orthonormalised (N3D) convention, which is the default convention used by SAF.
Definition saf_hoa.h:204
void ims_shoebox_removeSource(void *hIms, int sourceID)
Removes a specific source from the simulation.
Definition saf_reverb.c:793
void ims_shoebox_updateReceiver(void *hIms, int receiverID, _Atomic_FLOAT32 new_position_xyz[3])
Updates the position of a specific receiver in the simulation.
Definition saf_reverb.c:749
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...
Definition saf_reverb.c:650
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.
Definition saf_reverb.c:599
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...
Definition saf_reverb.c:298
void ims_shoebox_setWallAbsCoeffs(void *hIms, _Atomic_FLOAT32 *abs_wall)
Sets new wall absorption coefficients per wall and per band.
Definition saf_reverb.c:568
void ims_shoebox_computeEchograms(void *hIms, int maxN, float maxTime_ms)
Computes echograms for all active source/receiver combinations.
Definition saf_reverb.c:185
void ims_shoebox_destroy(void **phIms)
Destroys an instance of ims_shoebox room simulator.
Definition saf_reverb.c:141
void ims_shoebox_removeReceiver(void *hIms, int receiverID)
Removes a specific receiver from the simulation.
Definition saf_reverb.c:826
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.
Definition saf_reverb.c:37
#define IMS_MAX_NUM_RECEIVERS
Maximum number of receivers supported by an instance of the IMS simulator.
Definition saf_reverb.h:57
void ims_shoebox_updateSource(void *hIms, int sourceID, _Atomic_FLOAT32 new_position_xyz[3])
Updates the position of a specific source in the simulation.
Definition saf_reverb.c:705
void ims_shoebox_setRoomDimensions(void *hIms, _Atomic_FLOAT32 new_roomDimensions[3])
Sets new room dimensions.
Definition saf_reverb.c:542
#define ORDER2NSH(order)
Converts spherical harmonic order to number of spherical harmonic components i.e: (order+1)^2.
Definition saf_sh.h:51
#define saf_assert(x, message)
Macro to make an assertion, along with a string explaining its purpose.
#define SAF_CLAMP(a, min, max)
Ensures value "a" is clamped between the "min" and "max" values.
#define SAF_MIN(a, b)
Returns the minimum of the two values.
void ** malloc2d(size_t dim1, size_t dim2, size_t data_size)
2-D malloc (contiguously allocated, so use free() as usual to deallocate)
Definition md_malloc.c:89
void * malloc1d(size_t dim1_data_size)
1-D malloc (same as malloc, but with error checking)
Definition md_malloc.c:59
void *** malloc3d(size_t dim1, size_t dim2, size_t dim3, size_t data_size)
3-D malloc (contiguously allocated, so use free() as usual to deallocate)
Definition md_malloc.c:151
#define FLATTEN2D(A)
Use this macro when passing a 2-D dynamic multi-dimensional array to memset, memcpy or any other func...
Definition md_malloc.h:65
Main structure for ambi_roomsim.
_Atomic_FLOAT32 room_dims[3]
Room dimensions along the x,y,z axes in meters.
_Atomic_INT32 new_sh_order
New receiver SH order (current value will be replaced by this after next re-init)
_Atomic_NORM_TYPES norm
Ambisonic normalisation convention (see NORM_TYPES)
void * hIms
Image source implementation handle.
int receiverIDs[ROOM_SIM_MAX_NUM_RECEIVERS]
Unique IDs per receiver in the simulation.
_Atomic_CH_ORDER chOrdering
Ambisonic channel order convention (see CH_ORDER)
float fs
Host sampling rate, in Hz.
_Atomic_INT32 enableReflections
0: disabled, 1: enabled
int sourceIDs[ROOM_SIM_MAX_NUM_SOURCES]
Unique IDs per source in the simulation.
_Atomic_FLOAT32 abs_wall[6]
Absorption coefficients per wall, in the order in which the axis intersect walls: +x -x +y -y +z -z.
_Atomic_INT32 nReceivers
Current number of receivers.
_Atomic_INT32 new_nSources
New number of sources (current value will be replaced by this after next re-init)
_Atomic_INT32 new_nReceivers
New number of receivers (current value will be replaced by this after next re-init)
_Atomic_INT32 sh_order
Current SH order of receivers.
_Atomic_INT32 reinit_room
Flag, 1: re-init required, 0: not required.
float ** src_sigs
Source signal buffers; ROOM_SIM_MAX_NUM_SOURCES x AMBI_ROOMSIM_FRAME_SIZE.
_Atomic_INT32 nSources
Current number of sources.
float *** rec_sh_outsigs
Receiver signal buffers; ROOM_SIM_MAX_NUM_RECEIVERS x MAX_NUM_SH_SIGNALS x AMBI_ROOMSIM_FRAME_SIZE.
_Atomic_INT32 refl_order
Current maximum image source reflection order.
_Atomic_FLOAT32 rec_pos[ROOM_SIM_MAX_NUM_RECEIVERS][3]
Current receiver Cartesian coordinates, meters.
_Atomic_FLOAT32 src_pos[ROOM_SIM_MAX_NUM_SOURCES][3]
Current source Cartesian coordinates, meters.