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
26#include "ambi_roomsim.h"
28
30const float default_abs_wall[6] = { 0.341055000f, 0.431295000f, 0.351295000f, 0.344335000f, 0.401775000f, 0.482095000f};
32const float default_room_dims[3] = { 9.1f, 8.0f, 3.0f };
33
35(
36 void ** const phAmbi
37)
38{
40 *phAmbi = (void*)pData;
41
42 /* default user parameters */
43 pData->enableReflections = 1;
44 pData->sh_order = 3;
45 pData->refl_order = 3;
46 pData->nSources = 1;
47 pData->nReceivers = 1;
48 memcpy(pData->abs_wall, default_abs_wall, 6*sizeof(float));
49 memcpy(pData->room_dims, default_room_dims, 3*sizeof(float));
50 pData->chOrdering = CH_ACN;
51 pData->norm = NORM_SN3D;
52 memset(pData->src_pos, 0, ROOM_SIM_MAX_NUM_SOURCES*3*sizeof(float));
53 memset(pData->rec_pos, 0, ROOM_SIM_MAX_NUM_RECEIVERS*3*sizeof(float));
54
55 /* Internal */
56 pData->fs = 48000.0f;
57 pData->hIms = NULL;
58 float src_pos[3] = {5.2f, 1.5f, 1.4f};
59 memcpy(pData->src_pos[0], src_pos, 3*sizeof(float));
60 float src2_pos[3] = {2.1f, 1.0f, 1.3f};
61 memcpy(pData->src_pos[1], src2_pos, 3*sizeof(float));
62 float src3_pos[3] = {3.1f, 5.0f, 2.3f};
63 memcpy(pData->src_pos[2], src3_pos, 3*sizeof(float));
64 float src4_pos[3] = {7.1f, 2.0f, 1.4f};
65 memcpy(pData->src_pos[3], src4_pos, 3*sizeof(float));
66 float rec_pos[3] = {5.2f, 3.5f, 1.4f};
67 memcpy(pData->rec_pos[0], rec_pos, 3*sizeof(float));
68 memcpy(pData->rec_pos[1], rec_pos, 3*sizeof(float));
69 pData->new_sh_order = pData->sh_order;
70 pData->new_nSources = pData->nSources;
71 pData->new_nReceivers = pData->nReceivers;
72
73 pData->src_sigs = (float**)malloc2d(MAX_NUM_CHANNELS, AMBI_ROOMSIM_FRAME_SIZE, sizeof(float));
75
76 pData->reinit_room = 1;
77}
78
80(
81 void ** const phAmbi
82)
83{
84 ambi_roomsim_data *pData = (ambi_roomsim_data*)(*phAmbi);
85
86 if (pData != NULL) {
87 ims_shoebox_destroy(&(pData->hIms));
88 free(pData->src_sigs);
89 free(pData->rec_sh_outsigs);
90 free(pData);
91 pData = NULL;
92 *phAmbi = NULL;
93 }
94}
95
97(
98 void * const hAmbi,
99 int sampleRate
100)
101{
102 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
103 pData->fs = (float)sampleRate;
104}
105
107(
108 void * const hAmbi,
109 const float *const * inputs,
110 float* const* const outputs,
111 int nInputs,
112 int nOutputs,
113 int nSamples
114)
115{
116 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
117 int i, j, rec, ch, nSources, nReceivers, nSH, order;
118 float maxTime_s;
119 CH_ORDER chOrdering;
120 NORM_TYPES norm;
121
122 /* (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) */
123
124 /* Reinitialise room if needed */
125 if(pData->reinit_room){
126 ims_shoebox_destroy(&(pData->hIms));
127 ims_shoebox_create(&(pData->hIms), pData->room_dims, (float*)pData->abs_wall, 250.0f, 1, 343.0f, pData->fs);
128 for(i=0; i<pData->new_nSources; i++) /* re-add source objects... */
129 pData->sourceIDs[i] = ims_shoebox_addSource(pData->hIms, (float*)pData->src_pos[i], &(pData->src_sigs[i]));
130 for(i=0; i<pData->new_nReceivers; i++) /* re-add receiver objects... */
131 pData->receiverIDs[i] = ims_shoebox_addReceiverSH(pData->hIms, pData->new_sh_order, (float*)pData->rec_pos[i], &(pData->rec_sh_outsigs[i]));
132 pData->nSources = pData->new_nSources;
133 pData->nReceivers = pData->new_nReceivers;
134 pData->sh_order = pData->new_sh_order;
135 pData->reinit_room = 0;
136 }
137
138 /* Add/remove source objects */
139 if(pData->new_nSources!=pData->nSources){
140 if(pData->new_nSources>pData->nSources)
141 for(i=pData->nSources; i<pData->new_nSources; i++)
142 pData->sourceIDs[i] = ims_shoebox_addSource(pData->hIms, (float*)pData->src_pos[i], &(pData->src_sigs[i]));
143 else
144 for(i=pData->new_nSources; i<pData->nSources; i++)
145 ims_shoebox_removeSource(pData->hIms, pData->sourceIDs[i]);
146 pData->nSources = pData->new_nSources;
147 }
148
149 /* Add/remove receiver objects */
150 if(pData->new_nReceivers!=pData->nReceivers){
151 if(pData->new_nReceivers>pData->nReceivers)
152 for(i=pData->nReceivers; i<pData->new_nReceivers; i++)
153 pData->receiverIDs[i] = ims_shoebox_addReceiverSH(pData->hIms, pData->sh_order, (float*)pData->rec_pos[i], &(pData->rec_sh_outsigs[i]));
154 else
155 for(i=pData->new_nReceivers; i<pData->nReceivers; i++)
157 pData->nReceivers = pData->new_nReceivers;
158 }
159
160 /* local copies of user parameters */
161 chOrdering = pData->chOrdering;
162 norm = pData->norm;
163 order = SAF_MIN(pData->sh_order, MAX_SH_ORDER);
164 nSH = ORDER2NSH(order);
165 nSources = pData->nSources;
166 nReceivers = pData->nReceivers;
167 maxTime_s = -0.05f; /* 50ms */
168
169 /* Process frame */
170 if (nSamples == AMBI_ROOMSIM_FRAME_SIZE) {
171 /* Load time-domain data */
172 for(i=0; i < SAF_MIN(nSources,nInputs); i++)
173 memcpy(pData->src_sigs[i], inputs[i], AMBI_ROOMSIM_FRAME_SIZE * sizeof(float));
174 for(; i < nInputs; i++)
175 memset(pData->src_sigs[i], 0, AMBI_ROOMSIM_FRAME_SIZE * sizeof(float));
176
177 /* Update source/receiver positions, room dims/coeffs and re-compute echgrams
178 * (note, if nothing has changed since last frame then these calls will be bypassed internally) */
179 for(i=0; i<nSources; i++)
180 ims_shoebox_updateSource(pData->hIms, pData->sourceIDs[i], pData->src_pos[i]);
181 for(i=0; i<nReceivers; i++)
182 ims_shoebox_updateReceiver(pData->hIms, pData->receiverIDs[i], pData->rec_pos[i]);
184 ims_shoebox_setWallAbsCoeffs(pData->hIms, (float*)pData->abs_wall);
185 ims_shoebox_computeEchograms(pData->hIms, pData->enableReflections ? pData->refl_order : 0, maxTime_s);
186
187 /* Render audio for each receiver */
188 for(i=0; i<nReceivers; i++)
189 ims_shoebox_applyEchogramTD(pData->hIms, pData->receiverIDs[i], nSamples, 0);
190
191 /* Handle output */
192 for(rec=0, i=0; rec<nReceivers; rec++){
193 /* account for output channel order */
194 switch(chOrdering){
195 case CH_ACN: break;
197 }
198
199 /* account for normalisation scheme */
200 switch(norm){
201 case NORM_N3D: break;
204 }
205
206 /* Append this receiver's output channels to the master output buffer */
207 for(j=0; (j<SAF_MIN(nSH, MAX_NUM_SH_SIGNALS) && i<SAF_MIN(nOutputs, MAX_NUM_CHANNELS)); j++, i++)
208 memcpy(outputs[i], pData->rec_sh_outsigs[rec][j], AMBI_ROOMSIM_FRAME_SIZE * sizeof(float));
209 }
210 for(; i < nOutputs; i++)
211 memset(outputs[i], 0, AMBI_ROOMSIM_FRAME_SIZE * sizeof(float));
212 }
213 else{
214 for (ch=0; ch < nOutputs; ch++)
215 memset(outputs[ch],0, nSamples*sizeof(float));
216 }
217}
218
219/* Set Functions */
220
221void ambi_roomsim_refreshParams(void* const hAmbi)
222{
223 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
224 pData->reinit_room = 1;
225}
226
227void ambi_roomsim_setEnableIMSflag(void* const hAmbi, int newValue)
228{
229 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
230 pData->enableReflections = newValue;
231}
232
233void ambi_roomsim_setMaxReflectionOrder(void* const hAmbi, int newValue)
234{
235 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
236 pData->refl_order = newValue;
237}
238
239void ambi_roomsim_setOutputOrder(void* const hAmbi, int newOrder)
240{
241 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
242 if(newOrder != pData->new_sh_order){
243 pData->new_sh_order = newOrder;
244 /* FUMA only supports 1st order */
245 if(pData->new_sh_order!=SH_ORDER_FIRST && pData->chOrdering == CH_FUMA)
246 pData->chOrdering = CH_ACN;
247 if(pData->new_sh_order!=SH_ORDER_FIRST && pData->norm == NORM_FUMA)
248 pData->norm = NORM_SN3D;
249
250 pData->reinit_room = 1;
251 }
252}
253
254void ambi_roomsim_setNumSources(void* const hAmbi, int new_nSources)
255{
256 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
257 pData->new_nSources = SAF_CLAMP(new_nSources, 1, ROOM_SIM_MAX_NUM_SOURCES);
258}
259
260void ambi_roomsim_setSourceX(void* const hAmbi, int index, float newValue)
261{
262 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
263 saf_assert(index<=ROOM_SIM_MAX_NUM_SOURCES, "Index exceeds the maximum number of sources permitted");
264 pData->src_pos[index][0] = newValue;
265}
266
267void ambi_roomsim_setSourceY(void* const hAmbi, int index, float newValue)
268{
269 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
270 saf_assert(index<=ROOM_SIM_MAX_NUM_SOURCES, "Index exceeds the maximum number of sources permitted");
271 pData->src_pos[index][1] = newValue;
272}
273
274void ambi_roomsim_setSourceZ(void* const hAmbi, int index, float newValue)
275{
276 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
277 saf_assert(index<=ROOM_SIM_MAX_NUM_SOURCES, "Index exceeds the maximum number of sources permitted");
278 pData->src_pos[index][2] = newValue;
279}
280
281void ambi_roomsim_setNumReceivers(void* const hAmbi, int new_nReceivers)
282{
283 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
284 pData->new_nReceivers = SAF_CLAMP(new_nReceivers, 1, ROOM_SIM_MAX_NUM_RECEIVERS);
285}
286
287void ambi_roomsim_setReceiverX(void* const hAmbi, int index, float newValue)
288{
289 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
290 saf_assert(index<=ROOM_SIM_MAX_NUM_RECEIVERS, "Index exceeds the maximum number of receivers permitted");
291 pData->rec_pos[index][0] = newValue;
292}
293
294void ambi_roomsim_setReceiverY(void* const hAmbi, int index, float newValue)
295{
296 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
297 saf_assert(index<=ROOM_SIM_MAX_NUM_RECEIVERS, "Index exceeds the maximum number of receivers permitted");
298 pData->rec_pos[index][1] = newValue;
299}
300
301void ambi_roomsim_setReceiverZ(void* const hAmbi, int index, float newValue)
302{
303 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
304 saf_assert(index<=ROOM_SIM_MAX_NUM_RECEIVERS, "Index exceeds the maximum number of receivers permitted");
305 pData->rec_pos[index][2] = newValue;
306}
307
308void ambi_roomsim_setRoomDimX(void* const hAmbi, float newValue)
309{
310 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
311 if(newValue!=pData->room_dims[0]){
312 pData->room_dims[0] = newValue;
313 }
314}
315
316void ambi_roomsim_setRoomDimY(void* const hAmbi, float newValue)
317{
318 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
319 if(newValue!=pData->room_dims[1]){
320 pData->room_dims[1] = newValue;
321 }
322}
323
324void ambi_roomsim_setRoomDimZ(void* const hAmbi, float newValue)
325{
326 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
327 if(newValue!=pData->room_dims[2]){
328 pData->room_dims[2] = newValue;
329 }
330}
331
332void ambi_roomsim_setWallAbsCoeff(void* const hAmbi, int xyz_idx, int posNeg_idx, float new_value)
333{
334 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
335 saf_assert(xyz_idx<4, "xyz_idx indicates each spatial axis, so cannot exceed 4");
336 saf_assert(posNeg_idx==0 || posNeg_idx==1, "posNeg_idx is a bool");
337 if(new_value!=pData->abs_wall[2*xyz_idx+posNeg_idx]){
338 pData->abs_wall[2*xyz_idx+posNeg_idx] = new_value;
339 }
340}
341
342void ambi_roomsim_setChOrder(void* const hAmbi, int newOrder)
343{
344 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
345 if((CH_ORDER)newOrder != CH_FUMA || pData->new_sh_order==SH_ORDER_FIRST)/* FUMA only supports 1st order */
346 pData->chOrdering = (CH_ORDER)newOrder;
347}
348
349void ambi_roomsim_setNormType(void* const hAmbi, int newType)
350{
351 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
352 if((NORM_TYPES)newType != NORM_FUMA || pData->new_sh_order==SH_ORDER_FIRST)/* FUMA only supports 1st order */
353 pData->norm = (NORM_TYPES)newType;
354}
355
356
357/* Get Functions */
358
363
364int ambi_roomsim_getEnableIMSflag(void* const hAmbi)
365{
366 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
367 return pData->enableReflections;
368}
369
371{
372 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
373 return pData->refl_order;
374}
375
376int ambi_roomsim_getOutputOrder(void* const hAmbi)
377{
378 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
379 return pData->new_sh_order;
380}
381
382int ambi_roomsim_getNumSources(void* const hAmbi)
383{
384 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
385 return pData->new_nSources;
386}
387
392
393int ambi_roomsim_getNSHrequired(void* const hAmbi)
394{
395 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
396 return (pData->new_sh_order+1)*(pData->new_sh_order+1);
397}
398
399float ambi_roomsim_getSourceX(void* const hAmbi, int index)
400{
401 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
402 saf_assert(index<=ROOM_SIM_MAX_NUM_SOURCES, "Index exceeds the maximum number of sources permitted");
403 return pData->src_pos[index][0];
404}
405
406float ambi_roomsim_getSourceY(void* const hAmbi, int index)
407{
408 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
409 saf_assert(index<=ROOM_SIM_MAX_NUM_SOURCES, "Index exceeds the maximum number of sources permitted");
410 return pData->src_pos[index][1];
411}
412
413float ambi_roomsim_getSourceZ(void* const hAmbi, int index)
414{
415 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
416 saf_assert(index<=ROOM_SIM_MAX_NUM_SOURCES, "Index exceeds the maximum number of sources permitted");
417 return pData->src_pos[index][2];
418}
419
420int ambi_roomsim_getNumReceivers(void* const hAmbi)
421{
422 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
423 return pData->new_nReceivers;
424}
425
430
431float ambi_roomsim_getReceiverX(void* const hAmbi, int index)
432{
433 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
434 saf_assert(index<=ROOM_SIM_MAX_NUM_RECEIVERS, "Index exceeds the maximum number of receivers permitted");
435 return pData->rec_pos[index][0];
436}
437
438float ambi_roomsim_getReceiverY(void* const hAmbi, int index)
439{
440 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
441 saf_assert(index<=ROOM_SIM_MAX_NUM_RECEIVERS, "Index exceeds the maximum number of receivers permitted");
442 return pData->rec_pos[index][1];
443}
444
445float ambi_roomsim_getReceiverZ(void* const hAmbi, int index)
446{
447 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
448 saf_assert(index<=ROOM_SIM_MAX_NUM_RECEIVERS, "Index exceeds the maximum number of receivers permitted");
449 return pData->rec_pos[index][2];
450}
451
452float ambi_roomsim_getRoomDimX(void* const hAmbi)
453{
454 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
455 return pData->room_dims[0];
456}
457
458float ambi_roomsim_getRoomDimY(void* const hAmbi)
459{
460 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
461 return pData->room_dims[1];
462}
463
464float ambi_roomsim_getRoomDimZ(void* const hAmbi)
465{
466 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
467 return pData->room_dims[2];
468}
469
470float ambi_roomsim_getWallAbsCoeff(void* const hAmbi, int xyz_idx, int posNeg_idx)
471{
472 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
473 return pData->abs_wall[2*xyz_idx+posNeg_idx];
474}
475
476int ambi_roomsim_getChOrder(void* const hAmbi)
477{
478 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
479 return (int)pData->chOrdering;
480}
481
482int ambi_roomsim_getNormType(void* const hAmbi)
483{
484 ambi_roomsim_data *pData = (ambi_roomsim_data*)(hAmbi);
485 return (int)pData->norm;
486}
487
#define MAX_SH_ORDER
Maximum supported Ambisonic order.
Definition _common.h:52
#define MAX_NUM_CHANNELS
Maximum number of input/output channels supported.
Definition _common.h:230
NORM_TYPES
Available Ambisonic normalisation conventions.
Definition _common.h:74
@ NORM_SN3D
Schmidt semi-normalisation (SN3D)
Definition _common.h:76
@ NORM_FUMA
(Legacy) Furse-Malham scaling
Definition _common.h:77
@ NORM_N3D
orthonormalised (N3D)
Definition _common.h:75
CH_ORDER
Available Ambisonic channel ordering conventions.
Definition _common.h:59
@ CH_ACN
Ambisonic Channel Numbering (ACN)
Definition _common.h:60
@ CH_FUMA
(Legacy) Furse-Malham/B-format (WXYZ)
Definition _common.h:61
#define MAX_NUM_SH_SIGNALS
Maximum number of spherical harmonic components/signals supported.
Definition _common.h:239
@ SH_ORDER_FIRST
First-order (4 channels)
Definition _common.h:39
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_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.
int ambi_roomsim_getMaxNumReceivers()
Returns the maximum number of receivers.
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_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_getMaxNumSources()
Returns the maximum number of input signals/sources that can be encoded.
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_getProcessingDelay()
Returns the processing delay in samples (may be used for delay compensation features)
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_getNormType(void *const hAmbi)
Returns the Ambisonic normalisation convention currently being used to encode with (see NORM_TYPES en...
const float default_abs_wall[6]
Default absorption coefficients per wall.
void ambi_roomsim_setMaxReflectionOrder(void *const hAmbi, int newValue)
Sets the maximum reflection order.
const float default_room_dims[3]
Default room dimensions.
float ambi_roomsim_getReceiverY(void *const hAmbi, int index)
Returns the 'y' coordinate for a specific receiver index.
A simple shoebox room Ambisonic encoder.
#define ROOM_SIM_MAX_NUM_RECEIVERS
Maximum supported number of receivers for the room sim example.
#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_setRoomDimensions(void *hIms, float new_roomDimensions[3])
Sets new room dimensions.
Definition saf_reverb.c:542
void ims_shoebox_removeSource(void *hIms, int sourceID)
Removes a specific source from the simulation.
Definition saf_reverb.c:793
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_updateSource(void *hIms, int sourceID, float new_position_xyz[3])
Updates the position of a specific source in the simulation.
Definition saf_reverb.c:705
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_updateReceiver(void *hIms, int receiverID, float new_position_xyz[3])
Updates the position of a specific receiver in the simulation.
Definition saf_reverb.c:749
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:55
void ims_shoebox_setWallAbsCoeffs(void *hIms, float *abs_wall)
Sets new wall absorption coefficients per wall and per band.
Definition saf_reverb.c:568
#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.
int enableReflections
0: disabled, 1: enabled
int new_nSources
New number of sources (current value will be replaced by this after next re-init)
int new_sh_order
New receiver SH order (current value will be replaced by this after next re-init)
CH_ORDER chOrdering
Ambisonic channel order convention (see CH_ORDER)
void * hIms
Image source implementation handle.
int nSources
Current number of sources.
float rec_pos[ROOM_SIM_MAX_NUM_RECEIVERS][3]
Current receiver Cartesian coordinates, meters.
float abs_wall[6]
Absorption coefficients per wall, in the order in which the axis intersect walls: +x -x +y -y +z -z.
int receiverIDs[ROOM_SIM_MAX_NUM_RECEIVERS]
Unique IDs per receiver in the simulation.
float fs
Host sampling rate, in Hz.
int nReceivers
Current number of receivers.
int sourceIDs[ROOM_SIM_MAX_NUM_SOURCES]
Unique IDs per source in the simulation.
int sh_order
Current SH order of receivers.
int reinit_room
Flag, 1: re-init required, 0: not required.
float src_pos[ROOM_SIM_MAX_NUM_SOURCES][3]
Current source Cartesian coordinates, meters.
float room_dims[3]
Room dimensions along the x,y,z axes in meters.
int new_nReceivers
New number of receivers (current value will be replaced by this after next re-init)
float ** src_sigs
Source signal buffers; ROOM_SIM_MAX_NUM_SOURCES x AMBI_ROOMSIM_FRAME_SIZE.
NORM_TYPES norm
Ambisonic normalisation convention (see NORM_TYPES)
float *** rec_sh_outsigs
Receiver signal buffers; ROOM_SIM_MAX_NUM_RECEIVERS x MAX_NUM_SH_SIGNALS x AMBI_ROOMSIM_FRAME_SIZE.
int refl_order
Current maximum image source reflection order.