Repack the ambisonic dual-band decoder matrices
[openal-soft.git] / Alc / bformatdec.c
blob49532cc5c6963b39997c02aa9e9f081b192f61ed
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 typedef struct BandSplitter {
14 ALfloat coeff;
15 ALfloat lp_z1;
16 ALfloat lp_z2;
17 ALfloat hp_z1;
18 } BandSplitter;
20 static void bandsplit_init(BandSplitter *splitter, ALfloat freq_mult)
22 ALfloat w = freq_mult * F_TAU;
23 ALfloat cw = cosf(w);
24 if(cw > FLT_EPSILON)
25 splitter->coeff = (sinf(w) - 1.0f) / cw;
26 else
27 splitter->coeff = cw * -0.5f;
29 splitter->lp_z1 = 0.0f;
30 splitter->lp_z2 = 0.0f;
31 splitter->hp_z1 = 0.0f;
34 static 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 static const ALfloat SquareMatrix[4][FB_Max][MAX_AMBI_COEFFS] = {
126 { { 0.353553f, 0.204094f, 0.0f, 0.204094f }, { 0.25f, 0.204094f, 0.0f, 0.204094f } },
127 { { 0.353553f, -0.204094f, 0.0f, 0.204094f }, { 0.25f, -0.204094f, 0.0f, 0.204094f } },
128 { { 0.353553f, 0.204094f, 0.0f, -0.204094f }, { 0.25f, 0.204094f, 0.0f, -0.204094f } },
129 { { 0.353553f, -0.204094f, 0.0f, -0.204094f }, { 0.25f, -0.204094f, 0.0f, -0.204094f } },
131 static ALfloat SquareEncoder[4][MAX_AMBI_COEFFS];
133 static const ALfloat CubeMatrix[8][FB_Max][MAX_AMBI_COEFFS] = {
134 { { 0.25f, 0.14425f, 0.14425f, 0.14425f }, { 0.125f, 0.125f, 0.125f, 0.125f } },
135 { { 0.25f, -0.14425f, 0.14425f, 0.14425f }, { 0.125f, -0.125f, 0.125f, 0.125f } },
136 { { 0.25f, 0.14425f, 0.14425f, -0.14425f }, { 0.125f, 0.125f, 0.125f, -0.125f } },
137 { { 0.25f, -0.14425f, 0.14425f, -0.14425f }, { 0.125f, -0.125f, 0.125f, -0.125f } },
138 { { 0.25f, 0.14425f, -0.14425f, 0.14425f }, { 0.125f, 0.125f, -0.125f, 0.125f } },
139 { { 0.25f, -0.14425f, -0.14425f, 0.14425f }, { 0.125f, -0.125f, -0.125f, 0.125f } },
140 { { 0.25f, 0.14425f, -0.14425f, -0.14425f }, { 0.125f, 0.125f, -0.125f, -0.125f } },
141 { { 0.25f, -0.14425f, -0.14425f, -0.14425f }, { 0.125f, -0.125f, -0.125f, -0.125f } },
143 static ALfloat CubeEncoder[8][MAX_AMBI_COEFFS];
146 static inline MatrixMixerFunc SelectMixer(void)
148 #ifdef HAVE_SSE
149 if((CPUCapFlags&CPU_CAP_SSE))
150 return MixRow_SSE;
151 #endif
152 #ifdef HAVE_NEON
153 if((CPUCapFlags&CPU_CAP_NEON))
154 return MixRow_Neon;
155 #endif
156 return MixRow_C;
159 static MatrixMixerFunc MixMatrixRow = MixRow_C;
162 static alonce_flag bformatdec_inited = AL_ONCE_FLAG_INIT;
164 static void init_bformatdec(void)
166 ALuint i, j;
168 MixMatrixRow = SelectMixer();
170 CalcXYZCoeffs(-0.577350269f, 0.577350269f, -0.577350269f, 0.0f, CubeEncoder[0]);
171 CalcXYZCoeffs( 0.577350269f, 0.577350269f, -0.577350269f, 0.0f, CubeEncoder[1]);
172 CalcXYZCoeffs(-0.577350269f, 0.577350269f, 0.577350269f, 0.0f, CubeEncoder[2]);
173 CalcXYZCoeffs( 0.577350269f, 0.577350269f, 0.577350269f, 0.0f, CubeEncoder[3]);
174 CalcXYZCoeffs(-0.577350269f, -0.577350269f, -0.577350269f, 0.0f, CubeEncoder[4]);
175 CalcXYZCoeffs( 0.577350269f, -0.577350269f, -0.577350269f, 0.0f, CubeEncoder[5]);
176 CalcXYZCoeffs(-0.577350269f, -0.577350269f, 0.577350269f, 0.0f, CubeEncoder[6]);
177 CalcXYZCoeffs( 0.577350269f, -0.577350269f, 0.577350269f, 0.0f, CubeEncoder[7]);
179 CalcXYZCoeffs(-0.707106781f, 0.0f, -0.707106781f, 0.0f, SquareEncoder[0]);
180 CalcXYZCoeffs( 0.707106781f, 0.0f, -0.707106781f, 0.0f, SquareEncoder[1]);
181 CalcXYZCoeffs(-0.707106781f, 0.0f, 0.707106781f, 0.0f, SquareEncoder[2]);
182 CalcXYZCoeffs( 0.707106781f, 0.0f, 0.707106781f, 0.0f, SquareEncoder[3]);
184 for(i = 0;i < 4;i++)
186 /* Remove the skipped height-related coefficients for 2D rendering. */
187 SquareEncoder[i][2] = SquareEncoder[i][3];
188 SquareEncoder[i][3] = SquareEncoder[i][4];
189 SquareEncoder[i][4] = SquareEncoder[i][8];
190 SquareEncoder[i][5] = SquareEncoder[i][9];
191 SquareEncoder[i][6] = SquareEncoder[i][15];
192 for(j = 7;j < MAX_AMBI_COEFFS;j++)
193 SquareEncoder[i][j] = 0.0f;
198 #define MAX_DELAY_LENGTH 128
200 /* NOTE: BandSplitter filters are unused with single-band decoding */
201 typedef struct BFormatDec {
202 ALboolean Enabled[MAX_OUTPUT_CHANNELS];
204 union {
205 alignas(16) ALfloat Dual[MAX_OUTPUT_CHANNELS][FB_Max][MAX_AMBI_COEFFS];
206 alignas(16) ALfloat Single[MAX_OUTPUT_CHANNELS][MAX_AMBI_COEFFS];
207 } Matrix;
209 BandSplitter XOver[MAX_AMBI_COEFFS];
211 ALfloat (*Samples)[BUFFERSIZE];
212 /* These two alias into Samples */
213 ALfloat (*SamplesHF)[BUFFERSIZE];
214 ALfloat (*SamplesLF)[BUFFERSIZE];
216 alignas(16) ALfloat ChannelMix[BUFFERSIZE];
218 struct {
219 alignas(16) ALfloat Buffer[MAX_DELAY_LENGTH];
220 ALuint Length; /* Valid range is [0...MAX_DELAY_LENGTH). */
221 } Delay[MAX_OUTPUT_CHANNELS];
223 struct {
224 BandSplitter XOver[4];
226 const ALfloat (*restrict Matrix)[FB_Max][MAX_AMBI_COEFFS];
227 const ALfloat (*restrict Encoder)[MAX_AMBI_COEFFS];
228 ALuint NumChannels;
229 } UpSampler;
231 ALuint NumChannels;
232 ALboolean DualBand;
233 ALboolean Periphonic;
234 } BFormatDec;
236 BFormatDec *bformatdec_alloc()
238 alcall_once(&bformatdec_inited, init_bformatdec);
239 return al_calloc(16, sizeof(BFormatDec));
242 void bformatdec_free(BFormatDec *dec)
244 if(dec)
246 al_free(dec->Samples);
247 dec->Samples = NULL;
248 dec->SamplesHF = NULL;
249 dec->SamplesLF = NULL;
251 memset(dec, 0, sizeof(*dec));
252 al_free(dec);
256 int bformatdec_getOrder(const struct BFormatDec *dec)
258 if(dec->Periphonic)
260 if(dec->NumChannels > 9) return 3;
261 if(dec->NumChannels > 4) return 2;
262 if(dec->NumChannels > 1) return 1;
264 else
266 if(dec->NumChannels > 5) return 3;
267 if(dec->NumChannels > 3) return 2;
268 if(dec->NumChannels > 1) return 1;
270 return 0;
273 void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALuint chancount, ALuint srate, const ALuint chanmap[MAX_OUTPUT_CHANNELS], int flags)
275 static const ALuint map2DTo3D[7] = {
276 0, 1, 3, 4, 8, 9, 15
278 const ALfloat *coeff_scale = UnitScale;
279 ALfloat distgain[MAX_OUTPUT_CHANNELS];
280 ALfloat maxdist, ratio;
281 ALuint i;
283 al_free(dec->Samples);
284 dec->Samples = NULL;
285 dec->SamplesHF = NULL;
286 dec->SamplesLF = NULL;
288 dec->NumChannels = chancount;
289 dec->Samples = al_calloc(16, dec->NumChannels*2 * sizeof(dec->Samples[0]));
290 dec->SamplesHF = dec->Samples;
291 dec->SamplesLF = dec->SamplesHF + dec->NumChannels;
293 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
294 dec->Enabled[i] = AL_FALSE;
295 for(i = 0;i < conf->NumSpeakers;i++)
296 dec->Enabled[chanmap[i]] = AL_TRUE;
298 if(conf->CoeffScale == ADS_SN3D)
299 coeff_scale = SN3D2N3DScale;
300 else if(conf->CoeffScale == ADS_FuMa)
301 coeff_scale = FuMa2N3DScale;
303 ratio = 400.0f / (ALfloat)srate;
304 for(i = 0;i < 4;i++)
305 bandsplit_init(&dec->UpSampler.XOver[i], ratio);
306 if((conf->ChanMask&AMBI_PERIPHONIC_MASK))
308 dec->UpSampler.Matrix = CubeMatrix;
309 dec->UpSampler.Encoder = (const ALfloat(*)[MAX_AMBI_COEFFS])CubeEncoder;
310 dec->UpSampler.NumChannels = 8;
311 dec->Periphonic = AL_TRUE;
313 else
315 dec->UpSampler.Matrix = SquareMatrix;
316 dec->UpSampler.Encoder = (const ALfloat(*)[MAX_AMBI_COEFFS])SquareEncoder;
317 dec->UpSampler.NumChannels = 4;
318 dec->Periphonic = AL_FALSE;
321 maxdist = 0.0f;
322 for(i = 0;i < conf->NumSpeakers;i++)
324 maxdist = maxf(maxdist, conf->Speakers[i].Distance);
325 distgain[i] = 1.0f;
328 memset(dec->Delay, 0, sizeof(dec->Delay));
329 if((flags&BFDF_DistanceComp) && maxdist > 0.0f)
331 for(i = 0;i < conf->NumSpeakers;i++)
333 ALuint chan = chanmap[i];
334 ALfloat delay;
336 /* Distance compensation only delays in steps of the sample rate.
337 * This is a bit less accurate since the delay time falls to the
338 * nearest sample time, but it's far simpler as it doesn't have to
339 * deal with phase offsets. This means at 48khz, for instance, the
340 * distance delay will be in steps of about 7 millimeters.
342 delay = floorf((maxdist-conf->Speakers[i].Distance) / SPEEDOFSOUNDMETRESPERSEC *
343 (ALfloat)srate + 0.5f);
344 if(delay >= (ALfloat)MAX_DELAY_LENGTH)
345 ERR("Delay for speaker \"%s\" exceeds buffer length (%f >= %u)\n",
346 al_string_get_cstr(conf->Speakers[i].Name), delay, MAX_DELAY_LENGTH);
348 dec->Delay[chan].Length = (ALuint)clampf(delay, 0.0f, (ALfloat)(MAX_DELAY_LENGTH-1));
349 distgain[i] = conf->Speakers[i].Distance / maxdist;
350 TRACE("Channel %u \"%s\" distance compensation: %u samples, %f gain\n", chan,
351 al_string_get_cstr(conf->Speakers[i].Name), dec->Delay[chan].Length, distgain[i]
356 memset(&dec->Matrix, 0, sizeof(dec->Matrix));
357 if(conf->FreqBands == 1)
359 dec->DualBand = AL_FALSE;
360 for(i = 0;i < conf->NumSpeakers;i++)
362 ALuint chan = chanmap[i];
363 ALfloat gain;
364 ALuint j, k;
366 if(!dec->Periphonic)
368 for(j = 0,k = 0;j < 7;j++)
370 ALuint l = map2DTo3D[j];
371 if(j == 0) gain = conf->HFOrderGain[0];
372 else if(j == 1) gain = conf->HFOrderGain[1];
373 else if(j == 3) gain = conf->HFOrderGain[2];
374 else if(j == 5) gain = conf->HFOrderGain[3];
375 if((conf->ChanMask&(1<<l)))
376 dec->Matrix.Single[chan][j] = conf->HFMatrix[i][k++] / coeff_scale[l] *
377 gain * distgain[i];
380 else
382 for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
384 if(j == 0) gain = conf->HFOrderGain[0];
385 else if(j == 1) gain = conf->HFOrderGain[1];
386 else if(j == 4) gain = conf->HFOrderGain[2];
387 else if(j == 9) gain = conf->HFOrderGain[3];
388 if((conf->ChanMask&(1<<j)))
389 dec->Matrix.Single[chan][j] = conf->HFMatrix[i][k++] / coeff_scale[j] *
390 gain * distgain[i];
395 else
397 dec->DualBand = AL_TRUE;
399 ratio = conf->XOverFreq / (ALfloat)srate;
400 for(i = 0;i < MAX_AMBI_COEFFS;i++)
401 bandsplit_init(&dec->XOver[i], ratio);
403 ratio = powf(10.0f, conf->XOverRatio / 40.0f);
404 for(i = 0;i < conf->NumSpeakers;i++)
406 ALuint chan = chanmap[i];
407 ALfloat gain;
408 ALuint j, k;
410 if(!dec->Periphonic)
412 for(j = 0,k = 0;j < 7;j++)
414 ALuint l = map2DTo3D[j];
415 if(j == 0) gain = conf->HFOrderGain[0] * ratio;
416 else if(j == 1) gain = conf->HFOrderGain[1] * ratio;
417 else if(j == 3) gain = conf->HFOrderGain[2] * ratio;
418 else if(j == 5) gain = conf->HFOrderGain[3] * ratio;
419 if((conf->ChanMask&(1<<l)))
420 dec->Matrix.Dual[chan][FB_HighFreq][j] = conf->HFMatrix[i][k++] /
421 coeff_scale[l] * gain *
422 distgain[i];
424 for(j = 0,k = 0;j < 7;j++)
426 ALuint l = map2DTo3D[j];
427 if(j == 0) gain = conf->LFOrderGain[0] / ratio;
428 else if(j == 1) gain = conf->LFOrderGain[1] / ratio;
429 else if(j == 3) gain = conf->LFOrderGain[2] / ratio;
430 else if(j == 5) gain = conf->LFOrderGain[3] / ratio;
431 if((conf->ChanMask&(1<<l)))
432 dec->Matrix.Dual[chan][FB_LowFreq][j] = conf->LFMatrix[i][k++] /
433 coeff_scale[l] * gain *
434 distgain[i];
437 else
439 for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
441 if(j == 0) gain = conf->HFOrderGain[0] * ratio;
442 else if(j == 1) gain = conf->HFOrderGain[1] * ratio;
443 else if(j == 4) gain = conf->HFOrderGain[2] * ratio;
444 else if(j == 9) gain = conf->HFOrderGain[3] * ratio;
445 if((conf->ChanMask&(1<<j)))
446 dec->Matrix.Dual[chan][FB_HighFreq][j] = conf->HFMatrix[i][k++] /
447 coeff_scale[j] * gain *
448 distgain[i];
450 for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
452 if(j == 0) gain = conf->LFOrderGain[0] / ratio;
453 else if(j == 1) gain = conf->LFOrderGain[1] / ratio;
454 else if(j == 4) gain = conf->LFOrderGain[2] / ratio;
455 else if(j == 9) gain = conf->LFOrderGain[3] / ratio;
456 if((conf->ChanMask&(1<<j)))
457 dec->Matrix.Dual[chan][FB_LowFreq][j] = conf->LFMatrix[i][k++] /
458 coeff_scale[j] * gain *
459 distgain[i];
467 void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint OutChannels, ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint SamplesToDo)
469 ALuint chan, i;
471 if(dec->DualBand)
473 for(i = 0;i < dec->NumChannels;i++)
474 bandsplit_process(&dec->XOver[i], dec->SamplesHF[i], dec->SamplesLF[i],
475 InSamples[i], SamplesToDo);
477 for(chan = 0;chan < OutChannels;chan++)
479 if(!dec->Enabled[chan])
480 continue;
482 memset(dec->ChannelMix, 0, SamplesToDo*sizeof(ALfloat));
483 MixMatrixRow(dec->ChannelMix, dec->Matrix.Dual[chan][FB_HighFreq],
484 dec->SamplesHF, dec->NumChannels, SamplesToDo
486 MixMatrixRow(dec->ChannelMix, dec->Matrix.Dual[chan][FB_LowFreq],
487 dec->SamplesLF, dec->NumChannels, SamplesToDo
490 if(dec->Delay[chan].Length > 0)
492 const ALuint base = dec->Delay[chan].Length;
493 if(SamplesToDo >= base)
495 for(i = 0;i < base;i++)
496 OutBuffer[chan][i] += dec->Delay[chan].Buffer[i];
497 for(;i < SamplesToDo;i++)
498 OutBuffer[chan][i] += dec->ChannelMix[i-base];
499 memcpy(dec->Delay[chan].Buffer, &dec->ChannelMix[SamplesToDo-base],
500 base*sizeof(ALfloat));
502 else
504 for(i = 0;i < SamplesToDo;i++)
505 OutBuffer[chan][i] += dec->Delay[chan].Buffer[i];
506 memmove(dec->Delay[chan].Buffer, dec->Delay[chan].Buffer+SamplesToDo,
507 base - SamplesToDo);
508 memcpy(dec->Delay[chan].Buffer+base-SamplesToDo, dec->ChannelMix,
509 SamplesToDo*sizeof(ALfloat));
512 else for(i = 0;i < SamplesToDo;i++)
513 OutBuffer[chan][i] += dec->ChannelMix[i];
516 else
518 for(chan = 0;chan < OutChannels;chan++)
520 if(!dec->Enabled[chan])
521 continue;
523 memset(dec->ChannelMix, 0, SamplesToDo*sizeof(ALfloat));
524 MixMatrixRow(dec->ChannelMix, dec->Matrix.Single[chan], InSamples,
525 dec->NumChannels, SamplesToDo);
527 if(dec->Delay[chan].Length > 0)
529 const ALuint base = dec->Delay[chan].Length;
530 if(SamplesToDo >= base)
532 for(i = 0;i < base;i++)
533 OutBuffer[chan][i] += dec->Delay[chan].Buffer[i];
534 for(;i < SamplesToDo;i++)
535 OutBuffer[chan][i] += dec->ChannelMix[i-base];
536 memcpy(dec->Delay[chan].Buffer, &dec->ChannelMix[SamplesToDo-base],
537 base*sizeof(ALfloat));
539 else
541 for(i = 0;i < SamplesToDo;i++)
542 OutBuffer[chan][i] += dec->Delay[chan].Buffer[i];
543 memmove(dec->Delay[chan].Buffer, dec->Delay[chan].Buffer+SamplesToDo,
544 base - SamplesToDo);
545 memcpy(dec->Delay[chan].Buffer+base-SamplesToDo, dec->ChannelMix,
546 SamplesToDo*sizeof(ALfloat));
549 else for(i = 0;i < SamplesToDo;i++)
550 OutBuffer[chan][i] += dec->ChannelMix[i];
556 void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint InChannels, ALuint SamplesToDo)
558 ALuint i, j, k;
560 /* First, split the first-order components into low and high frequency
561 * bands. This assumes SamplesHF and SamplesLF have enough space for first-
562 * order content (to which, this up-sampler is only used with second-order
563 * or higher decoding, so it will).
565 for(i = 0;i < InChannels;i++)
566 bandsplit_process(&dec->UpSampler.XOver[i], dec->SamplesHF[i], dec->SamplesLF[i],
567 InSamples[i], SamplesToDo);
569 /* This up-sampler is very simplistic. It essentially decodes the first-
570 * order content to a square channel array (or cube if height is desired),
571 * then encodes those points onto the higher order soundfield.
573 for(k = 0;k < dec->UpSampler.NumChannels;k++)
575 memset(dec->ChannelMix, 0, SamplesToDo*sizeof(ALfloat));
576 MixMatrixRow(dec->ChannelMix, dec->UpSampler.Matrix[k][FB_HighFreq],
577 dec->SamplesHF, InChannels, SamplesToDo);
578 MixMatrixRow(dec->ChannelMix, dec->UpSampler.Matrix[k][FB_LowFreq],
579 dec->SamplesLF, InChannels, SamplesToDo);
581 for(j = 0;j < dec->NumChannels;j++)
583 ALfloat gain = dec->UpSampler.Encoder[k][j];
584 if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
585 continue;
586 for(i = 0;i < SamplesToDo;i++)
587 OutBuffer[j][i] += dec->ChannelMix[i] * gain;