Use separate macros for atomics that don't take a memory order
[openal-soft.git] / Alc / bformatdec.c
blob5556c2ef96f276e2388a499a3c1f03204cc14991
2 #include "config.h"
4 #include "bformatdec.h"
5 #include "ambdec.h"
6 #include "mixer_defs.h"
7 #include "alu.h"
9 #include "threads.h"
10 #include "almalloc.h"
13 void bandsplit_init(BandSplitter *splitter, ALfloat freq_mult)
15 ALfloat w = freq_mult * F_TAU;
16 ALfloat cw = cosf(w);
17 if(cw > FLT_EPSILON)
18 splitter->coeff = (sinf(w) - 1.0f) / cw;
19 else
20 splitter->coeff = cw * -0.5f;
22 splitter->lp_z1 = 0.0f;
23 splitter->lp_z2 = 0.0f;
24 splitter->hp_z1 = 0.0f;
27 void bandsplit_clear(BandSplitter *splitter)
29 splitter->lp_z1 = 0.0f;
30 splitter->lp_z2 = 0.0f;
31 splitter->hp_z1 = 0.0f;
34 void bandsplit_process(BandSplitter *splitter, ALfloat *restrict hpout, ALfloat *restrict lpout,
35 const ALfloat *input, ALuint count)
37 ALfloat coeff, d, x;
38 ALfloat z1, z2;
39 ALuint i;
41 coeff = splitter->coeff*0.5f + 0.5f;
42 z1 = splitter->lp_z1;
43 z2 = splitter->lp_z2;
44 for(i = 0;i < count;i++)
46 x = input[i];
48 d = (x - z1) * coeff;
49 x = z1 + d;
50 z1 = x + d;
52 d = (x - z2) * coeff;
53 x = z2 + d;
54 z2 = x + d;
56 lpout[i] = x;
58 splitter->lp_z1 = z1;
59 splitter->lp_z2 = z2;
61 coeff = splitter->coeff;
62 z1 = splitter->hp_z1;
63 for(i = 0;i < count;i++)
65 x = input[i];
67 d = x - coeff*z1;
68 x = z1 + coeff*d;
69 z1 = d;
71 hpout[i] = x - lpout[i];
73 splitter->hp_z1 = z1;
77 static const ALfloat UnitScale[MAX_AMBI_COEFFS] = {
78 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
79 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
81 static const ALfloat SN3D2N3DScale[MAX_AMBI_COEFFS] = {
82 1.000000000f, /* ACN 0 (W), sqrt(1) */
83 1.732050808f, /* ACN 1 (Y), sqrt(3) */
84 1.732050808f, /* ACN 2 (Z), sqrt(3) */
85 1.732050808f, /* ACN 3 (X), sqrt(3) */
86 2.236067978f, /* ACN 4 (V), sqrt(5) */
87 2.236067978f, /* ACN 5 (T), sqrt(5) */
88 2.236067978f, /* ACN 6 (R), sqrt(5) */
89 2.236067978f, /* ACN 7 (S), sqrt(5) */
90 2.236067978f, /* ACN 8 (U), sqrt(5) */
91 2.645751311f, /* ACN 9 (Q), sqrt(7) */
92 2.645751311f, /* ACN 10 (O), sqrt(7) */
93 2.645751311f, /* ACN 11 (M), sqrt(7) */
94 2.645751311f, /* ACN 12 (K), sqrt(7) */
95 2.645751311f, /* ACN 13 (L), sqrt(7) */
96 2.645751311f, /* ACN 14 (N), sqrt(7) */
97 2.645751311f, /* ACN 15 (P), sqrt(7) */
99 static const ALfloat FuMa2N3DScale[MAX_AMBI_COEFFS] = {
100 1.414213562f, /* ACN 0 (W), sqrt(2) */
101 1.732050808f, /* ACN 1 (Y), sqrt(3) */
102 1.732050808f, /* ACN 2 (Z), sqrt(3) */
103 1.732050808f, /* ACN 3 (X), sqrt(3) */
104 1.936491673f, /* ACN 4 (V), sqrt(15)/2 */
105 1.936491673f, /* ACN 5 (T), sqrt(15)/2 */
106 2.236067978f, /* ACN 6 (R), sqrt(5) */
107 1.936491673f, /* ACN 7 (S), sqrt(15)/2 */
108 1.936491673f, /* ACN 8 (U), sqrt(15)/2 */
109 2.091650066f, /* ACN 9 (Q), sqrt(35/8) */
110 1.972026594f, /* ACN 10 (O), sqrt(35)/3 */
111 2.231093404f, /* ACN 11 (M), sqrt(224/45) */
112 2.645751311f, /* ACN 12 (K), sqrt(7) */
113 2.231093404f, /* ACN 13 (L), sqrt(224/45) */
114 1.972026594f, /* ACN 14 (N), sqrt(35)/3 */
115 2.091650066f, /* ACN 15 (P), sqrt(35/8) */
119 enum FreqBand {
120 FB_HighFreq,
121 FB_LowFreq,
122 FB_Max
125 /* These points are in AL coordinates! */
126 static const ALfloat Ambi2DPoints[4][3] = {
127 { -0.707106781f, 0.0f, -0.707106781f },
128 { 0.707106781f, 0.0f, -0.707106781f },
129 { -0.707106781f, 0.0f, 0.707106781f },
130 { 0.707106781f, 0.0f, 0.707106781f },
132 static const ALfloat Ambi2DDecoder[4][FB_Max][MAX_AMBI_COEFFS] = {
133 { { 0.353553f, 0.204094f, 0.0f, 0.204094f }, { 0.25f, 0.204094f, 0.0f, 0.204094f } },
134 { { 0.353553f, -0.204094f, 0.0f, 0.204094f }, { 0.25f, -0.204094f, 0.0f, 0.204094f } },
135 { { 0.353553f, 0.204094f, 0.0f, -0.204094f }, { 0.25f, 0.204094f, 0.0f, -0.204094f } },
136 { { 0.353553f, -0.204094f, 0.0f, -0.204094f }, { 0.25f, -0.204094f, 0.0f, -0.204094f } },
138 static ALfloat Ambi2DEncoderT[4][MAX_AMBI_COEFFS];
140 /* These points are in AL coordinates! */
141 static const ALfloat Ambi3DPoints[8][3] = {
142 { -0.577350269f, 0.577350269f, -0.577350269f },
143 { 0.577350269f, 0.577350269f, -0.577350269f },
144 { -0.577350269f, 0.577350269f, 0.577350269f },
145 { 0.577350269f, 0.577350269f, 0.577350269f },
146 { -0.577350269f, -0.577350269f, -0.577350269f },
147 { 0.577350269f, -0.577350269f, -0.577350269f },
148 { -0.577350269f, -0.577350269f, 0.577350269f },
149 { 0.577350269f, -0.577350269f, 0.577350269f },
151 static const ALfloat Ambi3DDecoder[8][FB_Max][MAX_AMBI_COEFFS] = {
152 { { 0.25f, 0.1443375672f, 0.1443375672f, 0.1443375672f }, { 0.125f, 0.125f, 0.125f, 0.125f } },
153 { { 0.25f, -0.1443375672f, 0.1443375672f, 0.1443375672f }, { 0.125f, -0.125f, 0.125f, 0.125f } },
154 { { 0.25f, 0.1443375672f, 0.1443375672f, -0.1443375672f }, { 0.125f, 0.125f, 0.125f, -0.125f } },
155 { { 0.25f, -0.1443375672f, 0.1443375672f, -0.1443375672f }, { 0.125f, -0.125f, 0.125f, -0.125f } },
156 { { 0.25f, 0.1443375672f, -0.1443375672f, 0.1443375672f }, { 0.125f, 0.125f, -0.125f, 0.125f } },
157 { { 0.25f, -0.1443375672f, -0.1443375672f, 0.1443375672f }, { 0.125f, -0.125f, -0.125f, 0.125f } },
158 { { 0.25f, 0.1443375672f, -0.1443375672f, -0.1443375672f }, { 0.125f, 0.125f, -0.125f, -0.125f } },
159 { { 0.25f, -0.1443375672f, -0.1443375672f, -0.1443375672f }, { 0.125f, -0.125f, -0.125f, -0.125f } },
161 static ALfloat Ambi3DEncoderT[8][MAX_AMBI_COEFFS];
164 static RowMixerFunc MixMatrixRow = MixRow_C;
167 static alonce_flag bformatdec_inited = AL_ONCE_FLAG_INIT;
169 static void init_bformatdec(void)
171 ALuint i, j;
173 MixMatrixRow = SelectRowMixer();
175 for(i = 0;i < COUNTOF(Ambi3DPoints);i++)
176 CalcDirectionCoeffs(Ambi3DPoints[i], 0.0f, Ambi3DEncoderT[i]);
178 for(i = 0;i < COUNTOF(Ambi2DPoints);i++)
180 CalcDirectionCoeffs(Ambi2DPoints[i], 0.0f, Ambi2DEncoderT[i]);
182 /* Remove the skipped height-related coefficients for 2D rendering. */
183 Ambi2DEncoderT[i][2] = Ambi2DEncoderT[i][3];
184 Ambi2DEncoderT[i][3] = Ambi2DEncoderT[i][4];
185 Ambi2DEncoderT[i][4] = Ambi2DEncoderT[i][8];
186 Ambi2DEncoderT[i][5] = Ambi2DEncoderT[i][9];
187 Ambi2DEncoderT[i][6] = Ambi2DEncoderT[i][15];
188 for(j = 7;j < MAX_AMBI_COEFFS;j++)
189 Ambi2DEncoderT[i][j] = 0.0f;
194 /* This typedef is needed for SAFE_CONST to work. */
195 typedef ALfloat ALfloatMAX_AMBI_COEFFS[MAX_AMBI_COEFFS];
197 static void GenUpsamplerGains(const ALfloat (*restrict EncoderT)[MAX_AMBI_COEFFS],
198 const ALfloat (*restrict Decoder)[FB_Max][MAX_AMBI_COEFFS],
199 ALsizei InChannels,
200 ALfloat (*restrict OutGains)[MAX_OUTPUT_CHANNELS][FB_Max],
201 ALsizei OutChannels)
203 ALsizei i, j, k;
205 /* Combine the matrices that do the in->virt and virt->out conversions so
206 * we get a single in->out conversion. NOTE: the Encoder matrix and output
207 * are transposed, so the input channels line up with the rows and the
208 * output channels line up with the columns.
210 for(i = 0;i < 4;i++)
212 for(j = 0;j < OutChannels;j++)
214 ALfloat hfgain=0.0f, lfgain=0.0f;
215 for(k = 0;k < InChannels;k++)
217 hfgain += Decoder[k][FB_HighFreq][i]*EncoderT[k][j];
218 lfgain += Decoder[k][FB_LowFreq][i]*EncoderT[k][j];
220 OutGains[i][j][FB_HighFreq] = hfgain;
221 OutGains[i][j][FB_LowFreq] = lfgain;
227 #define MAX_DELAY_LENGTH 128
229 /* NOTE: BandSplitter filters are unused with single-band decoding */
230 typedef struct BFormatDec {
231 ALboolean Enabled[MAX_OUTPUT_CHANNELS];
233 union {
234 alignas(16) ALfloat Dual[MAX_OUTPUT_CHANNELS][FB_Max][MAX_AMBI_COEFFS];
235 alignas(16) ALfloat Single[MAX_OUTPUT_CHANNELS][MAX_AMBI_COEFFS];
236 } Matrix;
238 BandSplitter XOver[MAX_AMBI_COEFFS];
240 ALfloat (*Samples)[BUFFERSIZE];
241 /* These two alias into Samples */
242 ALfloat (*SamplesHF)[BUFFERSIZE];
243 ALfloat (*SamplesLF)[BUFFERSIZE];
245 alignas(16) ALfloat ChannelMix[BUFFERSIZE];
247 struct {
248 alignas(16) ALfloat Buffer[MAX_DELAY_LENGTH];
249 ALuint Length; /* Valid range is [0...MAX_DELAY_LENGTH). */
250 } Delay[MAX_OUTPUT_CHANNELS];
252 struct {
253 BandSplitter XOver[4];
255 ALfloat Gains[4][MAX_OUTPUT_CHANNELS][FB_Max];
256 } UpSampler;
258 ALuint NumChannels;
259 ALboolean DualBand;
260 ALboolean Periphonic;
261 } BFormatDec;
263 BFormatDec *bformatdec_alloc()
265 alcall_once(&bformatdec_inited, init_bformatdec);
266 return al_calloc(16, sizeof(BFormatDec));
269 void bformatdec_free(BFormatDec *dec)
271 if(dec)
273 al_free(dec->Samples);
274 dec->Samples = NULL;
275 dec->SamplesHF = NULL;
276 dec->SamplesLF = NULL;
278 memset(dec, 0, sizeof(*dec));
279 al_free(dec);
283 int bformatdec_getOrder(const struct BFormatDec *dec)
285 if(dec->Periphonic)
287 if(dec->NumChannels > 9) return 3;
288 if(dec->NumChannels > 4) return 2;
289 if(dec->NumChannels > 1) return 1;
291 else
293 if(dec->NumChannels > 5) return 3;
294 if(dec->NumChannels > 3) return 2;
295 if(dec->NumChannels > 1) return 1;
297 return 0;
300 void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALuint chancount, ALuint srate, const ALuint chanmap[MAX_OUTPUT_CHANNELS], int flags)
302 static const ALuint map2DTo3D[MAX_AMBI2D_COEFFS] = {
303 0, 1, 3, 4, 8, 9, 15
305 const ALfloat *coeff_scale = UnitScale;
306 ALfloat distgain[MAX_OUTPUT_CHANNELS];
307 ALfloat maxdist, ratio;
308 ALuint i;
310 al_free(dec->Samples);
311 dec->Samples = NULL;
312 dec->SamplesHF = NULL;
313 dec->SamplesLF = NULL;
315 dec->NumChannels = chancount;
316 dec->Samples = al_calloc(16, dec->NumChannels*2 * sizeof(dec->Samples[0]));
317 dec->SamplesHF = dec->Samples;
318 dec->SamplesLF = dec->SamplesHF + dec->NumChannels;
320 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
321 dec->Enabled[i] = AL_FALSE;
322 for(i = 0;i < conf->NumSpeakers;i++)
323 dec->Enabled[chanmap[i]] = AL_TRUE;
325 if(conf->CoeffScale == ADS_SN3D)
326 coeff_scale = SN3D2N3DScale;
327 else if(conf->CoeffScale == ADS_FuMa)
328 coeff_scale = FuMa2N3DScale;
330 ratio = 400.0f / (ALfloat)srate;
331 for(i = 0;i < 4;i++)
332 bandsplit_init(&dec->UpSampler.XOver[i], ratio);
333 memset(dec->UpSampler.Gains, 0, sizeof(dec->UpSampler.Gains));
334 if((conf->ChanMask&AMBI_PERIPHONIC_MASK))
336 GenUpsamplerGains(SAFE_CONST(ALfloatMAX_AMBI_COEFFS*,Ambi3DEncoderT),
337 Ambi3DDecoder, COUNTOF(Ambi3DDecoder),
338 dec->UpSampler.Gains, dec->NumChannels);
339 dec->Periphonic = AL_TRUE;
341 else
343 GenUpsamplerGains(SAFE_CONST(ALfloatMAX_AMBI_COEFFS*,Ambi2DEncoderT),
344 Ambi2DDecoder, COUNTOF(Ambi2DDecoder),
345 dec->UpSampler.Gains, dec->NumChannels);
346 dec->Periphonic = AL_FALSE;
349 maxdist = 0.0f;
350 for(i = 0;i < conf->NumSpeakers;i++)
352 maxdist = maxf(maxdist, conf->Speakers[i].Distance);
353 distgain[i] = 1.0f;
356 memset(dec->Delay, 0, sizeof(dec->Delay));
357 if((flags&BFDF_DistanceComp) && maxdist > 0.0f)
359 for(i = 0;i < conf->NumSpeakers;i++)
361 ALuint chan = chanmap[i];
362 ALfloat delay;
364 /* Distance compensation only delays in steps of the sample rate.
365 * This is a bit less accurate since the delay time falls to the
366 * nearest sample time, but it's far simpler as it doesn't have to
367 * deal with phase offsets. This means at 48khz, for instance, the
368 * distance delay will be in steps of about 7 millimeters.
370 delay = floorf((maxdist-conf->Speakers[i].Distance) / SPEEDOFSOUNDMETRESPERSEC *
371 (ALfloat)srate + 0.5f);
372 if(delay >= (ALfloat)MAX_DELAY_LENGTH)
373 ERR("Delay for speaker \"%s\" exceeds buffer length (%f >= %u)\n",
374 al_string_get_cstr(conf->Speakers[i].Name), delay, MAX_DELAY_LENGTH);
376 dec->Delay[chan].Length = (ALuint)clampf(delay, 0.0f, (ALfloat)(MAX_DELAY_LENGTH-1));
377 distgain[i] = conf->Speakers[i].Distance / maxdist;
378 TRACE("Channel %u \"%s\" distance compensation: %u samples, %f gain\n", chan,
379 al_string_get_cstr(conf->Speakers[i].Name), dec->Delay[chan].Length, distgain[i]
384 memset(&dec->Matrix, 0, sizeof(dec->Matrix));
385 if(conf->FreqBands == 1)
387 dec->DualBand = AL_FALSE;
388 for(i = 0;i < conf->NumSpeakers;i++)
390 ALuint chan = chanmap[i];
391 ALfloat gain;
392 ALuint j, k;
394 if(!dec->Periphonic)
396 for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++)
398 ALuint l = map2DTo3D[j];
399 if(j == 0) gain = conf->HFOrderGain[0];
400 else if(j == 1) gain = conf->HFOrderGain[1];
401 else if(j == 3) gain = conf->HFOrderGain[2];
402 else if(j == 5) gain = conf->HFOrderGain[3];
403 if((conf->ChanMask&(1<<l)))
404 dec->Matrix.Single[chan][j] = conf->HFMatrix[i][k++] / coeff_scale[l] *
405 gain * distgain[i];
408 else
410 for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
412 if(j == 0) gain = conf->HFOrderGain[0];
413 else if(j == 1) gain = conf->HFOrderGain[1];
414 else if(j == 4) gain = conf->HFOrderGain[2];
415 else if(j == 9) gain = conf->HFOrderGain[3];
416 if((conf->ChanMask&(1<<j)))
417 dec->Matrix.Single[chan][j] = conf->HFMatrix[i][k++] / coeff_scale[j] *
418 gain * distgain[i];
423 else
425 dec->DualBand = AL_TRUE;
427 ratio = conf->XOverFreq / (ALfloat)srate;
428 for(i = 0;i < MAX_AMBI_COEFFS;i++)
429 bandsplit_init(&dec->XOver[i], ratio);
431 ratio = powf(10.0f, conf->XOverRatio / 40.0f);
432 for(i = 0;i < conf->NumSpeakers;i++)
434 ALuint chan = chanmap[i];
435 ALfloat gain;
436 ALuint j, k;
438 if(!dec->Periphonic)
440 for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++)
442 ALuint l = map2DTo3D[j];
443 if(j == 0) gain = conf->HFOrderGain[0] * ratio;
444 else if(j == 1) gain = conf->HFOrderGain[1] * ratio;
445 else if(j == 3) gain = conf->HFOrderGain[2] * ratio;
446 else if(j == 5) gain = conf->HFOrderGain[3] * ratio;
447 if((conf->ChanMask&(1<<l)))
448 dec->Matrix.Dual[chan][FB_HighFreq][j] = conf->HFMatrix[i][k++] /
449 coeff_scale[l] * gain *
450 distgain[i];
452 for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++)
454 ALuint l = map2DTo3D[j];
455 if(j == 0) gain = conf->LFOrderGain[0] / ratio;
456 else if(j == 1) gain = conf->LFOrderGain[1] / ratio;
457 else if(j == 3) gain = conf->LFOrderGain[2] / ratio;
458 else if(j == 5) gain = conf->LFOrderGain[3] / ratio;
459 if((conf->ChanMask&(1<<l)))
460 dec->Matrix.Dual[chan][FB_LowFreq][j] = conf->LFMatrix[i][k++] /
461 coeff_scale[l] * gain *
462 distgain[i];
465 else
467 for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
469 if(j == 0) gain = conf->HFOrderGain[0] * ratio;
470 else if(j == 1) gain = conf->HFOrderGain[1] * ratio;
471 else if(j == 4) gain = conf->HFOrderGain[2] * ratio;
472 else if(j == 9) gain = conf->HFOrderGain[3] * ratio;
473 if((conf->ChanMask&(1<<j)))
474 dec->Matrix.Dual[chan][FB_HighFreq][j] = conf->HFMatrix[i][k++] /
475 coeff_scale[j] * gain *
476 distgain[i];
478 for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
480 if(j == 0) gain = conf->LFOrderGain[0] / ratio;
481 else if(j == 1) gain = conf->LFOrderGain[1] / ratio;
482 else if(j == 4) gain = conf->LFOrderGain[2] / ratio;
483 else if(j == 9) gain = conf->LFOrderGain[3] / ratio;
484 if((conf->ChanMask&(1<<j)))
485 dec->Matrix.Dual[chan][FB_LowFreq][j] = conf->LFMatrix[i][k++] /
486 coeff_scale[j] * gain *
487 distgain[i];
495 void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint SamplesToDo)
497 ALuint chan, i;
499 if(dec->DualBand)
501 for(i = 0;i < dec->NumChannels;i++)
502 bandsplit_process(&dec->XOver[i], dec->SamplesHF[i], dec->SamplesLF[i],
503 InSamples[i], SamplesToDo);
505 for(chan = 0;chan < OutChannels;chan++)
507 if(!dec->Enabled[chan])
508 continue;
510 memset(dec->ChannelMix, 0, SamplesToDo*sizeof(ALfloat));
511 MixMatrixRow(dec->ChannelMix, dec->Matrix.Dual[chan][FB_HighFreq],
512 SAFE_CONST(ALfloatBUFFERSIZE*,dec->SamplesHF), dec->NumChannels, 0,
513 SamplesToDo
515 MixMatrixRow(dec->ChannelMix, dec->Matrix.Dual[chan][FB_LowFreq],
516 SAFE_CONST(ALfloatBUFFERSIZE*,dec->SamplesLF), dec->NumChannels, 0,
517 SamplesToDo
520 if(dec->Delay[chan].Length > 0)
522 const ALuint base = dec->Delay[chan].Length;
523 if(SamplesToDo >= base)
525 for(i = 0;i < base;i++)
526 OutBuffer[chan][i] += dec->Delay[chan].Buffer[i];
527 for(;i < SamplesToDo;i++)
528 OutBuffer[chan][i] += dec->ChannelMix[i-base];
529 memcpy(dec->Delay[chan].Buffer, &dec->ChannelMix[SamplesToDo-base],
530 base*sizeof(ALfloat));
532 else
534 for(i = 0;i < SamplesToDo;i++)
535 OutBuffer[chan][i] += dec->Delay[chan].Buffer[i];
536 memmove(dec->Delay[chan].Buffer, dec->Delay[chan].Buffer+SamplesToDo,
537 base - SamplesToDo);
538 memcpy(dec->Delay[chan].Buffer+base-SamplesToDo, dec->ChannelMix,
539 SamplesToDo*sizeof(ALfloat));
542 else for(i = 0;i < SamplesToDo;i++)
543 OutBuffer[chan][i] += dec->ChannelMix[i];
546 else
548 for(chan = 0;chan < OutChannels;chan++)
550 if(!dec->Enabled[chan])
551 continue;
553 memset(dec->ChannelMix, 0, SamplesToDo*sizeof(ALfloat));
554 MixMatrixRow(dec->ChannelMix, dec->Matrix.Single[chan], InSamples,
555 dec->NumChannels, 0, SamplesToDo);
557 if(dec->Delay[chan].Length > 0)
559 const ALuint base = dec->Delay[chan].Length;
560 if(SamplesToDo >= base)
562 for(i = 0;i < base;i++)
563 OutBuffer[chan][i] += dec->Delay[chan].Buffer[i];
564 for(;i < SamplesToDo;i++)
565 OutBuffer[chan][i] += dec->ChannelMix[i-base];
566 memcpy(dec->Delay[chan].Buffer, &dec->ChannelMix[SamplesToDo-base],
567 base*sizeof(ALfloat));
569 else
571 for(i = 0;i < SamplesToDo;i++)
572 OutBuffer[chan][i] += dec->Delay[chan].Buffer[i];
573 memmove(dec->Delay[chan].Buffer, dec->Delay[chan].Buffer+SamplesToDo,
574 base - SamplesToDo);
575 memcpy(dec->Delay[chan].Buffer+base-SamplesToDo, dec->ChannelMix,
576 SamplesToDo*sizeof(ALfloat));
579 else for(i = 0;i < SamplesToDo;i++)
580 OutBuffer[chan][i] += dec->ChannelMix[i];
586 void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint InChannels, ALuint SamplesToDo)
588 ALuint i, j;
590 /* This up-sampler is very simplistic. It essentially decodes the first-
591 * order content to a square channel array (or cube if height is desired),
592 * then encodes those points onto the higher order soundfield. The decoder
593 * and encoder matrices have been combined to directly convert each input
594 * channel to the output, without the need for storing the virtual channel
595 * array.
597 for(i = 0;i < InChannels;i++)
599 /* First, split the first-order components into low and high frequency
600 * bands.
602 bandsplit_process(&dec->UpSampler.XOver[i],
603 dec->Samples[FB_HighFreq], dec->Samples[FB_LowFreq],
604 InSamples[i], SamplesToDo
607 /* Now write each band to the output. */
608 for(j = 0;j < dec->NumChannels;j++)
609 MixMatrixRow(OutBuffer[j], dec->UpSampler.Gains[i][j],
610 SAFE_CONST(ALfloatBUFFERSIZE*,dec->Samples), FB_Max, 0,
611 SamplesToDo
617 typedef struct AmbiUpsampler {
618 alignas(16) ALfloat Samples[FB_Max][BUFFERSIZE];
620 BandSplitter XOver[4];
622 ALfloat Gains[4][MAX_OUTPUT_CHANNELS][FB_Max];
623 } AmbiUpsampler;
625 AmbiUpsampler *ambiup_alloc()
627 alcall_once(&bformatdec_inited, init_bformatdec);
628 return al_calloc(16, sizeof(AmbiUpsampler));
631 void ambiup_free(struct AmbiUpsampler *ambiup)
633 al_free(ambiup);
636 void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device)
638 ALfloat gains[8][MAX_OUTPUT_CHANNELS];
639 ALfloat ratio;
640 ALuint i;
642 ratio = 400.0f / (ALfloat)device->Frequency;
643 for(i = 0;i < 4;i++)
644 bandsplit_init(&ambiup->XOver[i], ratio);
646 for(i = 0;i < COUNTOF(Ambi3DEncoderT);i++)
647 ComputePanningGains(device->Dry, Ambi3DEncoderT[i], 1.0f, gains[i]);
649 memset(ambiup->Gains, 0, sizeof(ambiup->Gains));
650 GenUpsamplerGains(SAFE_CONST(ALfloatMAX_AMBI_COEFFS*,gains),
651 Ambi3DDecoder, COUNTOF(Ambi3DDecoder),
652 ambiup->Gains, device->Dry.NumChannels);
655 void ambiup_process(struct AmbiUpsampler *ambiup, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint SamplesToDo)
657 ALuint i, j;
659 for(i = 0;i < 4;i++)
661 bandsplit_process(&ambiup->XOver[i],
662 ambiup->Samples[FB_HighFreq], ambiup->Samples[FB_LowFreq],
663 InSamples[i], SamplesToDo
666 for(j = 0;j < OutChannels;j++)
667 MixMatrixRow(OutBuffer[j], ambiup->Gains[i][j],
668 SAFE_CONST(ALfloatBUFFERSIZE*,ambiup->Samples), FB_Max, 0,
669 SamplesToDo