SAF
Loading...
Searching...
No Matches
ambi_dec_internal.c
Go to the documentation of this file.
1/*
2 * Copyright 2017-2018 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
46#include "ambi_dec_internal.h"
47
48void ambi_dec_setCodecStatus(void* const hAmbi, CODEC_STATUS newStatus)
49{
50 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
51 if(newStatus==CODEC_STATUS_NOT_INITIALISED){
52 /* Pause until current initialisation is complete */
54 SAF_SLEEP(10);
55 }
56 pData->codecStatus = newStatus;
57}
58
60(
61 void* const hAmbi,
62 float azimuth_deg,
63 float elevation_deg,
64 float_complex h_intrp[HYBRID_BANDS][NUM_EARS]
65)
66{
67 ambi_dec_data *pData = (ambi_dec_data*)(hAmbi);
68 ambi_dec_codecPars* pars = pData->pars;
69 int i, band;
70 int aziIndex, elevIndex, N_azi, idx3d;
71 float_complex ipd;
72 float aziRes, elevRes, weights[1][3], itds3[3], itdInterp[1];
73 float magnitudes3[HYBRID_BANDS][3][NUM_EARS], magInterp[HYBRID_BANDS][NUM_EARS];
74
75 /* find closest pre-computed VBAP direction */
76 aziRes = (float)pars->hrtf_vbapTableRes[0];
77 elevRes = (float)pars->hrtf_vbapTableRes[1];
78 N_azi = (int)(360.0f / aziRes + 0.5f) + 1;
79 aziIndex = (int)(matlab_fmodf(azimuth_deg + 180.0f, 360.0f) / aziRes + 0.5f);
80 elevIndex = (int)((elevation_deg + 90.0f) / elevRes + 0.5f);
81 idx3d = elevIndex * N_azi + aziIndex;
82 for (i = 0; i < 3; i++)
83 weights[0][i] = pars->hrtf_vbap_gtableComp[idx3d*3 + i];
84
85 /* retrieve the 3 itds and hrtf magnitudes */
86 for (i = 0; i < 3; i++) {
87 itds3[i] = pars->itds_s[pars->hrtf_vbap_gtableIdx[idx3d*3+i]];
88 for (band = 0; band < HYBRID_BANDS; band++) {
89 magnitudes3[band][i][0] = pars->hrtf_fb_mag[band*NUM_EARS*(pars->N_hrir_dirs) + 0*(pars->N_hrir_dirs) + pars->hrtf_vbap_gtableIdx[idx3d*3+i]];
90 magnitudes3[band][i][1] = pars->hrtf_fb_mag[band*NUM_EARS*(pars->N_hrir_dirs) + 1*(pars->N_hrir_dirs) + pars->hrtf_vbap_gtableIdx[idx3d*3+i]];
91 }
92 }
93
94 /* interpolate hrtf magnitudes and itd seperately */
95 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 1, 1, 3, 1,
96 (float*)weights, 3,
97 (float*)itds3, 1, 0,
98 (float*)itdInterp, 1);
99 for (band = 0; band < HYBRID_BANDS; band++) {
100 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 1, 2, 3, 1,
101 (float*)weights, 3,
102 (float*)magnitudes3[band], 2, 0,
103 (float*)magInterp[band], 2);
104 }
105
106 /* reintroduce the interaural phase difference per band */
107 for (band = 0; band < HYBRID_BANDS; band++) {
108 if(pData->freqVector[band]<1.5e3f)
109 ipd = cmplxf(0.0f, (matlab_fmodf(2.0f*SAF_PI*(pData->freqVector[band]) * itdInterp[0] + SAF_PI, 2.0f*SAF_PI) - SAF_PI)/2.0f);
110 else
111 ipd = cmplxf(0.0f, 0.0f);
112 h_intrp[band][0] = ccmulf(cmplxf(magInterp[band][0], 0.0f), cexpf(ipd));
113 h_intrp[band][1] = ccmulf(cmplxf(magInterp[band][1], 0.0f), conjf(cexpf(ipd)));
114 }
115}
116
118(
120 float dirs_deg[MAX_NUM_LOUDSPEAKERS][2],
121 int* newNCH,
122 int* nDims
123)
124{
125 float sum_elev;
126 int ch, i, nCH;
127
128 nCH = ch = 0;
129 switch(preset){
130 default:
131 /* fall through */
132 case LOUDSPEAKER_ARRAY_PRESET_DEFAULT:
133 /* fall through */
134 case LOUDSPEAKER_ARRAY_PRESET_5PX:
135 nCH = 5;
136 for(ch=0; ch<nCH; ch++)
137 for(i=0; i<2; i++)
138 dirs_deg[ch][i] = __5pX_dirs_deg[ch][i];
139 break;
140 case LOUDSPEAKER_ARRAY_PRESET_7PX:
141 nCH = 7;
142 for(ch=0; ch<nCH; ch++)
143 for(i=0; i<2; i++)
144 dirs_deg[ch][i] = __7pX_dirs_deg[ch][i];
145 break;
146 case LOUDSPEAKER_ARRAY_PRESET_8PX:
147 nCH = 8;
148 for(ch=0; ch<nCH; ch++)
149 for(i=0; i<2; i++)
150 dirs_deg[ch][i] = __8pX_dirs_deg[ch][i];
151 break;
152 case LOUDSPEAKER_ARRAY_PRESET_9PX:
153 nCH = 9;
154 for(ch=0; ch<nCH; ch++)
155 for(i=0; i<2; i++)
156 dirs_deg[ch][i] = __9pX_dirs_deg[ch][i];
157 break;
158 case LOUDSPEAKER_ARRAY_PRESET_10PX:
159 nCH = 10;
160 for(ch=0; ch<nCH; ch++)
161 for(i=0; i<2; i++)
162 dirs_deg[ch][i] = __10pX_dirs_deg[ch][i];
163 break;
164 case LOUDSPEAKER_ARRAY_PRESET_11PX:
165 nCH = 11;
166 for(ch=0; ch<nCH; ch++)
167 for(i=0; i<2; i++)
168 dirs_deg[ch][i] = __11pX_dirs_deg[ch][i];
169 break;
170 case LOUDSPEAKER_ARRAY_PRESET_11PX_7_4:
171 nCH = 11;
172 for(ch=0; ch<nCH; ch++)
173 for(i=0; i<2; i++)
174 dirs_deg[ch][i] = __11pX_7_4_dirs_deg[ch][i];
175 break;
176 case LOUDSPEAKER_ARRAY_PRESET_13PX:
177 nCH = 13;
178 for(ch=0; ch<nCH; ch++)
179 for(i=0; i<2; i++)
180 dirs_deg[ch][i] = __13pX_dirs_deg[ch][i];
181 break;
182 case LOUDSPEAKER_ARRAY_PRESET_22PX:
183 nCH = 22;
184 for(ch=0; ch<nCH; ch++)
185 for(i=0; i<2; i++)
186 dirs_deg[ch][i] = __22pX_dirs_deg[ch][i];
187 break;
188 case LOUDSPEAKER_ARRAY_PRESET_22P2_9_10_3:
189 saf_print_error("Not suitable, since it contains LFE channels");
190 break;
191 case LOUDSPEAKER_ARRAY_PRESET_AALTO_MCC:
192 nCH = 45;
193 for(ch=0; ch<nCH; ch++)
194 for(i=0; i<2; i++)
195 dirs_deg[ch][i] = __Aalto_MCC_dirs_deg[ch][i];
196 break;
197 case LOUDSPEAKER_ARRAY_PRESET_AALTO_MCC_SUBSET:
198 nCH = 37;
199 for(ch=0; ch<nCH; ch++)
200 for(i=0; i<2; i++)
201 dirs_deg[ch][i] = __Aalto_MCCsubset_dirs_deg[ch][i];
202 break;
203 case LOUDSPEAKER_ARRAY_PRESET_AALTO_APAJA:
204 nCH = 29;
205 for(ch=0; ch<nCH; ch++)
206 for(i=0; i<2; i++)
207 dirs_deg[ch][i] = __Aalto_Apaja_dirs_deg[ch][i];
208 break;
209 case LOUDSPEAKER_ARRAY_PRESET_AALTO_LR:
210 nCH = 13;
211 for(ch=0; ch<nCH; ch++)
212 for(i=0; i<2; i++)
213 dirs_deg[ch][i] = __Aalto_LR_dirs_deg[ch][i];
214 break;
215 case LOUDSPEAKER_ARRAY_PRESET_DTU_AVIL:
216 nCH = 64;
217 for(ch=0; ch<nCH; ch++)
218 for(i=0; i<2; i++)
219 dirs_deg[ch][i] = __DTU_AVIL_dirs_deg[ch][i];
220 break;
221 case LOUDSPEAKER_ARRAY_PRESET_ZYLIA_LAB:
222 nCH = 22;
223 for(ch=0; ch<nCH; ch++)
224 for(i=0; i<2; i++)
225 dirs_deg[ch][i] = __Zylia_Lab_dirs_deg[ch][i];
226 break;
227 case LOUDSPEAKER_ARRAY_PRESET_T_DESIGN_4:
228 nCH = 4;
229 for(ch=0; ch<nCH; ch++)
230 for(i=0; i<2; i++)
231 dirs_deg[ch][i] = __Tdesign_degree_2_dirs_deg[ch][i];
232 break;
233 case LOUDSPEAKER_ARRAY_PRESET_T_DESIGN_12:
234 nCH = 12;
235 for(ch=0; ch<nCH; ch++)
236 for(i=0; i<2; i++)
237 dirs_deg[ch][i] = __Tdesign_degree_4_dirs_deg[ch][i];
238 break;
239 case LOUDSPEAKER_ARRAY_PRESET_T_DESIGN_24:
240 nCH = 24;
241 for(ch=0; ch<nCH; ch++)
242 for(i=0; i<2; i++)
243 dirs_deg[ch][i] = __Tdesign_degree_6_dirs_deg[ch][i];
244 break;
245 case LOUDSPEAKER_ARRAY_PRESET_T_DESIGN_36:
246 nCH = 36;
247 for(ch=0; ch<nCH; ch++)
248 for(i=0; i<2; i++)
249 dirs_deg[ch][i] = __Tdesign_degree_8_dirs_deg[ch][i];
250 break;
251 case LOUDSPEAKER_ARRAY_PRESET_T_DESIGN_48:
252 nCH = 48;
253 for(ch=0; ch<nCH; ch++)
254 for(i=0; i<2; i++)
255 dirs_deg[ch][i] = __Tdesign_degree_9_dirs_deg[ch][i];
256 break;
257 case LOUDSPEAKER_ARRAY_PRESET_T_DESIGN_60:
258 nCH = 60;
259 for(ch=0; ch<nCH; ch++)
260 for(i=0; i<2; i++)
261 dirs_deg[ch][i] = __Tdesign_degree_10_dirs_deg[ch][i];
262 break;
263 case LOUDSPEAKER_ARRAY_PRESET_SPH_COV_9:
264 nCH = 9;
265 for(ch=0; ch<nCH; ch++)
266 for(i=0; i<2; i++)
267 dirs_deg[ch][i] = __SphCovering_9_dirs_deg[ch][i];
268 break;
269 case LOUDSPEAKER_ARRAY_PRESET_SPH_COV_16:
270 nCH = 16;
271 for(ch=0; ch<nCH; ch++)
272 for(i=0; i<2; i++)
273 dirs_deg[ch][i] = __SphCovering_16_dirs_deg[ch][i];
274 break;
275 case LOUDSPEAKER_ARRAY_PRESET_SPH_COV_25:
276 nCH = 25;
277 for(ch=0; ch<nCH; ch++)
278 for(i=0; i<2; i++)
279 dirs_deg[ch][i] = __SphCovering_25_dirs_deg[ch][i];
280 break;
281 case LOUDSPEAKER_ARRAY_PRESET_SPH_COV_49:
282 nCH = 49;
283 for(ch=0; ch<nCH; ch++)
284 for(i=0; i<2; i++)
285 dirs_deg[ch][i] = __SphCovering_49_dirs_deg[ch][i];
286 break;
287 case LOUDSPEAKER_ARRAY_PRESET_SPH_COV_64:
288 nCH = 64;
289 for(ch=0; ch<nCH; ch++)
290 for(i=0; i<2; i++)
291 dirs_deg[ch][i] = __SphCovering_64_dirs_deg[ch][i];
292 break;
293 }
294 saf_assert(nCH>0, "Number of loudspeakers must be more than 0");
295
296 /* Fill remaining slots with default coords */
297 for(; ch<MAX_NUM_LOUDSPEAKERS; ch++)
298 for(i=0; i<2; i++)
299 dirs_deg[ch][i] = __default_LScoords128_deg[ch][i];
300
301 /* specify new number of channels (for dynamically changing the number of TFT channels) */
302 (*newNCH) = nCH;
303
304 /* Estimate number of dimensions.
305 * (Fails if using 2D setups are not on the horizontal plane ) */
306 sum_elev = 0.0f;
307 for(i=0; i<nCH; i++)
308 sum_elev += fabsf(dirs_deg[i][1]);
309 if(sum_elev < 0.01f)
310 (*nDims) = 2;
311 else
312 (*nDims) = 3;
313}
LOUDSPEAKER_ARRAY_PRESETS
Available loudspeaker array presets.
Definition _common.h:99
CODEC_STATUS
Current status of the codec.
Definition _common.h:201
@ CODEC_STATUS_NOT_INITIALISED
Codec has not yet been initialised, or the codec configuration has changed.
Definition _common.h:204
@ CODEC_STATUS_INITIALISING
Codec is currently being initialised, input audio should not be processed.
Definition _common.h:207
#define HYBRID_BANDS
Number of frequency bands.
void ambi_dec_setCodecStatus(void *const hAmbi, CODEC_STATUS newStatus)
Sets codec status (see CODEC_STATUS enum)
void ambi_dec_interpHRTFs(void *const hAmbi, float azimuth_deg, float elevation_deg, float_complex h_intrp[HYBRID_BANDS][NUM_EARS])
Interpolates between the 3 nearest HRTFs using amplitude-preserving VBAP gains.
void loadLoudspeakerArrayPreset(LOUDSPEAKER_ARRAY_PRESETS preset, float dirs_deg[MAX_NUM_LOUDSPEAKERS][2], int *newNCH, int *nDims)
Returns the loudspeaker directions for a specified loudspeaker array preset.
A frequency-dependent Ambisonic decoder for reproducing Ambisonic sound scenes over loudspeakers.
#define MAX_NUM_LOUDSPEAKERS
Maximum permitted output channels.
#define saf_print_error(message)
Macro to print a error message along with the filename and line number.
const float __Zylia_Lab_dirs_deg[22][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for the 22.x setup, at Zylia Labs.
#define saf_assert(x, message)
Macro to make an assertion, along with a string explaining its purpose.
#define SAF_PI
pi constant (single precision)
const float __9pX_dirs_deg[9][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 9.x setup.
const float __SphCovering_16_dirs_deg[16][2]
Directions [azimuth, Elevation] in degrees, for sphere covering: 16 dirs.
const float __Aalto_MCC_dirs_deg[45][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for the multi-channel anechoic chamber (MCC),...
const float __SphCovering_49_dirs_deg[49][2]
Directions [azimuth, Elevation] in degrees, for sphere covering: 49 dirs.
#define NUM_EARS
2 (true for most humans)
float matlab_fmodf(float x, float y)
C fmodf function, except it behaves like 'mod' in Matlab (i.e.
const float __5pX_dirs_deg[5][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 5.x setup.
const float __11pX_dirs_deg[11][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 11.x setup.
const float __Tdesign_degree_9_dirs_deg[48][2]
Directions [azimuth, Elevation] in degrees, for minimum Tdesign degree: 9.
const float __Tdesign_degree_2_dirs_deg[4][2]
Directions [azimuth, Elevation] in degrees, for minimum Tdesign degree: 2.
const float __11pX_7_4_dirs_deg[11][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 7.4.x setup.
const float __Tdesign_degree_8_dirs_deg[36][2]
Directions [azimuth, Elevation] in degrees, for minimum Tdesign degree: 8.
const float __default_LScoords128_deg[128][2]
Default Loudspeaker directions [azimuth, Elevation] - to replace above!
const float __Aalto_MCCsubset_dirs_deg[37][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for the multi-channel anechoic chamber (MCC) ...
const float __Aalto_Apaja_dirs_deg[29][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for the audio-visual listening room (Apaja),...
const float __SphCovering_9_dirs_deg[9][2]
Directions [azimuth, Elevation] in degrees, for sphere covering: 9 dirs.
const float __SphCovering_64_dirs_deg[64][2]
Directions [azimuth, Elevation] in degrees, for sphere covering: 64 dirs.
const float __Tdesign_degree_4_dirs_deg[12][2]
Directions [azimuth, Elevation] in degrees, for minimum Tdesign degree: 4.
const float __Aalto_LR_dirs_deg[13][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for the ITU standard listening room (LR),...
const float __DTU_AVIL_dirs_deg[64][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for the Audio Visual Immersion Lab (AVIL),...
const float __8pX_dirs_deg[8][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 8.x setup.
const float __Tdesign_degree_6_dirs_deg[24][2]
Directions [azimuth, Elevation] in degrees, for minimum Tdesign degree: 6.
const float __13pX_dirs_deg[13][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 13.x setup.
const float __7pX_dirs_deg[7][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 7.x setup.
const float __22pX_dirs_deg[22][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 22.x setup.
const float __SphCovering_25_dirs_deg[25][2]
Directions [azimuth, Elevation] in degrees, for sphere covering: 25 dirs.
const float __Tdesign_degree_10_dirs_deg[60][2]
Directions [azimuth, Elevation] in degrees, for minimum Tdesign degree: 10.
const float __10pX_dirs_deg[10][2]
Loudspeaker directions [azimuth, Elevation] in degrees, for a 10.x setup.
Contains variables for sofa file loading, HRTF interpolation, and the loudspeaker decoders.
float * itds_s
interaural-time differences for each HRIR (in seconds); N_hrirs x 1
int * hrtf_vbap_gtableIdx
N_hrtf_vbap_gtable x 3.
int hrtf_vbapTableRes[2]
[azi elev] step sizes in degrees
float * hrtf_fb_mag
magnitudes of the HRTF filterbank coefficients; nBands x nCH x N_hrirs
int N_hrir_dirs
number of HRIR directions in the current sofa file
float * hrtf_vbap_gtableComp
N_hrtf_vbap_gtable x 3.
Main structure for ambi_dec.
CODEC_STATUS codecStatus
see CODEC_STATUS
float freqVector[HYBRID_BANDS]
frequency vector for time-frequency transform, in Hz
ambi_dec_codecPars * pars
codec parameters