Avoid duplicating some scale tables
[openal-soft.git] / Alc / bformatdec.c
blob28dbc742f91c6a5d70136d1811802a05f3fb4631
2 #include "config.h"
4 #include "bformatdec.h"
5 #include "ambdec.h"
6 #include "mixer_defs.h"
7 #include "alu.h"
9 #include "bool.h"
10 #include "threads.h"
11 #include "almalloc.h"
14 void bandsplit_init(BandSplitter *splitter, ALfloat f0norm)
16 ALfloat w = f0norm * F_TAU;
17 ALfloat cw = cosf(w);
18 if(cw > FLT_EPSILON)
19 splitter->coeff = (sinf(w) - 1.0f) / cw;
20 else
21 splitter->coeff = cw * -0.5f;
23 splitter->lp_z1 = 0.0f;
24 splitter->lp_z2 = 0.0f;
25 splitter->hp_z1 = 0.0f;
28 void bandsplit_clear(BandSplitter *splitter)
30 splitter->lp_z1 = 0.0f;
31 splitter->lp_z2 = 0.0f;
32 splitter->hp_z1 = 0.0f;
35 void bandsplit_process(BandSplitter *splitter, ALfloat *restrict hpout, ALfloat *restrict lpout,
36 const ALfloat *input, ALsizei count)
38 ALfloat coeff, d, x;
39 ALfloat z1, z2;
40 ALsizei i;
42 coeff = splitter->coeff*0.5f + 0.5f;
43 z1 = splitter->lp_z1;
44 z2 = splitter->lp_z2;
45 for(i = 0;i < count;i++)
47 x = input[i];
49 d = (x - z1) * coeff;
50 x = z1 + d;
51 z1 = x + d;
53 d = (x - z2) * coeff;
54 x = z2 + d;
55 z2 = x + d;
57 lpout[i] = x;
59 splitter->lp_z1 = z1;
60 splitter->lp_z2 = z2;
62 coeff = splitter->coeff;
63 z1 = splitter->hp_z1;
64 for(i = 0;i < count;i++)
66 x = input[i];
68 d = x - coeff*z1;
69 x = z1 + coeff*d;
70 z1 = d;
72 hpout[i] = x - lpout[i];
74 splitter->hp_z1 = z1;
78 void splitterap_init(SplitterAllpass *splitter, ALfloat f0norm)
80 ALfloat w = f0norm * F_TAU;
81 ALfloat cw = cosf(w);
82 if(cw > FLT_EPSILON)
83 splitter->coeff = (sinf(w) - 1.0f) / cw;
84 else
85 splitter->coeff = cw * -0.5f;
87 splitter->z1 = 0.0f;
90 void splitterap_clear(SplitterAllpass *splitter)
92 splitter->z1 = 0.0f;
95 void splitterap_process(SplitterAllpass *splitter, ALfloat *restrict samples, ALsizei count)
97 ALfloat coeff, d, x;
98 ALfloat z1;
99 ALsizei i;
101 coeff = splitter->coeff;
102 z1 = splitter->z1;
103 for(i = 0;i < count;i++)
105 x = samples[i];
107 d = x - coeff*z1;
108 x = z1 + coeff*d;
109 z1 = d;
111 samples[i] = x;
113 splitter->z1 = z1;
117 /* NOTE: These are scale factors as applied to Ambisonics content. Decoder
118 * coefficients should be divided by these values to get proper N3D scalings.
120 const ALfloat N3D2N3DScale[MAX_AMBI_COEFFS] = {
121 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
122 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
124 const ALfloat SN3D2N3DScale[MAX_AMBI_COEFFS] = {
125 1.000000000f, /* ACN 0 (W), sqrt(1) */
126 1.732050808f, /* ACN 1 (Y), sqrt(3) */
127 1.732050808f, /* ACN 2 (Z), sqrt(3) */
128 1.732050808f, /* ACN 3 (X), sqrt(3) */
129 2.236067978f, /* ACN 4 (V), sqrt(5) */
130 2.236067978f, /* ACN 5 (T), sqrt(5) */
131 2.236067978f, /* ACN 6 (R), sqrt(5) */
132 2.236067978f, /* ACN 7 (S), sqrt(5) */
133 2.236067978f, /* ACN 8 (U), sqrt(5) */
134 2.645751311f, /* ACN 9 (Q), sqrt(7) */
135 2.645751311f, /* ACN 10 (O), sqrt(7) */
136 2.645751311f, /* ACN 11 (M), sqrt(7) */
137 2.645751311f, /* ACN 12 (K), sqrt(7) */
138 2.645751311f, /* ACN 13 (L), sqrt(7) */
139 2.645751311f, /* ACN 14 (N), sqrt(7) */
140 2.645751311f, /* ACN 15 (P), sqrt(7) */
142 const ALfloat FuMa2N3DScale[MAX_AMBI_COEFFS] = {
143 1.414213562f, /* ACN 0 (W), sqrt(2) */
144 1.732050808f, /* ACN 1 (Y), sqrt(3) */
145 1.732050808f, /* ACN 2 (Z), sqrt(3) */
146 1.732050808f, /* ACN 3 (X), sqrt(3) */
147 1.936491673f, /* ACN 4 (V), sqrt(15)/2 */
148 1.936491673f, /* ACN 5 (T), sqrt(15)/2 */
149 2.236067978f, /* ACN 6 (R), sqrt(5) */
150 1.936491673f, /* ACN 7 (S), sqrt(15)/2 */
151 1.936491673f, /* ACN 8 (U), sqrt(15)/2 */
152 2.091650066f, /* ACN 9 (Q), sqrt(35/8) */
153 1.972026594f, /* ACN 10 (O), sqrt(35)/3 */
154 2.231093404f, /* ACN 11 (M), sqrt(224/45) */
155 2.645751311f, /* ACN 12 (K), sqrt(7) */
156 2.231093404f, /* ACN 13 (L), sqrt(224/45) */
157 1.972026594f, /* ACN 14 (N), sqrt(35)/3 */
158 2.091650066f, /* ACN 15 (P), sqrt(35/8) */
162 #define HF_BAND 0
163 #define LF_BAND 1
164 #define NUM_BANDS 2
166 /* These points are in AL coordinates! */
167 static const ALfloat Ambi3DPoints[8][3] = {
168 { -0.577350269f, 0.577350269f, -0.577350269f },
169 { 0.577350269f, 0.577350269f, -0.577350269f },
170 { -0.577350269f, 0.577350269f, 0.577350269f },
171 { 0.577350269f, 0.577350269f, 0.577350269f },
172 { -0.577350269f, -0.577350269f, -0.577350269f },
173 { 0.577350269f, -0.577350269f, -0.577350269f },
174 { -0.577350269f, -0.577350269f, 0.577350269f },
175 { 0.577350269f, -0.577350269f, 0.577350269f },
177 static const ALfloat Ambi3DDecoder[8][MAX_AMBI_COEFFS] = {
178 { 0.125f, 0.125f, 0.125f, 0.125f },
179 { 0.125f, -0.125f, 0.125f, 0.125f },
180 { 0.125f, 0.125f, 0.125f, -0.125f },
181 { 0.125f, -0.125f, 0.125f, -0.125f },
182 { 0.125f, 0.125f, -0.125f, 0.125f },
183 { 0.125f, -0.125f, -0.125f, 0.125f },
184 { 0.125f, 0.125f, -0.125f, -0.125f },
185 { 0.125f, -0.125f, -0.125f, -0.125f },
187 static const ALfloat Ambi3DDecoderHFScale[MAX_AMBI_COEFFS] = {
188 2.0f,
189 1.15470054f, 1.15470054f, 1.15470054f
193 /* NOTE: BandSplitter filters are unused with single-band decoding */
194 typedef struct BFormatDec {
195 ALuint Enabled; /* Bitfield of enabled channels. */
197 union {
198 alignas(16) ALfloat Dual[MAX_OUTPUT_CHANNELS][NUM_BANDS][MAX_AMBI_COEFFS];
199 alignas(16) ALfloat Single[MAX_OUTPUT_CHANNELS][MAX_AMBI_COEFFS];
200 } Matrix;
202 BandSplitter XOver[MAX_AMBI_COEFFS];
204 ALfloat (*Samples)[BUFFERSIZE];
205 /* These two alias into Samples */
206 ALfloat (*SamplesHF)[BUFFERSIZE];
207 ALfloat (*SamplesLF)[BUFFERSIZE];
209 alignas(16) ALfloat ChannelMix[BUFFERSIZE];
211 struct {
212 BandSplitter XOver;
213 ALfloat Gains[NUM_BANDS];
214 } UpSampler[4];
216 ALsizei NumChannels;
217 ALboolean DualBand;
218 } BFormatDec;
220 BFormatDec *bformatdec_alloc()
222 return al_calloc(16, sizeof(BFormatDec));
225 void bformatdec_free(BFormatDec **dec)
227 if(dec && *dec)
229 al_free((*dec)->Samples);
230 (*dec)->Samples = NULL;
231 (*dec)->SamplesHF = NULL;
232 (*dec)->SamplesLF = NULL;
234 al_free(*dec);
235 *dec = NULL;
239 void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount, ALuint srate, const ALsizei chanmap[MAX_OUTPUT_CHANNELS])
241 static const ALsizei map2DTo3D[MAX_AMBI2D_COEFFS] = {
242 0, 1, 3, 4, 8, 9, 15
244 const ALfloat *coeff_scale = N3D2N3DScale;
245 bool periphonic;
246 ALfloat ratio;
247 ALsizei i;
249 al_free(dec->Samples);
250 dec->Samples = NULL;
251 dec->SamplesHF = NULL;
252 dec->SamplesLF = NULL;
254 dec->NumChannels = chancount;
255 dec->Samples = al_calloc(16, dec->NumChannels*2 * sizeof(dec->Samples[0]));
256 dec->SamplesHF = dec->Samples;
257 dec->SamplesLF = dec->SamplesHF + dec->NumChannels;
259 dec->Enabled = 0;
260 for(i = 0;i < conf->NumSpeakers;i++)
261 dec->Enabled |= 1 << chanmap[i];
263 if(conf->CoeffScale == ADS_SN3D)
264 coeff_scale = SN3D2N3DScale;
265 else if(conf->CoeffScale == ADS_FuMa)
266 coeff_scale = FuMa2N3DScale;
268 memset(dec->UpSampler, 0, sizeof(dec->UpSampler));
269 ratio = 400.0f / (ALfloat)srate;
270 for(i = 0;i < 4;i++)
271 bandsplit_init(&dec->UpSampler[i].XOver, ratio);
272 if((conf->ChanMask&AMBI_PERIPHONIC_MASK))
274 periphonic = true;
276 dec->UpSampler[0].Gains[HF_BAND] = (conf->ChanMask > 0x1ff) ? W_SCALE_3H3P :
277 (conf->ChanMask > 0xf) ? W_SCALE_2H2P : 1.0f;
278 dec->UpSampler[0].Gains[LF_BAND] = 1.0f;
279 for(i = 1;i < 4;i++)
281 dec->UpSampler[i].Gains[HF_BAND] = (conf->ChanMask > 0x1ff) ? XYZ_SCALE_3H3P :
282 (conf->ChanMask > 0xf) ? XYZ_SCALE_2H2P : 1.0f;
283 dec->UpSampler[i].Gains[LF_BAND] = 1.0f;
286 else
288 periphonic = false;
290 dec->UpSampler[0].Gains[HF_BAND] = (conf->ChanMask > 0x1ff) ? W_SCALE_3H0P :
291 (conf->ChanMask > 0xf) ? W_SCALE_2H0P : 1.0f;
292 dec->UpSampler[0].Gains[LF_BAND] = 1.0f;
293 for(i = 1;i < 3;i++)
295 dec->UpSampler[i].Gains[HF_BAND] = (conf->ChanMask > 0x1ff) ? XYZ_SCALE_3H0P :
296 (conf->ChanMask > 0xf) ? XYZ_SCALE_2H0P : 1.0f;
297 dec->UpSampler[i].Gains[LF_BAND] = 1.0f;
299 dec->UpSampler[3].Gains[HF_BAND] = 0.0f;
300 dec->UpSampler[3].Gains[LF_BAND] = 0.0f;
303 memset(&dec->Matrix, 0, sizeof(dec->Matrix));
304 if(conf->FreqBands == 1)
306 dec->DualBand = AL_FALSE;
307 for(i = 0;i < conf->NumSpeakers;i++)
309 ALsizei chan = chanmap[i];
310 ALfloat gain;
311 ALsizei j, k;
313 if(!periphonic)
315 for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++)
317 ALsizei l = map2DTo3D[j];
318 if(j == 0) gain = conf->HFOrderGain[0];
319 else if(j == 1) gain = conf->HFOrderGain[1];
320 else if(j == 3) gain = conf->HFOrderGain[2];
321 else if(j == 5) gain = conf->HFOrderGain[3];
322 if((conf->ChanMask&(1<<l)))
323 dec->Matrix.Single[chan][j] = conf->HFMatrix[i][k++] / coeff_scale[l] *
324 gain;
327 else
329 for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
331 if(j == 0) gain = conf->HFOrderGain[0];
332 else if(j == 1) gain = conf->HFOrderGain[1];
333 else if(j == 4) gain = conf->HFOrderGain[2];
334 else if(j == 9) gain = conf->HFOrderGain[3];
335 if((conf->ChanMask&(1<<j)))
336 dec->Matrix.Single[chan][j] = conf->HFMatrix[i][k++] / coeff_scale[j] *
337 gain;
342 else
344 dec->DualBand = AL_TRUE;
346 ratio = conf->XOverFreq / (ALfloat)srate;
347 for(i = 0;i < MAX_AMBI_COEFFS;i++)
348 bandsplit_init(&dec->XOver[i], ratio);
350 ratio = powf(10.0f, conf->XOverRatio / 40.0f);
351 for(i = 0;i < conf->NumSpeakers;i++)
353 ALsizei chan = chanmap[i];
354 ALfloat gain;
355 ALsizei j, k;
357 if(!periphonic)
359 for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++)
361 ALsizei l = map2DTo3D[j];
362 if(j == 0) gain = conf->HFOrderGain[0] * ratio;
363 else if(j == 1) gain = conf->HFOrderGain[1] * ratio;
364 else if(j == 3) gain = conf->HFOrderGain[2] * ratio;
365 else if(j == 5) gain = conf->HFOrderGain[3] * ratio;
366 if((conf->ChanMask&(1<<l)))
367 dec->Matrix.Dual[chan][HF_BAND][j] = conf->HFMatrix[i][k++] /
368 coeff_scale[l] * gain;
370 for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++)
372 ALsizei l = map2DTo3D[j];
373 if(j == 0) gain = conf->LFOrderGain[0] / ratio;
374 else if(j == 1) gain = conf->LFOrderGain[1] / ratio;
375 else if(j == 3) gain = conf->LFOrderGain[2] / ratio;
376 else if(j == 5) gain = conf->LFOrderGain[3] / ratio;
377 if((conf->ChanMask&(1<<l)))
378 dec->Matrix.Dual[chan][LF_BAND][j] = conf->LFMatrix[i][k++] /
379 coeff_scale[l] * gain;
382 else
384 for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
386 if(j == 0) gain = conf->HFOrderGain[0] * ratio;
387 else if(j == 1) gain = conf->HFOrderGain[1] * ratio;
388 else if(j == 4) gain = conf->HFOrderGain[2] * ratio;
389 else if(j == 9) gain = conf->HFOrderGain[3] * ratio;
390 if((conf->ChanMask&(1<<j)))
391 dec->Matrix.Dual[chan][HF_BAND][j] = conf->HFMatrix[i][k++] /
392 coeff_scale[j] * gain;
394 for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
396 if(j == 0) gain = conf->LFOrderGain[0] / ratio;
397 else if(j == 1) gain = conf->LFOrderGain[1] / ratio;
398 else if(j == 4) gain = conf->LFOrderGain[2] / ratio;
399 else if(j == 9) gain = conf->LFOrderGain[3] / ratio;
400 if((conf->ChanMask&(1<<j)))
401 dec->Matrix.Dual[chan][LF_BAND][j] = conf->LFMatrix[i][k++] /
402 coeff_scale[j] * gain;
410 void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALsizei OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei SamplesToDo)
412 ALsizei chan, i;
414 OutBuffer = ASSUME_ALIGNED(OutBuffer, 16);
415 if(dec->DualBand)
417 for(i = 0;i < dec->NumChannels;i++)
418 bandsplit_process(&dec->XOver[i], dec->SamplesHF[i], dec->SamplesLF[i],
419 InSamples[i], SamplesToDo);
421 for(chan = 0;chan < OutChannels;chan++)
423 if(!(dec->Enabled&(1<<chan)))
424 continue;
426 memset(dec->ChannelMix, 0, SamplesToDo*sizeof(ALfloat));
427 MixRowSamples(dec->ChannelMix, dec->Matrix.Dual[chan][HF_BAND],
428 dec->SamplesHF, dec->NumChannels, 0, SamplesToDo
430 MixRowSamples(dec->ChannelMix, dec->Matrix.Dual[chan][LF_BAND],
431 dec->SamplesLF, dec->NumChannels, 0, SamplesToDo
434 for(i = 0;i < SamplesToDo;i++)
435 OutBuffer[chan][i] += dec->ChannelMix[i];
438 else
440 for(chan = 0;chan < OutChannels;chan++)
442 if(!(dec->Enabled&(1<<chan)))
443 continue;
445 memset(dec->ChannelMix, 0, SamplesToDo*sizeof(ALfloat));
446 MixRowSamples(dec->ChannelMix, dec->Matrix.Single[chan], InSamples,
447 dec->NumChannels, 0, SamplesToDo);
449 for(i = 0;i < SamplesToDo;i++)
450 OutBuffer[chan][i] += dec->ChannelMix[i];
456 void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei InChannels, ALsizei SamplesToDo)
458 ALsizei i;
460 /* This up-sampler leverages the differences observed in dual-band second-
461 * and third-order decoder matrices compared to first-order. For the same
462 * output channel configuration, the low-frequency matrix has identical
463 * coefficients in the shared input channels, while the high-frequency
464 * matrix has extra scalars applied to the W channel and X/Y/Z channels.
465 * Mixing the first-order content into the higher-order stream with the
466 * appropriate counter-scales applied to the HF response results in the
467 * subsequent higher-order decode generating the same response as a first-
468 * order decode.
470 for(i = 0;i < InChannels;i++)
472 /* First, split the first-order components into low and high frequency
473 * bands.
475 bandsplit_process(&dec->UpSampler[i].XOver,
476 dec->Samples[HF_BAND], dec->Samples[LF_BAND],
477 InSamples[i], SamplesToDo
480 /* Now write each band to the output. */
481 MixRowSamples(OutBuffer[i], dec->UpSampler[i].Gains,
482 dec->Samples, NUM_BANDS, 0, SamplesToDo
488 #define INVALID_UPSAMPLE_INDEX INT_MAX
490 static ALsizei GetACNIndex(const BFChannelConfig *chans, ALsizei numchans, ALsizei acn)
492 ALsizei i;
493 for(i = 0;i < numchans;i++)
495 if(chans[i].Index == acn)
496 return i;
498 return INVALID_UPSAMPLE_INDEX;
500 #define GetChannelForACN(b, a) GetACNIndex((b).Ambi.Map, (b).NumChannels, (a))
502 typedef struct AmbiUpsampler {
503 alignas(16) ALfloat Samples[NUM_BANDS][BUFFERSIZE];
505 BandSplitter XOver[4];
507 ALfloat Gains[4][MAX_OUTPUT_CHANNELS][NUM_BANDS];
508 } AmbiUpsampler;
510 AmbiUpsampler *ambiup_alloc()
512 return al_calloc(16, sizeof(AmbiUpsampler));
515 void ambiup_free(struct AmbiUpsampler **ambiup)
517 if(ambiup)
519 al_free(*ambiup);
520 *ambiup = NULL;
524 void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device, ALfloat w_scale, ALfloat xyz_scale)
526 ALfloat ratio;
527 ALsizei i;
529 ratio = 400.0f / (ALfloat)device->Frequency;
530 for(i = 0;i < 4;i++)
531 bandsplit_init(&ambiup->XOver[i], ratio);
533 memset(ambiup->Gains, 0, sizeof(ambiup->Gains));
534 if(device->Dry.CoeffCount > 0)
536 ALfloat encgains[8][MAX_OUTPUT_CHANNELS];
537 ALsizei j;
538 size_t k;
540 for(k = 0;k < COUNTOF(Ambi3DPoints);k++)
542 ALfloat coeffs[MAX_AMBI_COEFFS] = { 0.0f };
543 CalcDirectionCoeffs(Ambi3DPoints[k], 0.0f, coeffs);
544 ComputeDryPanGains(&device->Dry, coeffs, 1.0f, encgains[k]);
547 /* Combine the matrices that do the in->virt and virt->out conversions
548 * so we get a single in->out conversion. NOTE: the Encoder matrix
549 * (encgains) and output are transposed, so the input channels line up
550 * with the rows and the output channels line up with the columns.
552 for(i = 0;i < 4;i++)
554 for(j = 0;j < device->Dry.NumChannels;j++)
556 ALfloat gain=0.0f;
557 for(k = 0;k < COUNTOF(Ambi3DDecoder);k++)
558 gain += Ambi3DDecoder[k][i] * encgains[k][j];
559 ambiup->Gains[i][j][HF_BAND] = gain * Ambi3DDecoderHFScale[i];
560 ambiup->Gains[i][j][LF_BAND] = gain;
564 else
566 for(i = 0;i < 4;i++)
568 ALsizei index = GetChannelForACN(device->Dry, i);
569 if(index != INVALID_UPSAMPLE_INDEX)
571 ALfloat scale = device->Dry.Ambi.Map[index].Scale;
572 ambiup->Gains[i][index][HF_BAND] = scale * ((i==0) ? w_scale : xyz_scale);
573 ambiup->Gains[i][index][LF_BAND] = scale;
579 void ambiup_process(struct AmbiUpsampler *ambiup, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALsizei OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei SamplesToDo)
581 ALsizei i, j;
583 for(i = 0;i < 4;i++)
585 bandsplit_process(&ambiup->XOver[i],
586 ambiup->Samples[HF_BAND], ambiup->Samples[LF_BAND],
587 InSamples[i], SamplesToDo
590 for(j = 0;j < OutChannels;j++)
591 MixRowSamples(OutBuffer[j], ambiup->Gains[i][j],
592 ambiup->Samples, NUM_BANDS, 0, SamplesToDo