SAF
Loading...
Searching...
No Matches
test__examples.c
Go to the documentation of this file.
1/*
2 * Copyright 2020-2021 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#include "saf_test.h"
26
27#ifdef SAF_ENABLE_EXAMPLES_TESTS
28
30 int nSH, i, ch, framesize;
31 void* hAmbi;
32 float leftEarEnergy, rightEarEnergy, direction_deg[2];
33 float* inSig, *y;
34 float** shSig, **binSig, **shSig_frame, **binSig_frame;
35
36 /* Config */
37 const int order = 4;
38 const int fs = 48000;
39 const int signalLength = fs*2;
40
41 /* Create and initialise an instance of ambi_bin */
42 ambi_bin_create(&hAmbi);
43
44 /* Configure and initialise the ambi_bin codec */
47 ambi_bin_initCodec(hAmbi); /* Can be called whenever (thread-safe) */
48 /* "initCodec" should be called after calling any of the "set" functions.
49 * It should be noted that intialisations are only conducted if they are
50 * needed, so calling this function periodically with a timer on a separate
51 * thread is perfectly safe and viable. Also, if the intialisations take
52 * longer than it takes to "process" the current block of samples, then the
53 * output is simply muted/zeroed during this time. */
54
55 ambi_bin_init(hAmbi, fs); /* Should be called before calling "process"
56 * Cannot be called while "process" is on-going */
57 ambi_bin_initCodec(hAmbi); /* Can be called whenever (thread-safe) */
59 ambi_bin_setYaw(hAmbi, 180.0f); /* turn the listener around */
60
61 /* Define input mono signal */
62 nSH = ORDER2NSH(order);
63 inSig = malloc1d(signalLength*sizeof(float));
64 shSig = (float**)malloc2d(nSH,signalLength,sizeof(float));
65 //rand_m1_1(inSig, signalLength); /* Mono white-noise signal */
66 memset(inSig, 0, signalLength*sizeof(float));
67 inSig[5000] = 1.f;
68 /* Encode to get input spherical harmonic (Ambisonic) signal */
69 direction_deg[0] = -90.0f; /* encode hard-right */
70 direction_deg[1] = 0.0f;
71 y = malloc1d(nSH*sizeof(float));
72 getRSH(order, (float*)direction_deg, 1, y); /* SH plane-wave weights */
73 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, signalLength, 1, 1.0f,
74 y, 1,
75 inSig, signalLength, 0.0f,
76 FLATTEN2D(shSig), signalLength);
77
78 /* Decode to binaural */
79 framesize = ambi_bin_getFrameSize();
80 binSig = (float**)calloc2d(NUM_EARS,signalLength,sizeof(float));
81 shSig_frame = (float**)malloc1d(nSH*sizeof(float*));
82 binSig_frame = (float**)malloc1d(NUM_EARS*sizeof(float*));
83 for(i=0; i<(int)((float)signalLength/(float)framesize); i++){
84 for(ch=0; ch<nSH; ch++)
85 shSig_frame[ch] = &shSig[ch][i*framesize];
86 for(ch=0; ch<NUM_EARS; ch++)
87 binSig_frame[ch] = &binSig[ch][i*framesize];
88
89 ambi_bin_process(hAmbi, (const float* const*)shSig_frame, binSig_frame, nSH, NUM_EARS, framesize);
90 }
91
92 /* Assert that left ear energy is higher than the right ear */
93 leftEarEnergy = rightEarEnergy = 0.0f;
94 for(i=0; i<signalLength; i++){
95 leftEarEnergy += powf(fabsf(binSig[0][i]), 2.0f);
96 rightEarEnergy += powf(fabsf(binSig[1][i]), 2.0f);
97 }
98 TEST_ASSERT_TRUE(leftEarEnergy>=rightEarEnergy);
99 TEST_ASSERT_TRUE(leftEarEnergy>=0.f);
100 TEST_ASSERT_TRUE(leftEarEnergy<=10.f);
101
102 /* Clean-up */
103 ambi_bin_destroy(&hAmbi);
104 free(inSig);
105 free(shSig);
106 free(y);
107 free(binSig);
108 free(shSig_frame);
109 free(binSig_frame);
110}
111
113 int nSH, i, j, ch, max_ind, framesize;
114 void* hAmbi;
115 float loudspeakerEnergy[22], direction_deg[2];
116 float* inSig, *y;
117 float** shSig, **lsSig, **shSig_frame, **lsSig_frame;
118
119 /* Config */
120 const int order = 4;
121 const int fs = 48000;
122 const int signalLength = fs*2;
123
124 /* Create and initialise an instance of ambi_dec */
125 ambi_dec_create(&hAmbi);
126
127 /* Configure and initialise the ambi_dec codec */
130 /* 22.x loudspeaker layout, SAD decoder */
131 ambi_dec_setOutputConfigPreset(hAmbi, LOUDSPEAKER_ARRAY_PRESET_22PX);
132 ambi_dec_setDecMethod(hAmbi, DECODING_METHOD_SAD, 0/* low-freq decoder */);
133 ambi_dec_setDecMethod(hAmbi, DECODING_METHOD_SAD, 1/* high-freq decoder */);
134 ambi_dec_initCodec(hAmbi); /* Can be called whenever (thread-safe) */
135 /* "initCodec" should be called after calling any of the "set" functions.
136 * It should be noted that intialisations are only conducted if they are
137 * needed, so calling this function periodically with a timer on a separate
138 * thread is perfectly safe and viable. Also, if the intialisations take
139 * longer than it takes to "process" the current block of samples, then the
140 * output is simply muted/zeroed during this time. */
141
142 ambi_dec_init(hAmbi, fs); /* Should be called before calling "process"
143 * Cannot be called while "process" is on-going */
144
145 /* Define input mono signal */
146 nSH = ORDER2NSH(order);
147 inSig = malloc1d(signalLength*sizeof(float));
148 shSig = (float**)malloc2d(nSH,signalLength,sizeof(float));
149 rand_m1_1(inSig, signalLength); /* Mono white-noise signal */
150
151 /* Encode to get input spherical harmonic (Ambisonic) signal */
152 direction_deg[0] = 90.0f; /* encode to loudspeaker direction: index 8 */
153 direction_deg[1] = 0.0f;
154 y = malloc1d(nSH*sizeof(float));
155 getRSH(order, (float*)direction_deg, 1, y); /* SH plane-wave weights */
156 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, signalLength, 1, 1.0f,
157 y, 1,
158 inSig, signalLength, 0.0f,
159 FLATTEN2D(shSig), signalLength);
160
161 /* Decode to loudspeakers */
162 framesize = ambi_dec_getFrameSize();
163 lsSig = (float**)calloc2d(22,signalLength,sizeof(float));
164 shSig_frame = (float**)malloc1d(nSH*sizeof(float*));
165 lsSig_frame = (float**)malloc1d(22*sizeof(float*));
166 for(i=0; i<(int)((float)signalLength/(float)framesize); i++){
167 for(ch=0; ch<nSH; ch++)
168 shSig_frame[ch] = &shSig[ch][i*framesize];
169 for(ch=0; ch<22; ch++)
170 lsSig_frame[ch] = &lsSig[ch][i*framesize];
171
172 ambi_dec_process(hAmbi, (const float* const*)shSig_frame, lsSig_frame, nSH, 22, framesize);
173 }
174
175 /* Assert that channel 8 (corresponding to the loudspeaker where the plane-
176 * wave was encoded to) has the most energy */
177 memset(loudspeakerEnergy, 0, 22*sizeof(float));
178 for(i=0; i<signalLength; i++){
179 for(j=0; j<22; j++)
180 loudspeakerEnergy[j] += powf(fabsf(lsSig[j][i]), 2.0f);
181 }
182 utility_simaxv(loudspeakerEnergy, 22, &max_ind);
183 TEST_ASSERT_TRUE(max_ind==7);
184
185 /* Clean-up */
186 ambi_dec_destroy(&hAmbi);
187 free(inSig);
188 free(shSig);
189 free(y);
190 free(lsSig);
191 free(shSig_frame);
192 free(lsSig_frame);
193}
194
196 int nSH, i, ch, framesize, j, delay;
197 void* hAmbi;
198 float direction_deg[2][2];
199 float** inSig, *y;
200 float** shSig, **shSig_ref, **inSig_frame, **shSig_frame;
201
202 /* Config */
203 const float acceptedTolerance = 0.000001f;
204 const int order = 4;
205 const int fs = 48000;
206 const int signalLength = fs*2;
207 direction_deg[0][0] = 90.0f; /* encode to loudspeaker direction: index 8 */
208 direction_deg[0][1] = 0.0f;
209 direction_deg[1][0] = 20.0f; /* encode to loudspeaker direction: index 8 */
210 direction_deg[1][1] = -45.0f;
212
213 /* Create and initialise an instance of ambi_enc */
214 ambi_enc_create(&hAmbi);
215 ambi_enc_init(hAmbi, fs); /* Cannot be called while "process" is on-going */
216
217 /* Configure ambi_enc */
218 ambi_enc_setOutputOrder(hAmbi, (SH_ORDERS)order);
219 ambi_enc_setNormType(hAmbi, NORM_N3D); /* (The default for all SH-related examples is SN3D) */
220 ambi_enc_setEnablePostScaling(hAmbi, 0); /* Disable scaling output by number of input channels */
221 ambi_enc_setNumSources(hAmbi, 2);
222 ambi_enc_setSourceAzi_deg(hAmbi, 0, direction_deg[0][0]);
223 ambi_enc_setSourceElev_deg(hAmbi, 0, direction_deg[0][1]);
224 ambi_enc_setSourceAzi_deg(hAmbi, 1, direction_deg[1][0]);
225 ambi_enc_setSourceElev_deg(hAmbi, 1, direction_deg[1][1]);
226
227 /* Define input mono signal */
228 nSH = ORDER2NSH(order);
229 inSig = (float**)malloc2d(2,signalLength,sizeof(float));
230 shSig_ref = (float**)malloc2d(nSH,signalLength,sizeof(float));
231 rand_m1_1(FLATTEN2D(inSig), 2*signalLength); /* Mono white-noise signal */
232
233 /* Encode reference */
234 y = malloc1d(nSH*2*sizeof(float));
235 getRSH(order, (float*)direction_deg, 2, y); /* SH plane-wave weights */
236 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, signalLength, 2, 1.0f,
237 y, 2,
238 FLATTEN2D(inSig), signalLength, 0.0f,
239 FLATTEN2D(shSig_ref), signalLength);
240
241 /* Encode via ambi_enc */
242 framesize = ambi_enc_getFrameSize();
243 shSig = (float**)calloc2d(nSH,signalLength,sizeof(float));
244 inSig_frame = (float**)malloc1d(2*sizeof(float*));
245 shSig_frame = (float**)malloc1d(nSH*sizeof(float*));
246 for(i=0; i<(int)((float)signalLength/(float)framesize); i++){
247 for(ch=0; ch<2; ch++)
248 inSig_frame[ch] = &inSig[ch][i*framesize];
249 for(ch=0; ch<nSH; ch++)
250 shSig_frame[ch] = &shSig[ch][i*framesize];
251
252 ambi_enc_process(hAmbi, (const float* const*)inSig_frame, shSig_frame, 2, nSH, framesize);
253 }
254
255 /* ambi_enc should be equivalent to the reference */
256 for(i=0; i<nSH; i++)
257 for(j=0; j<signalLength-delay; j++)
258 TEST_ASSERT_FLOAT_WITHIN(acceptedTolerance, shSig_ref[i][j], shSig[i][j+delay]);
259
260 /* Clean-up */
261 ambi_enc_destroy(&hAmbi);
262 free(inSig);
263 free(shSig);
264 free(shSig_ref);
265 free(y);
266}
267
269 int nSH, i, j, framesize, ch;
270 void* hA2sh, *safFFT, *hMC;
271 float direction_deg[2], radius;
272 float* inSig, *f;
273 float** shSig, **inSig_32, **micSig, **h_array, **micSig_frame, **shSig_frame;
274 double* kr;
275 float_complex* tmp_H;
276 float_complex*** H_array;
277
278 /* Config */
279 const int order = 4;
280 const int fs = 48000;
281 const int signalLength = fs*2;
282 const int nFFT = 1024;
283 const int nBins = nFFT/2+1;
284
285 /* Create and initialise an instance of array2sh for the Eigenmike32 */
286 array2sh_create(&hA2sh);
287 array2sh_init(hA2sh, fs); /* Cannot be called while "process" is on-going */
288 array2sh_setPreset(hA2sh, MICROPHONE_ARRAY_PRESET_EIGENMIKE32);
290
291 /* Define input mono signal */
292 nSH = ORDER2NSH(order);
293 inSig = malloc1d(signalLength*sizeof(float));
294 rand_m1_1(inSig, signalLength); /* Mono white-noise signal */
295
296 /* Simulate an Eigenmike in a free-field with a single plane-wave */
297 f = malloc1d(nBins*sizeof(float));
298 kr = malloc1d(nBins*sizeof(double));
299 getUniformFreqVector(nFFT, (float)fs, f);
300 f[0] = f[1]/4.0f; /* To avoid NaNs at DC */
301 radius = 0.042f;
302 for(i=0; i<nBins; i++)
303 kr[i] = 2.0*SAF_PId*(f[i])*(radius)/343.0f;
304 direction_deg[0] = 90.0f;
305 direction_deg[1] = 0.0f;
306 H_array = (float_complex***)malloc3d(nBins, 32, 1, sizeof(float_complex));
307 simulateSphArray(order, kr, kr, nBins, (float*)__Eigenmike32_coords_rad, 32,
308 (float*)direction_deg, 1, ARRAY_CONSTRUCTION_RIGID, 1.0f, FLATTEN3D(H_array));
309
310 /* Inverse FFT to get the time-domain filters */
311 tmp_H = malloc1d(nBins*sizeof(float_complex));
312 h_array = (float**)malloc2d(32, nFFT, sizeof(float));
313 saf_rfft_create(&safFFT, nFFT);
314 for(i=0; i<32; i++){
315 for(j=0; j<nBins; j++)
316 tmp_H[j] = H_array[j][i][0];
317 saf_rfft_backward(safFFT, tmp_H, h_array[i]);
318 }
319
320 /* Simulate the Eigenmike time-domain signals by convolving the mono signal
321 * with each sensor transfer function */
322 micSig = (float**)calloc2d(32, signalLength, sizeof(float));
323 inSig_32 = (float**)malloc2d(32, signalLength, sizeof(float));
324 for(i=0; i<32; i++) /* Replicate inSig for all 32 channels */
325 memcpy(inSig_32[i], inSig, signalLength* sizeof(float));
326 saf_multiConv_create(&hMC, 256, FLATTEN2D(h_array), nFFT, 32, 0);
327 for(i=0; i<(int)((float)signalLength/256.0f); i++)
328 saf_multiConv_apply(hMC, FLATTEN2D(inSig_32), FLATTEN2D(micSig));
329
330 /* Encode simulated Eigenmike signals into spherical harmonic signals */
331 framesize = array2sh_getFrameSize();
332 shSig = (float**)malloc2d(nSH,signalLength,sizeof(float));
333 micSig_frame = (float**)malloc1d(32*sizeof(float*));
334 shSig_frame = (float**)malloc1d(nSH*sizeof(float*));
335 for(i=0; i<(int)((float)signalLength/(float)framesize); i++){
336 for(ch=0; ch<32; ch++)
337 micSig_frame[ch] = &micSig[ch][i*framesize];
338 for(ch=0; ch<nSH; ch++)
339 shSig_frame[ch] = &shSig[ch][i*framesize];
340
341 array2sh_process(hA2sh, (const float* const*)micSig_frame, shSig_frame, 32, nSH, framesize);
342 }
343
344 /* Clean-up */
345 array2sh_destroy(&hA2sh);
346 saf_rfft_destroy(&safFFT);
348 free(inSig);
349 free(shSig);
350 free(inSig_32);
351 free(f);
352 free(kr);
353 free(H_array);
354 free(h_array);
355 free(tmp_H);
356 free(micSig_frame);
357 free(shSig_frame);
358}
359
361 int ch, nSH, i, j, delay, framesize;
362 void* hRot;
363 float direction_deg[2], ypr[3], Rzyx[3][3];
364 float** inSig, *y, **shSig_frame, **shSig_rot_frame;
365 float** shSig, **shSig_rot, **shSig_rot_ref, **Mrot;
366
367 /* Config */
368 const float acceptedTolerance = 0.000001f;
369 const int order = 4;
370 const int fs = 48000;
371 const int signalLength = fs*2;
372 direction_deg[0] = 90.0f; /* encode to loudspeaker direction: index 8 */
373 direction_deg[1] = 0.0f;
374 ypr[0] = -0.4f;
375 ypr[1] = -1.4f;
376 ypr[2] = 2.1f;
378
379 /* Create and initialise an instance of rotator */
380 rotator_create(&hRot);
381 rotator_init(hRot, fs); /* Cannot be called while "process" is on-going */
382
383 /* Configure rotator codec */
384 rotator_setOrder(hRot, (SH_ORDERS)order);
386 rotator_setYaw(hRot, ypr[0]*180.0f/SAF_PI); /* rad->degrees */
387 rotator_setPitch(hRot, ypr[1]*180.0f/SAF_PI);
388 rotator_setRoll(hRot, ypr[2]*180.0f/SAF_PI);
389
390 /* Define input mono signal */
391 nSH = ORDER2NSH(order);
392 inSig = (float**)malloc2d(1,signalLength,sizeof(float));
393 shSig = (float**)malloc2d(nSH,signalLength,sizeof(float));
394 rand_m1_1(FLATTEN2D(inSig), signalLength); /* Mono white-noise signal */
395
396 /* Encode */
397 y = malloc1d(nSH*sizeof(float));
398 getRSH(order, (float*)direction_deg, 1, y); /* SH plane-wave weights */
399 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, signalLength, 1, 1.0f,
400 y, 1,
401 FLATTEN2D(inSig), signalLength, 0.0f,
402 FLATTEN2D(shSig), signalLength);
403
404 /* Rotated version reference */
405 Mrot = (float**)malloc2d(nSH, nSH, sizeof(float));
406 yawPitchRoll2Rzyx(ypr[0], ypr[1], ypr[2], 0, Rzyx);
407 getSHrotMtxReal(Rzyx, FLATTEN2D(Mrot), order);
408 shSig_rot_ref = (float**)malloc2d(nSH,signalLength,sizeof(float));
409 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, nSH, signalLength, nSH, 1.0f,
410 FLATTEN2D(Mrot), nSH,
411 FLATTEN2D(shSig), signalLength, 0.0f,
412 FLATTEN2D(shSig_rot_ref), signalLength);
413
414 /* Rotate with rotator */
415 framesize = rotator_getFrameSize();
416 shSig_rot = (float**)malloc2d(nSH,signalLength,sizeof(float));
417 shSig_frame = (float**)malloc1d(nSH*sizeof(float*));
418 shSig_rot_frame = (float**)malloc1d(nSH*sizeof(float*));
419 for(i=0; i<(int)((float)signalLength/(float)framesize); i++){
420 for(ch=0; ch<nSH; ch++)
421 shSig_frame[ch] = &shSig[ch][i*framesize];
422 for(ch=0; ch<nSH; ch++)
423 shSig_rot_frame[ch] = &shSig_rot[ch][i*framesize];
424
425 rotator_process(hRot, (const float* const*)shSig_frame, shSig_rot_frame, nSH, nSH, framesize);
426 }
427
428 /* ambi_enc should be equivalent to the reference, except delayed due to the
429 * temporal interpolation employed in ambi_enc */
430 for(i=0; i<nSH; i++)
431 for(j=0; j<signalLength-delay; j++)
432 TEST_ASSERT_FLOAT_WITHIN(acceptedTolerance, shSig_rot_ref[i][j], shSig_rot[i][j+delay]);
433
434 /* Clean-up */
435 rotator_destroy(&hRot);
436 free(inSig);
437 free(shSig);
438 free(shSig_rot_ref);
439 free(Mrot);
440 free(y);
441 free(shSig_frame);
442 free(shSig_rot_frame);
443}
444
446 int i, ch, framesize, nOutputs;
447 void* hSpr;
448 float** inSigs, **outSigs;
449 float** inSig_frame, **outSig_frame;
450
451 /* Config */
452 const int fs = 48000;
453 const int nInputs = 1;
454 const int signalLength = fs*2;
455
456 /* Create and initialise an instance of spreader */
457 spreader_create(&hSpr);
458
459 /* Configure and initialise the spreader codec */
461 nOutputs = NUM_EARS; /* the default is binaural operation */
462 spreader_setNumSources(hSpr, nInputs);
463 spreader_init(hSpr, fs); /* Should be called before calling "process"
464 * Cannot be called while "process" is on-going */
465 spreader_initCodec(hSpr); /* Can be called whenever (thread-safe) */
466
467 /* Define input mono signal */
468 inSigs = (float**)malloc2d(nInputs,signalLength,sizeof(float));
469 outSigs = (float**)malloc2d(nOutputs,signalLength,sizeof(float));
470 rand_m1_1(FLATTEN2D(inSigs), nInputs*signalLength); /* white-noise signals */
471
472 /* Apply spreader */
473 framesize = spreader_getFrameSize();
474 inSig_frame = (float**)malloc1d(nInputs*sizeof(float*));
475 outSig_frame = (float**)malloc1d(nOutputs*sizeof(float*));
476 for(i=0; i<(int)((float)signalLength/(float)framesize); i++){
477 for(ch=0; ch<nInputs; ch++)
478 inSig_frame[ch] = &inSigs[ch][i*framesize];
479 for(ch=0; ch<nOutputs; ch++)
480 outSig_frame[ch] = &outSigs[ch][i*framesize];
481
482 spreader_process(hSpr, (const float* const*)inSig_frame, outSig_frame, nInputs, nOutputs, framesize);
483 }
484
485 /* Clean-up */
486 spreader_destroy(&hSpr);
487 free(inSigs);
488 free(outSigs);
489 free(inSig_frame);
490 free(outSig_frame);
491}
492
493#endif /* SAF_ENABLE_EXAMPLES_TESTS */
@ NORM_N3D
orthonormalised (N3D)
Definition _common.h:75
SH_ORDERS
Available spherical harmonic (SH) input/output order options.
Definition _common.h:38
void ambi_bin_setInputOrderPreset(void *const hAmbi, SH_ORDERS newPreset)
Sets the decoding order (see SH_ORDERS enum)
Definition ambi_bin.c:534
void ambi_bin_create(void **const phAmbi)
Creates an instance of ambi_bin.
Definition ambi_bin.c:51
void ambi_bin_initCodec(void *const hAmbi)
Intialises the codec variables, based on current global/user parameters.
Definition ambi_bin.c:169
void ambi_bin_process(void *const hAmbi, const float *const *inputs, float *const *const outputs, int nInputs, int nOutputs, int nSamples)
Decodes input spherical harmonic signals to the binaural channels.
Definition ambi_bin.c:403
void ambi_bin_setNormType(void *const hAmbi, int newType)
Sets the Ambisonic normalisation convention to decode with, in order to match with the convention emp...
Definition ambi_bin.c:562
void ambi_bin_setEnableRotation(void *const hAmbi, int newState)
Sets the flag to enable/disable (1 or 0) sound-field rotation.
Definition ambi_bin.c:605
void ambi_bin_setYaw(void *const hAmbi, float newYaw_deg)
Sets the 'yaw' rotation angle, in degrees.
Definition ambi_bin.c:611
int ambi_bin_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition ambi_bin.c:668
void ambi_bin_destroy(void **const phAmbi)
Destroys an instance of ambi_bin.
Definition ambi_bin.c:111
void ambi_bin_init(void *const hAmbi, int samplerate)
Initialises ambi_bin with default settings, and samplerate.
Definition ambi_bin.c:149
void ambi_dec_create(void **const phAmbi)
Creates an instance of the ambi_dec.
Definition ambi_dec.c:49
void ambi_dec_init(void *const hAmbi, int samplerate)
Initialises an instance of ambi_dec with default settings.
Definition ambi_dec.c:171
int ambi_dec_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition ambi_dec.c:831
void ambi_dec_initCodec(void *const hAmbi)
Intialises the codec variables, based on current global/user parameters.
Definition ambi_dec.c:184
void ambi_dec_process(void *const hAmbi, const float *const *inputs, float *const *outputs, int nInputs, int nOutputs, int nSamples)
Decodes input spherical harmonic signals to the loudspeaker channels.
Definition ambi_dec.c:470
void ambi_dec_setOutputConfigPreset(void *const hAmbi, int newPresetID)
Sets the output loudspeaker preset.
Definition ambi_dec.c:712
@ DECODING_METHOD_SAD
Sampling Ambisonic Decoder (SAD)
Definition ambi_dec.h:74
void ambi_dec_setDecMethod(void *const hAmbi, int index, int newID)
Sets the decoding method for a specific decoder.
Definition ambi_dec.c:803
void ambi_dec_setMasterDecOrder(void *const hAmbi, int newValue)
Sets the master decoding order.
Definition ambi_dec.c:607
void ambi_dec_setNormType(void *const hAmbi, int newType)
Sets the Ambisonic normalisation convention to decode with, in order to match with the convention emp...
Definition ambi_dec.c:796
void ambi_dec_destroy(void **const phAmbi)
Destroys an instance of the ambi_dec.
Definition ambi_dec.c:120
void ambi_enc_setEnablePostScaling(void *const hAmbi, int newStatus)
By default, ambi_enc will scale the output signals by the number of input signals.
Definition ambi_enc.c:285
int ambi_enc_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition ambi_enc.c:202
void ambi_enc_setOutputOrder(void *const hAmbi, int newValue)
Sets the encoding order (see SH_ORDERS enum)
Definition ambi_enc.c:215
int ambi_enc_getProcessingDelay(void)
Returns the processing delay in samples (may be used for delay compensation features)
Definition ambi_enc.c:371
void ambi_enc_setSourceElev_deg(void *const hAmbi, int index, float newElev_deg)
Sets the elevation for a specific source index.
Definition ambi_enc.c:242
void ambi_enc_setNormType(void *const hAmbi, int newType)
Sets the Ambisonic normalisation convention to encode with (see NORM_TYPES enum)
Definition ambi_enc.c:278
void ambi_enc_init(void *const hAmbi, int samplerate)
Initialises an instance of ambi_enc with default settings.
Definition ambi_enc.c:69
void ambi_enc_setNumSources(void *const hAmbi, int new_nSources)
Sets the number of input signals/sources to encode.
Definition ambi_enc.c:251
void ambi_enc_setSourceAzi_deg(void *const hAmbi, int index, float newAzi_deg)
Sets the azimuth for a specific source index.
Definition ambi_enc.c:231
void ambi_enc_destroy(void **const phAmbi)
Destroys an instance of ambi_enc.
Definition ambi_enc.c:55
void ambi_enc_process(void *const hAmbi, const float *const *inputs, float *const *outputs, int nInputs, int nOutputs, int nSamples)
Encodes input signals into spherical harmonic signals, at the specified encoding directions.
Definition ambi_enc.c:89
void ambi_enc_create(void **const phAmbi)
Creates an instance of ambi_enc.
Definition ambi_enc.c:30
void array2sh_setNormType(void *const hA2sh, int newType)
Sets the Ambisonic normalisation convention to encode with, in order to match with the convention emp...
Definition array2sh.c:489
void array2sh_destroy(void **const phA2sh)
Destroys an instance of array2sh.
Definition array2sh.c:105
void array2sh_create(void **const phA2sh)
Creates an instance of array2sh.
Definition array2sh.c:53
void array2sh_setPreset(void *const hA2sh, ARRAY2SH_MICROPHONE_ARRAY_PRESETS preset)
Sets a pre-defined microphone/hydrophone array preset (See ARRAY2SH_MICROPHONE_ARRAY_PRESETS enum)
Definition array2sh.c:327
void array2sh_init(void *const hA2sh, int samplerate)
Initialises an instance of array2sh with default settings.
Definition array2sh.c:149
void array2sh_process(void *const hA2sh, const float *const *inputs, float *const *outputs, int nInputs, int nOutputs, int nSamples)
Spatially encode microphone/hydrophone array signals into spherical harmonic signals.
Definition array2sh.c:186
int array2sh_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition array2sh.c:516
void getRSH(int N, float *dirs_deg, int nDirs, float *Y)
Computes real-valued spherical harmonics [1] for each given direction on the unit sphere.
Definition saf_hoa.c:119
#define ORDER2NSH(order)
Converts spherical harmonic order to number of spherical harmonic components i.e: (order+1)^2.
Definition saf_sh.h:51
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...
Definition saf_sh.c:2769
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...
Definition saf_sh.c:586
@ ARRAY_CONSTRUCTION_RIGID
Rigid baffle, omni-directional sensors.
Definition saf_sh.h:68
void saf_multiConv_destroy(void **const phMC)
Destroys an instance of multiConv.
#define SAF_PI
pi constant (single precision)
const float __Eigenmike32_coords_rad[32][2]
Sensor array coordinates for the Eigenmike32.
void saf_multiConv_apply(void *const hMC, float *inputSig, float *outputSig)
Performs the multi-channel convolution.
#define NUM_EARS
2 (true for most humans)
#define SAF_PId
pi constant (double precision)
void saf_rfft_create(void **const phFFT, int N)
Creates an instance of saf_rfft; real<->half-complex (conjugate-symmetric) FFT.
void saf_multiConv_create(void **const phMC, int hopSize, float *H, int length_h, int nCH, int usePartFLAG)
Creates an instance of multiConv.
void getUniformFreqVector(int fftSize, float fs, float *freqVector)
Calculates the frequencies (in Hz) of uniformly spaced bins, for a given FFT size and sampling rate.
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 yawPitchRoll2Rzyx(float yaw, float pitch, float roll, int rollPitchYawFLAG, float R[3][3])
Constructs a 3x3 rotation matrix from the Euler angles, using the yaw-pitch-roll (zyx) convention.
void rand_m1_1(float *vector, int length)
Generates random numbers between -1 and 1 and stores them in the input vector.
void utility_simaxv(const float *a, const int len, int *index)
Single-precision, index of maximum absolute value in a vector, i.e.
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
void ** calloc2d(size_t dim1, size_t dim2, size_t data_size)
2-D calloc (contiguously allocated, so use free() as usual to deallocate)
Definition md_malloc.c:102
#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
#define FLATTEN3D(A)
Use this macro when passing a 3-D dynamic multi-dimensional array to memset, memcpy or any other func...
Definition md_malloc.h:72
int rotator_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition rotator.c:333
void rotator_setPitch(void *const hRot, float newPitch)
Sets the 'pitch' rotation angle, in DEGREES.
Definition rotator.c:218
void rotator_create(void **const phRot)
Creates an instance of rotator.
Definition rotator.c:38
int rotator_getProcessingDelay(void)
Returns the processing delay in samples (may be used for delay compensation features)
Definition rotator.c:434
void rotator_init(void *const hRot, int samplerate)
Initialises an instance of rotator with default settings.
Definition rotator.c:80
void rotator_destroy(void **const phRot)
Destroys an instance of rotator.
Definition rotator.c:67
void rotator_setRoll(void *const hRot, float newRoll)
Sets the 'roll' rotation angle , in DEGREES.
Definition rotator.c:225
void rotator_setNormType(void *const hRot, int newType)
Sets the Ambisonic normalisation convention to decode with, in order to match with the convention emp...
Definition rotator.c:311
void rotator_process(void *const hRot, const float *const *inputs, float *const *outputs, int nInputs, int nOutputs, int nSamples)
Rotates the input spherical harmonic signals.
Definition rotator.c:102
void rotator_setYaw(void *const hRot, float newYaw)
Sets the 'yaw' rotation angle, in DEGREES.
Definition rotator.c:211
void rotator_setOrder(void *const hRot, int newOrder)
Sets the input/output order (see SH_ORDERS enum)
Definition rotator.c:318
Unit test program for the Spatial_Audio_Framework.
void spreader_init(void *const hSpr, int samplerate)
Initialises an instance of spreader with default settings.
Definition spreader.c:195
void spreader_create(void **const phSpr)
Creates an instance of the spreader.
Definition spreader.c:35
int spreader_getFrameSize(void)
Returns the processing framesize (i.e., number of samples processed with every _process() call )
Definition spreader.c:771
void spreader_initCodec(void *const hSpr)
Intialises the codec variables, based on current global/user parameters.
Definition spreader.c:208
void spreader_setNumSources(void *const hSpr, int new_nSources)
Sets the number of input channels/sources to binauralise.
Definition spreader.c:742
void spreader_destroy(void **const phSpr)
Destroys an instance of the spreader.
Definition spreader.c:120
void spreader_setUseDefaultHRIRsflag(void *const hSpr, int newState)
Sets flag to dictate whether the default HRIRs in the Spatial_Audio_Framework should be used (1),...
Definition spreader.c:749
void spreader_process(void *const hSpr, const float *const *inputs, float *const *outputs, int nInputs, int nOutputs, int nSamples)
Spatialises and spreads the input signals in the user specified directions.
Definition spreader.c:361
void test__saf_example_array2sh(void)
Testing the SAF array2sh.h example (this may also serve as a tutorial on how to use it)
void test__saf_example_rotator(void)
Testing the SAF rotator.h example (this may also serve as a tutorial on how to use it)
void test__saf_example_ambi_enc(void)
Testing the SAF ambi_enc.h example (this may also serve as a tutorial on how to use it)
void test__saf_example_ambi_bin(void)
Testing the SAF ambi_bin.h example (this may also serve as a tutorial on how to use it)
void test__saf_example_spreader(void)
Testing the SAF spreader.h example (this may also serve as a tutorial on how to use it)
void test__saf_example_ambi_dec(void)
Testing the SAF ambi_dec.h example (this may also serve as a tutorial on how to use it)