Skip height-related ambisonic channels for 2D rendering
[openal-soft.git] / Alc / bformatdec.c
blob3a07ac36be88eb471b60a0ea8c46ac658088ca36
2 #include "config.h"
4 #include "bformatdec.h"
5 #include "ambdec.h"
6 #include "alu.h"
8 #include "threads.h"
11 typedef struct BandSplitter {
12 ALfloat coeff;
13 ALfloat lp_z1;
14 ALfloat lp_z2;
15 ALfloat hp_z1;
16 } BandSplitter;
18 static void bandsplit_init(BandSplitter *splitter, ALfloat freq_mult)
20 ALfloat w = freq_mult * F_TAU;
21 ALfloat cw = cosf(w);
22 if(cw > FLT_EPSILON)
23 splitter->coeff = (sinf(w) - 1.0f) / cw;
24 else
25 splitter->coeff = cw * -0.5f;
27 splitter->lp_z1 = 0.0f;
28 splitter->lp_z2 = 0.0f;
29 splitter->hp_z1 = 0.0f;
32 static void bandsplit_process(BandSplitter *splitter, ALfloat *restrict hpout, ALfloat *restrict lpout,
33 const ALfloat *input, ALuint count)
35 ALfloat coeff, d, x;
36 ALuint i;
38 coeff = splitter->coeff*0.5f + 0.5f;
39 for(i = 0;i < count;i++)
41 x = input[i];
43 d = (x - splitter->lp_z1) * coeff;
44 x = splitter->lp_z1 + d;
45 splitter->lp_z1 = x + d;
47 d = (x - splitter->lp_z2) * coeff;
48 x = splitter->lp_z2 + d;
49 splitter->lp_z2 = x + d;
51 lpout[i] = x;
54 coeff = splitter->coeff;
55 for(i = 0;i < count;i++)
57 x = input[i];
59 d = x - coeff*splitter->hp_z1;
60 x = splitter->hp_z1 + coeff*d;
61 splitter->hp_z1 = d;
63 hpout[i] = x - lpout[i];
68 static const ALfloat UnitScale[MAX_AMBI_COEFFS] = {
69 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
70 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
72 static const ALfloat SN3D2N3DScale[MAX_AMBI_COEFFS] = {
73 1.000000000f, /* ACN 0 (W), sqrt(1) */
74 1.732050808f, /* ACN 1 (Y), sqrt(3) */
75 1.732050808f, /* ACN 2 (Z), sqrt(3) */
76 1.732050808f, /* ACN 3 (X), sqrt(3) */
77 2.236067978f, /* ACN 4 (V), sqrt(5) */
78 2.236067978f, /* ACN 5 (T), sqrt(5) */
79 2.236067978f, /* ACN 6 (R), sqrt(5) */
80 2.236067978f, /* ACN 7 (S), sqrt(5) */
81 2.236067978f, /* ACN 8 (U), sqrt(5) */
82 2.645751311f, /* ACN 9 (Q), sqrt(7) */
83 2.645751311f, /* ACN 10 (O), sqrt(7) */
84 2.645751311f, /* ACN 11 (M), sqrt(7) */
85 2.645751311f, /* ACN 12 (K), sqrt(7) */
86 2.645751311f, /* ACN 13 (L), sqrt(7) */
87 2.645751311f, /* ACN 14 (N), sqrt(7) */
88 2.645751311f, /* ACN 15 (P), sqrt(7) */
90 static const ALfloat FuMa2N3DScale[MAX_AMBI_COEFFS] = {
91 1.414213562f, /* ACN 0 (W), sqrt(2) */
92 1.732050808f, /* ACN 1 (Y), sqrt(3) */
93 1.732050808f, /* ACN 2 (Z), sqrt(3) */
94 1.732050808f, /* ACN 3 (X), sqrt(3) */
95 1.936491673f, /* ACN 4 (V), sqrt(15)/2 */
96 1.936491673f, /* ACN 5 (T), sqrt(15)/2 */
97 2.236067978f, /* ACN 6 (R), sqrt(5) */
98 1.936491673f, /* ACN 7 (S), sqrt(15)/2 */
99 1.936491673f, /* ACN 8 (U), sqrt(15)/2 */
100 2.091650066f, /* ACN 9 (Q), sqrt(35/8) */
101 1.972026594f, /* ACN 10 (O), sqrt(35)/3 */
102 2.231093404f, /* ACN 11 (M), sqrt(224/45) */
103 2.645751311f, /* ACN 12 (K), sqrt(7) */
104 2.231093404f, /* ACN 13 (L), sqrt(224/45) */
105 1.972026594f, /* ACN 14 (N), sqrt(35)/3 */
106 2.091650066f, /* ACN 15 (P), sqrt(35/8) */
110 static const ALfloat SquareMatrixHF[4][MAX_AMBI_COEFFS] = {
111 { 0.353553f, 0.204094f, 0.0f, 0.204094f },
112 { 0.353553f, -0.204094f, 0.0f, 0.204094f },
113 { 0.353553f, 0.204094f, 0.0f, -0.204094f },
114 { 0.353553f, -0.204094f, 0.0f, -0.204094f },
116 static ALfloat SquareEncoder[4][MAX_AMBI_COEFFS];
118 static const ALfloat CubeMatrixHF[8][MAX_AMBI_COEFFS] = {
119 { 0.25f, 0.14425f, 0.14425f, 0.14425f },
120 { 0.25f, -0.14425f, 0.14425f, 0.14425f },
121 { 0.25f, 0.14425f, 0.14425f, -0.14425f },
122 { 0.25f, -0.14425f, 0.14425f, -0.14425f },
123 { 0.25f, 0.14425f, -0.14425f, 0.14425f },
124 { 0.25f, -0.14425f, -0.14425f, 0.14425f },
125 { 0.25f, 0.14425f, -0.14425f, -0.14425f },
126 { 0.25f, -0.14425f, -0.14425f, -0.14425f },
128 static ALfloat CubeEncoder[8][MAX_AMBI_COEFFS];
130 static alonce_flag encoder_inited = AL_ONCE_FLAG_INIT;
132 static void init_encoder(void)
134 ALuint i, j;
136 CalcXYZCoeffs(-0.577350269f, 0.577350269f, -0.577350269f, CubeEncoder[0]);
137 CalcXYZCoeffs( 0.577350269f, 0.577350269f, -0.577350269f, CubeEncoder[1]);
138 CalcXYZCoeffs(-0.577350269f, 0.577350269f, 0.577350269f, CubeEncoder[2]);
139 CalcXYZCoeffs( 0.577350269f, 0.577350269f, 0.577350269f, CubeEncoder[3]);
140 CalcXYZCoeffs(-0.577350269f, -0.577350269f, -0.577350269f, CubeEncoder[4]);
141 CalcXYZCoeffs( 0.577350269f, -0.577350269f, -0.577350269f, CubeEncoder[5]);
142 CalcXYZCoeffs(-0.577350269f, -0.577350269f, 0.577350269f, CubeEncoder[6]);
143 CalcXYZCoeffs( 0.577350269f, -0.577350269f, 0.577350269f, CubeEncoder[7]);
145 CalcXYZCoeffs(-0.707106781f, 0.0f, -0.707106781f, SquareEncoder[0]);
146 CalcXYZCoeffs( 0.707106781f, 0.0f, -0.707106781f, SquareEncoder[1]);
147 CalcXYZCoeffs(-0.707106781f, 0.0f, 0.707106781f, SquareEncoder[2]);
148 CalcXYZCoeffs( 0.707106781f, 0.0f, 0.707106781f, SquareEncoder[3]);
150 for(i = 0;i < 4;i++)
152 /* Remove the skipped height-related coefficients for 2D rendering. */
153 SquareEncoder[i][2] = SquareEncoder[i][3];
154 SquareEncoder[i][3] = SquareEncoder[i][4];
155 SquareEncoder[i][4] = SquareEncoder[i][8];
156 SquareEncoder[i][5] = SquareEncoder[i][9];
157 SquareEncoder[i][6] = SquareEncoder[i][15];
158 for(j = 7;j < MAX_AMBI_COEFFS;j++)
159 SquareEncoder[i][j] = 0.0f;
164 /* NOTE: Low-frequency (LF) fields and BandSplitter filters are unused with
165 * single-band decoding
167 typedef struct BFormatDec {
168 alignas(16) ALfloat MatrixHF[MAX_OUTPUT_CHANNELS][MAX_AMBI_COEFFS];
169 alignas(16) ALfloat MatrixLF[MAX_OUTPUT_CHANNELS][MAX_AMBI_COEFFS];
171 BandSplitter XOver[MAX_AMBI_COEFFS];
173 ALfloat (*Samples)[BUFFERSIZE];
174 /* These two alias into Samples */
175 ALfloat (*SamplesHF)[BUFFERSIZE];
176 ALfloat (*SamplesLF)[BUFFERSIZE];
178 struct {
179 const ALfloat (*restrict MatrixHF)[MAX_AMBI_COEFFS];
180 const ALfloat (*restrict Encoder)[MAX_AMBI_COEFFS];
181 ALuint NumChannels;
182 } UpSampler;
184 ALuint NumChannels;
185 ALboolean DualBand;
186 ALboolean Periphonic;
187 } BFormatDec;
189 BFormatDec *bformatdec_alloc()
191 alcall_once(&encoder_inited, init_encoder);
192 return al_calloc(16, sizeof(BFormatDec));
195 void bformatdec_free(BFormatDec *dec)
197 if(dec)
199 al_free(dec->Samples);
200 dec->Samples = NULL;
201 dec->SamplesHF = NULL;
202 dec->SamplesLF = NULL;
204 memset(dec, 0, sizeof(*dec));
205 al_free(dec);
209 int bformatdec_getOrder(const struct BFormatDec *dec)
211 if(dec->Periphonic)
213 if(dec->NumChannels > 9) return 3;
214 if(dec->NumChannels > 4) return 2;
215 if(dec->NumChannels > 1) return 1;
217 else
219 if(dec->NumChannels > 5) return 3;
220 if(dec->NumChannels > 3) return 2;
221 if(dec->NumChannels > 1) return 1;
223 return 0;
226 void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALuint chancount, ALuint srate, const ALuint chanmap[MAX_OUTPUT_CHANNELS])
228 static const ALuint map2DTo3D[7] = {
229 0, 1, 3, 4, 8, 9, 15
231 const ALfloat *coeff_scale = UnitScale;
232 ALfloat ratio;
233 ALuint i;
235 al_free(dec->Samples);
236 dec->Samples = NULL;
237 dec->SamplesHF = NULL;
238 dec->SamplesLF = NULL;
240 dec->NumChannels = chancount;
241 dec->Samples = al_calloc(16, dec->NumChannels * conf->FreqBands *
242 sizeof(dec->Samples[0]));
243 dec->SamplesHF = dec->Samples;
244 dec->SamplesLF = dec->SamplesHF + dec->NumChannels;
246 if(conf->CoeffScale == ADS_SN3D)
247 coeff_scale = SN3D2N3DScale;
248 else if(conf->CoeffScale == ADS_FuMa)
249 coeff_scale = FuMa2N3DScale;
251 if((conf->ChanMask & ~0x831b))
253 dec->UpSampler.MatrixHF = CubeMatrixHF;
254 dec->UpSampler.Encoder = (const ALfloat(*)[MAX_AMBI_COEFFS])CubeEncoder;
255 dec->UpSampler.NumChannels = 8;
256 dec->Periphonic = AL_TRUE;
258 else
260 dec->UpSampler.MatrixHF = SquareMatrixHF;
261 dec->UpSampler.Encoder = (const ALfloat(*)[MAX_AMBI_COEFFS])SquareEncoder;
262 dec->UpSampler.NumChannels = 4;
263 dec->Periphonic = AL_FALSE;
266 if(conf->FreqBands == 1)
268 dec->DualBand = AL_FALSE;
269 ratio = 1.0f;
271 else
273 dec->DualBand = AL_TRUE;
275 ratio = conf->XOverFreq / (ALfloat)srate;
276 for(i = 0;i < MAX_AMBI_COEFFS;i++)
277 bandsplit_init(&dec->XOver[i], ratio);
279 ratio = powf(10.0f, conf->XOverRatio / 40.0f);
280 memset(dec->MatrixLF, 0, sizeof(dec->MatrixLF));
281 for(i = 0;i < conf->NumSpeakers;i++)
283 ALuint chan = chanmap[i];
284 ALuint j, k = 0;
285 ALfloat gain;
287 if(!dec->Periphonic)
289 for(j = 0;j < 7;j++)
291 ALuint l = map2DTo3D[j];
292 if(j == 0) gain = conf->LFOrderGain[0] / ratio;
293 else if(j == 1) gain = conf->LFOrderGain[1] / ratio;
294 else if(j == 3) gain = conf->LFOrderGain[2] / ratio;
295 else if(j == 5) gain = conf->LFOrderGain[3] / ratio;
296 if((conf->ChanMask&(1<<l)))
297 dec->MatrixLF[chan][j] = conf->LFMatrix[i][k++] / coeff_scale[l] * gain;
300 else
302 for(j = 0;j < MAX_AMBI_COEFFS;j++)
304 if(j == 0) gain = conf->LFOrderGain[0] / ratio;
305 else if(j == 1) gain = conf->LFOrderGain[1] / ratio;
306 else if(j == 4) gain = conf->LFOrderGain[2] / ratio;
307 else if(j == 9) gain = conf->LFOrderGain[3] / ratio;
308 if((conf->ChanMask&(1<<j)))
309 dec->MatrixLF[chan][j] = conf->LFMatrix[i][k++] / coeff_scale[j] * gain;
315 memset(dec->MatrixHF, 0, sizeof(dec->MatrixHF));
316 for(i = 0;i < conf->NumSpeakers;i++)
318 ALuint chan = chanmap[i];
319 ALuint j, k = 0;
320 ALfloat gain;
322 if(!dec->Periphonic)
324 for(j = 0;j < 7;j++)
326 ALuint l = map2DTo3D[j];
327 if(j == 0) gain = conf->HFOrderGain[0] * ratio;
328 else if(j == 1) gain = conf->HFOrderGain[1] * ratio;
329 else if(j == 3) gain = conf->HFOrderGain[2] * ratio;
330 else if(j == 5) gain = conf->HFOrderGain[3] * ratio;
331 if((conf->ChanMask&(1<<l)))
332 dec->MatrixHF[chan][j] = conf->HFMatrix[i][k++] / coeff_scale[l] * gain;
335 else
337 for(j = 0;j < MAX_AMBI_COEFFS;j++)
339 if(j == 0) gain = conf->HFOrderGain[0] * ratio;
340 else if(j == 1) gain = conf->HFOrderGain[1] * ratio;
341 else if(j == 4) gain = conf->HFOrderGain[2] * ratio;
342 else if(j == 9) gain = conf->HFOrderGain[3] * ratio;
343 if((conf->ChanMask&(1<<j)))
344 dec->MatrixHF[chan][j] = conf->HFMatrix[i][k++] / coeff_scale[j] * gain;
351 static void apply_row(ALfloat *out, const ALfloat *mtx, ALfloat (*restrict in)[BUFFERSIZE], ALuint inchans, ALuint todo)
353 ALuint c, i;
355 for(c = 0;c < inchans;c++)
357 ALfloat gain = mtx[c];
358 if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
359 continue;
360 for(i = 0;i < todo;i++)
361 out[i] += in[c][i] * gain;
365 void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint OutChannels, ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint SamplesToDo)
367 ALuint chan, i;
369 if(dec->DualBand)
371 for(i = 0;i < dec->NumChannels;i++)
372 bandsplit_process(&dec->XOver[i], dec->SamplesHF[i], dec->SamplesLF[i],
373 InSamples[i], SamplesToDo);
375 for(chan = 0;chan < OutChannels;chan++)
377 apply_row(OutBuffer[chan], dec->MatrixHF[chan], dec->SamplesHF,
378 dec->NumChannels, SamplesToDo);
379 apply_row(OutBuffer[chan], dec->MatrixLF[chan], dec->SamplesLF,
380 dec->NumChannels, SamplesToDo);
383 else
385 for(chan = 0;chan < OutChannels;chan++)
386 apply_row(OutBuffer[chan], dec->MatrixHF[chan], InSamples,
387 dec->NumChannels, SamplesToDo);
392 void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint InChannels, ALuint SamplesToDo)
394 ALuint i, j, k;
396 /* This up-sampler is very simplistic. It essentially decodes the first-
397 * order content to a square channel array (or cube if height is desired),
398 * then encodes those points onto the higher order soundfield.
400 for(k = 0;k < dec->UpSampler.NumChannels;k++)
402 memset(dec->Samples[0], 0, SamplesToDo*sizeof(ALfloat));
403 apply_row(dec->Samples[0], dec->UpSampler.MatrixHF[k], InSamples,
404 InChannels, SamplesToDo);
406 for(j = 0;j < dec->NumChannels;j++)
408 ALfloat gain = dec->UpSampler.Encoder[k][j];
409 if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
410 continue;
411 for(i = 0;i < SamplesToDo;i++)
412 OutBuffer[j][i] += dec->Samples[0][i] * gain;